这个PInvoke代码是否正确可靠?

HCL*_*HCL 21 .net c# pinvoke .net-4.0 alternate-data-stream

这个问题中,我搜索了一个解锁文件的简单解决方案.感谢所有的评论和回答,我找到了PInvoking的简单解决方案DeleteFile.

它工作,但因为我从来没有通过PInvoke(Win32)使用文件操作,我不知道是否有一些陷阱或是否有另一种方法来调用DeleteFile删除文件的备用流.

我还不知道的是,如果我必须在try/catch中包装调用,或者仅仅查看布尔结果就足够了.在我的测试中,没有提出异常,但我不知道在现实世界中会发生什么.

public class FileUnblocker {

    [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool DeleteFile(string name );

    public bool Unblock(string fileName) {
        return DeleteFile(fileName+ ":Zone.Identifier");
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码看起来可靠吗?

更新
我发布了一个不完整的方法(unblock方法没有将"Zone.Identifier"文字连接到文件名).我现在纠正了这个,抱歉.

Dav*_*nan 18

调用本机方法永远不会引发异常.如果文件删除失败,无论出于何种原因,调用DeleteFile返回false.

你的P/Invoke代码很好.您正确使用Unicode字符,设置SetLastErrortrue和参数编组是正确的.要检查错误,请查找布尔值返回值DeleteFile.如果它为假(即调用失败),则调用Marshal.GetLastWin32Error以找出Win32错误代码.

功能失败的最明显原因是:

  1. 该文件不存在.
  2. 备用流不存在.
  3. 该进程没有足够的权限来删除备用流.

对于1和2,ERROR_FILE_NOT_FOUND将返回错误代码.对于3,您将获得错误代码ERROR_ACCESS_DENIED.


小智 6

我对代码做了一个小改进.您现在可以将启动路径传递给UnblockPath()函数,它将自动取消阻止可执行文件的所有文件和子目录文件.它可以进一步细化,只搜索.exe,.dll等.

[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteFile(string name);

public static void UnblockPath(string path)
{
    string[] files = System.IO.Directory.GetFiles(path);
    string[] dirs = System.IO.Directory.GetDirectories(path);

    foreach (string file in files)
    {
        UnblockFile(file);
    }

    foreach (string dir in dirs)
    {
        UnblockPath(dir);
    }

}

public static bool UnblockFile(string fileName)
{
    return DeleteFile(fileName + ":Zone.Identifier");
}
Run Code Online (Sandbox Code Playgroud)