C# 如何获取Windows中所有打开的命名管道的列表并避免可能的异常?

C# 如何获取Windows中所有打开的命名管道的列表并避免可能的异常?,c#,.net,named-pipes,C#,.net,Named Pipes,在理想情况下,获取命名管道的列表非常简单,可以在以下位置找到: 但是提到了解决方案 var namedPipes = Directory.GetFiles(@"\\.\pipe\"); 有时会有不可预测的结果。上面的链接中提到了其中一个(路径异常中的无效字符)。今天我遇到了我自己的例外: ArgumentException“第二个路径片段不能是驱动器或UNC名称。参数名称:path2” 问题是在.net中是否有任何真正有效的解决方案来获取所有打开的命名管道的列表?谢谢我深入研究了目录类源代码

在理想情况下,获取命名管道的列表非常简单,可以在以下位置找到:

但是提到了解决方案

var namedPipes = Directory.GetFiles(@"\\.\pipe\");
有时会有不可预测的结果。上面的链接中提到了其中一个(路径异常中的无效字符)。今天我遇到了我自己的例外:

ArgumentException“第二个路径片段不能是驱动器或UNC名称。参数名称:path2”


问题是在.net中是否有任何真正有效的解决方案来获取所有打开的命名管道的列表?谢谢

我深入研究了目录类源代码并找到了灵感。下面是一个有效的解决方案,它为您提供了所有打开的命名管道的列表。我的结果不包含\\.\pipe\前缀,因为它可以在Directory.GetFiles的结果中看到。我在WinXp SP3、Win 7、Win 8.1上测试了我的解决方案

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct WIN32_FIND_DATA
    {
        public uint dwFileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public string cAlternateFileName;
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);


    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA
       lpFindFileData);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool FindClose(IntPtr hFindFile);

    private static void Main(string[] args)
    {
        var namedPipes = new List<string>();
        WIN32_FIND_DATA lpFindFileData;

        var ptr = FindFirstFile(@"\\.\pipe\*", out lpFindFileData);
        namedPipes.Add(lpFindFileData.cFileName);
        while (FindNextFile(ptr, out lpFindFileData))
        {
            namedPipes.Add(lpFindFileData.cFileName);
        }
        FindClose(ptr);

        namedPipes.Sort();

        foreach (var v in namedPipes)
            Console.WriteLine(v);

        Console.ReadLine();
     }
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
结构WIN32查找数据
{
公共uint-dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
公共单位净收益率高;
公共部门和公共部门;
公共单位数据保留0;
保留的公共单位1;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=260)]
公共字符串cFileName;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=14)]
公共字符串cAlternateFileName;
}
[DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
静态外部IntPtr FindFirstFile(字符串lpFileName,out WIN32_FIND_DATA lpFindFileData);
[DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
静态外部bool FindNextFile(IntPtr hFindFile,输出WIN32_FIND_数据
lpFindFileData);
[DllImport(“kernel32.dll”,SetLastError=true)]
静态外部bool FindClose(IntPtr hFindFile);
私有静态void Main(字符串[]args)
{
var namedPipes=新列表();
WIN32_FIND_数据lpFindFileData;
var ptr=FindFirstFile(@“\\.\pipe\*”,out lpFindFileData);
namedPipes.Add(lpFindFileData.cFileName);
while(FindNextFile(ptr,out lpFindFileData))
{
namedPipes.Add(lpFindFileData.cFileName);
}
FindClose(ptr);
namedPipes.Sort();
foreach(命名管道中的变量v)
控制台写入线(v);
Console.ReadLine();
}

使用返回IEnumerable的.NET 4 API之一,您可以捕获这些异常:

static IEnumerable<string> EnumeratePipes() {
    bool MoveNextSafe(IEnumerator enumerator) {

        // Pipes might have illegal characters in path. Seen one from IAR containing < and >.
        // The FileSystemEnumerable.MoveNext source code indicates that another call to MoveNext will return
        // the next entry.
        // Pose a limit in case the underlying implementation changes somehow. This also means that no more than 10
        // pipes with bad names may occur in sequence.
        const int Retries = 10;
        for (int i = 0; i < Retries; i++) {
            try {
                return enumerator.MoveNext();
            } catch (ArgumentException) {
            }
        }
        Log.Warn("Pipe enumeration: Retry limit due to bad names reached.");
        return false;
    }

    using (var enumerator = Directory.EnumerateFiles(@"\\.\pipe\").GetEnumerator()) {
        while (MoveNextSafe(enumerator)) {
            yield return enumerator.Current;
        }
    }
}
静态IEnumerable枚举管道(){
bool MoveNextSafe(IEnumerator枚举器){
//管道路径中可能有非法字符。可以从IAR中看到包含<和>。
//FileSystemEnumerable.MoveNext源代码表示将返回对MoveNext的另一个调用
//下一个条目。
//在底层实现发生某种变化时设置一个限制。这也意味着不超过10
//具有坏名称的管道可能按顺序出现。
const int Retries=10;
for(int i=0;i

当然,名称不好的管道最终不会被列举出来。因此,如果确实要列出所有管道,则无法使用此解决方案。

使用pipelist.exe()我发现破坏代码的管道名为:“D:\Virtuals\Windows 8.1 x64 Professional\Windows 8.1 x64 Professional.vmx”。如果我关闭虚拟测试机,一切都正常。但是,管道的这种名称仍然可以被其他任何人使用。因此,我的问题仍然悬而未决。这是否在.NET中得到了修复?我只能在以.NET 3.5或更早版本为目标时复制它,即使在Windows 7上也不行。调用
FindFirstFile()
FindNextFile()
时,此代码缺少任何错误处理。至少,在使用
lpFindFileData
FindNextFile()
/
FindClose()
执行任何操作之前,请确保
FindFirstFile()
没有返回
无效的\u句柄\u值
,例如
var ptr=FindFirstFile(@“\.\pipe\*”,out lpFindFileData);如果(ptr!=-1){do{namedPipes.Add(lpFindFileData.cFileName);}而(FindNextFile(ptr,out lpFindFileData));FindClose(ptr);}