【问题标题】:How can I get a list of all open named pipes in Windows and avoiding possible exceptions?如何获取 Windows 中所有打开的命名管道的列表并避免可能的异常?
【发布时间】:2014-09-26 09:13:32
【问题描述】:

在理想情况下,获取命名管道列表非常简单,可以在这里找到: How can I get a list of all open named pipes in Windows?

但提到了解决方案

var namedPipes = Directory.GetFiles(@"\\.\pipe\");

偶尔会出现不可预知的结果。上面的链接中提到了其中之一(路径异常中的无效字符)。今天我遇到了自己的例外:

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

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

【问题讨论】:

  • 使用 pipelist.exe (technet.microsoft.com/en-us/sysinternals/dd581625.aspx) 我发现破坏我的代码的管道被命名为:“D:\Virtuals\Windows 8.1 x64 Professional\Windows 8.1 x64 Professional.vmx”。如果我关闭我的虚拟测试机一切正常。但是,其他任何人都可以使用这种管道名称。因此我的问题仍然存在
  • 这个问题在 .NET 中已经修复了吗?我只能在面向 .NET 3.5 或更早版本时重现它,即使在 Windows 7 上也不行。

标签: c# .net named-pipes


【解决方案1】:

使用返回 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;
        }
    }
}

当然,最后没有列举出名字不好的管道。因此,如果您真的想列出 所有 管道,则不能使用此解决方案。

【讨论】:

    【解决方案2】:

    我深入研究了 Directory 类的源代码并找到了灵感。这是一个可行的解决方案,它为您提供所有打开的命名管道的列表。我的结果不包含 \\.\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();
         }
    

    【讨论】:

    • 此代码在调用FindFirstFile()FindNextFile() 时缺少任何错误处理。至少,在对lpFindFileDataFindNextFile()/FindClose() 进行任何操作之前,请确保FindFirstFile() 不会返回INVALID_HANDLE_VALUE,例如var ptr = FindFirstFile(@"\\.\pipe\*", out lpFindFileData); if (ptr != -1) { do { namedPipes.Add(lpFindFileData.cFileName); } while (FindNextFile(ptr, out lpFindFileData)); FindClose(ptr); }
    猜你喜欢
    • 2010-09-20
    • 2012-07-11
    • 1970-01-01
    • 2020-12-26
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多