你一定是最倒霉的人,才会遇到这个错误。我可以确认它的行为符合您的观察,并且在互联网上的任何地方都找不到对此的任何引用。
所以我跟踪了 .NET 源代码以了解 Directory.EnumerateFiles 是如何工作的,并且 - 在内心深处 - 最终遇到了 call 到 FindFirstFile 和随后的 FindNextFile 调用。这些是直接从内核中 PInvoked,所以你不能比这更低。
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
那么必须测试一下。你猜怎么了?它在本地目录中捕获 XLSX 文件,但不在网络共享中。
The doc for the function 也没有提到这种行为。是的。您刚刚遇到了一个未记录的“功能”:)
编辑:这变得更好了。看起来在 .NET Core(从 2.0 一直到 .NET 5)中不再存在这种行为。这次他们实际上写了自己的pattern matcher。 *.xls 不会在任何文件夹中捕获 XLSX,无论是本地文件夹还是其他文件夹。然而their documentation 仍然表示应该这样做。
Edit 2021:该文档现已成为 updated,并附有关于 .NET Framework 的怪癖的评论。
这是我对FindFirstFile 调用的测试代码:
public class Program
{
public static void Main(string[] args)
{
// Ensure these test folders only contain ONE file.
// Name the file "Test.xlsx"
Test(@"C:\Temp\*.xls"); // Finds the xlsx file just fine
Test(@"\\Server\Temp\*.xls"); // But not here!
}
public static void Test(string fileName)
{
Win32Native.WIN32_FIND_DATA data;
var hnd = Win32Native.FindFirstFile(fileName, out data);
if (hnd == Win32Native.InvalidPtr)
Debug.WriteLine("Not found!!");
else
Debug.WriteLine("Found: " + data.cFileName);
}
}
/** Windows native Pinvoke **/
public class Win32Native
{
public static IntPtr InvalidPtr = new IntPtr(-1);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public 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;
}
}