尝试从我的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具有相同的效果。
虽然我没有检查这是否属实,但对于有类似要求的其他人来说,它仍然是一个选择。
答案 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。