C# 这个PInvoke代码正确可靠吗?
在中,我搜索了一个简单的解决方案来解除阻止文件。 感谢所有的评论和回答,我通过PInvokingC# 这个PInvoke代码正确可靠吗?,c#,.net,.net-4.0,pinvoke,alternate-data-stream,C#,.net,.net 4.0,Pinvoke,Alternate Data Stream,在中,我搜索了一个简单的解决方案来解除阻止文件。 感谢所有的评论和回答,我通过PInvokingDeleteFile找到了一个简单的解决方案 它可以工作,但因为我从未通过PInvoke(Win32)使用过文件操作,我不知道是否存在一些缺陷,或者是否有另一种方法调用DeleteFile来删除文件的备用流 我也不知道我是否必须用try/catch来包装调用,或者仅仅查看布尔结果就足够了。在我的测试中,没有出现异常,但我不知道现实世界会发生什么 public class FileUnblocker {
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");
}
}
这个代码看起来可靠吗
更新我发布了一个不完整的方法(unblock方法没有将“Zone.Identifier”文本连接到文件名)。对不起,我现在已经更正了。调用本机方法永远不会引发异常。如果文件删除失败,无论出于何种原因,对
DeleteFile
的调用将返回false
您的p/Invoke代码很好。您正确地使用了Unicode字符,将SetLastError
设置为true
,并且参数编组正确。要检查错误,请从DeleteFile
中查找布尔返回值。如果为false(即调用失败),则调用查找Win32错误代码
功能失效的最明显原因是:
对于1和2,将返回错误代码。对于3,您将得到一个错误代码。我对代码做了一些改进。现在,您可以将启动路径传递给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");
}
对于那些通过并盲目否决答案的人:请有礼貌地解释为什么答案是错误的。@克里斯,实际上我想知道的是,是谁否决了两个答案:1)只不过是给了问题中的答案同等的P/Invoke签名,在一个例子中,使用Ansi字符串和2)并没有以任何方式解决这个问题。我做到了,你永远也不会明白我的意思。哈哈哈。>:)StackOverflow不是代码审阅站点。CodeReview.SE是。@SamAxe Code Review不是一个审查代码可靠性的网站。StackOverflow是。+1抱歉,我太匆忙了,没有发布代码,我忘记了在Unblock方法中添加流标识符。我已经编辑了我的帖子。对不起,一般来说,我尽量不发布糟糕的问题,浪费人们的时间。下次我会更加小心。@HCL是的,我有点被甩了。不过,我想我现在已经涵盖了所有的基础!这与此相反-锁定文件。这与问题无关,但仍然有用,谢谢。
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal class Zone
{
public static void WriteAlternateStream(string path, string text)
{
const int GENERIC_WRITE = 1073741824;
const int FILE_SHARE_WRITE = 2;
const int OPEN_ALWAYS = 4;
var stream = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_ALWAYS, 0, IntPtr.Zero);
using (FileStream fs = new FileStream(stream, FileAccess.Write))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(text);
}
}
}
public static void Id()
{
var x = Application.ExecutablePath + ":Zone.Identifier";
WriteAlternateStream(x, "[ZoneTransfer]\r\nZoneId=3");
}
# region Imports
[DllImport("kernel32.dll", EntryPoint = "CreateFileW")]
public static extern System.IntPtr CreateFileW(
[InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
[InAttribute()] IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
[InAttribute()] IntPtr hTemplateFile
);
#endregion
}