如何用null参数调用/调用SetFileTime?

时间:2012-07-04 13:19:59

标签: c# .net file-io pinvoke

尝试从我的C#程序P / Invoke SetFileTime function,我使用以下签名:

[DllImport(@"kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetFileTime(
    IntPtr hFile,
    ref long lpCreationTime,
    ref long lpLastAccessTime,
    ref long lpLastWriteTime);

文档说明了以下非托管签名:

BOOL WINAPI SetFileTime(
  __in      HANDLE hFile,
  __in_opt  const FILETIME *lpCreationTime,
  __in_opt  const FILETIME *lpLastAccessTime,
  __in_opt  const FILETIME *lpLastWriteTime
);

对于第2,第3和第4个参数,它们可以是可选的:

  

如果应用程序不需要更改此信息,则此参数可以为NULL。

这正是我想要做的:只传递三个日期时间值中的一个,并将其他值设置为null

我完全迷失了如何用P / Invoke签名来表达这一点。

因此我的问题是:

能够将null传递给SetFileTime函数参数的正确P / Invoke签名(或正确的调用方式)是什么?

修改1:

由于FileInfo class已经提供了用于设置文件时间的可写属性,因此您可能会问,为什么我自己这样做而不是使用该类。

原因是我计划在我的Long Paths库中使用此函数,该库用于克服MAX_PATH限制,因此无法使用标准.NET函数。

因此,遗憾的是,使用FileInfo类不是一种选择。

编辑2:

我使用Hans建议的解决方案解决了这个问题。之后,我发现a user-contributed comment below the function说:

  

此外,为其中一个参数指定零值与指定NULL具有相同的效果。

虽然我没有检查这是否属实,但对于有类似要求的其他人来说,它仍然是一个选择。

1 个答案:

答案 0 :(得分:3)

您无法使用C#中的 ref 关键字对其进行建模,它始终在运行时生成非空指针。您实际上必须声明它long*,这需要使用unsafe关键字。使用&local-var语法传递参数或使用null

避免使用不安全的一个可能技巧是使用不同的名称声明此方法的3个版本,使用DllImport的EntryPoint属性将它们全部映射到SetFileTime()。指定您不想设置为IntPtr的那些,这样您就可以传递IntPtr.Zero,即您想要设置为ref long的那个。例如:

[DllImport("kernel32.dll", SetLastError = true, EntryPoint="SetFileTime", ExactSpelling=true)]
internal static extern bool SetFileCreateTime(
    IntPtr hFile,
    ref long lpCreationTime,
    IntPtr lpLastAccessTimeUnused,
    IntPtr lpLastWriteTimeUnused);

重复SetFileAccessTime和SetFileWriteTime。