OpenFileDialog在超过260个字符的路径上返回空字符串(或根本不返回)

问题描述 投票:3回答:1

我正在编写一个程序,该程序需要从系统上的任何位置读取文件。该程序的某些用户的路径超过了260个字符的限制。 OpenFileDialog不适用于路径超过260个字符的文件。

我尝试同时使用System.Windows.Forms.OpenFileDialogMicrosoft.Win32.OpenFileDialog。对于前者,当我导航并选择文件后单击“打开”时,窗口不会关闭,程序也不会继续。对于后者,当我单击“打开”时,窗口将关闭,但是路径为空字符串。

我已经更新了计算机上的注册表。我已经编辑了应用清单文件。我会尝试将“ //?/”字符串添加到我的路径前,但没有可添加的路径。

var dialog = new OpenFileDialog
{
  // initialize dialog
}

if (dialog.ShowDialog() == DialogResult.OK) // DialogResult.OK replaced with true if using Microsoft.Win32.OpenFileDialog
{
  // if when using System.Windows.Forms.OpenFileDialog, I will never get to this point
  // if using Microsoft.Win32.OpenFileDialog, I will get here but dialog.FileNames will be empty
}

如果我更新了注册表和应用清单,我希望上面的代码在长路径和短路径中都可以使用。我怀疑这不被支持,但是我所有的搜索都显示人们提供的解决方案要么不起作用,要么仅在特定情况下起作用。

c# .net openfiledialog max-path
1个回答
0
投票

在使用System.Windows.Forms.OpenFileDialog的情况下,我可以使用事件处理程序来解决此问题,从而克服了ShowDialog()在用户单击“打开”时不返回的问题,

    System.Windows.Forms.OpenFileDialog openFileDialog_WindowsForms = new System.Windows.Forms.OpenFileDialog
    {
        CheckFileExists = true,
        CheckPathExists = true,
        ValidateNames = false
    };
    openFileDialog_WindowsForms.FileOk += (s, e) =>
    {
        string[] fileNames = openFileDialog_WindowsForms.getFileNames_WindowsForms();

        foreach (var file in fileNames)
        {
            try
            {
                Console.WriteLine(File.ReadAllText(file));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Couldn't open file from Windows.Forms.OpenFileDialog:" + ex.Message);
            }
        }

        openFileDialog_WindowsForms.Dispose();
    };

    openFileDialog_WindowsForms.ShowDialog();

并进行反射以克服从FilePathFilePaths属性无法访问的路径。事实证明,这些路径存在于我可以使用反射访问的私有财产中。

public static class OpenFileDialogLongPathExtension
{
    public static string[] getFileNames_WindowsForms(this System.Windows.Forms.OpenFileDialog dialog)
    {
        var fileNamesProperty = dialog.GetType().GetProperty("FileNamesInternal", BindingFlags.NonPublic | BindingFlags.Instance);
        var fileNamesFromProperty = (string[])fileNamesProperty?.GetValue(dialog);
        return fileNamesFromProperty;
    }
}

我为Microsoft.Win32.OpenFileDialog尝试了类似的操作,但似乎私有属性仍然无效,因此相同的解决方案将不起作用。

不管怎样,我希望这对其他人有帮助。此示例是使用.NET Framework 4.8创建的。

© www.soinside.com 2019 - 2024. All rights reserved.