C#:System.Diagnostics.Process.Start(“Explorer.exe”,@“/ select”+ FilePath)。 文件名为unicode字符时无法打开文件

我想用窗口资源管理器打开文件的位置。 我正在使用C#代码

System.Diagnostics.Process.Start("Explorer.exe", @"/select," + FilePath) 

它适用于简单的英文字符,但如果文件的名称是Unicode字符(Thia语言),则无法打开文件的位置。

有人可以帮忙吗?

试着把它放在引号中:

 System.Diagnostics.Process.Start("Explorer.exe", @"/select,""" + FilePath + "\"") 

这段代码没有问题:

  static void Main(string[] args) { string path = @"c:\temp\លួចស្រលាញ់សង្សារគេ.DAT"; System.IO.File.WriteAllText(path, "hello"); string txt = System.IO.File.ReadAllText(path); } 

在Windows 7中,文件已创建并在资源管理器中正确显示。 您没有记录您的操作系统版本,因此这是一种失败模式,尽管是非常小的模式。 更有可能是映射到E:驱动器的文件系统出现问题。 像闪存驱动器或网络重定向器上的FAT32卷。 分别在superuser.com和serverfault.com上提出相关问题。 不要忘记记录这些基本细节。

以下代码适用于带有韩文字符的文件(是unicode字符)。 请尝试一下,让我知道它是否有效。

  ... if (this.IsDirectory()) { OpenFileWith("explorer.exe", this.FullPath, "/root,"); } else { OpenFileWith("explorer.exe", this.FullPath, "/select,"); } ... public static void OpenFileWith(string exePath, string path, string arguments) { if (path == null) return; try { System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo.WorkingDirectory = Path.GetDirectoryName(path); if (exePath != null) { process.StartInfo.FileName = exePath; //Pre-post insert quotes for fileNames with spaces. process.StartInfo.Arguments = string.Format("{0}\"{1}\"", arguments, path); } else { process.StartInfo.FileName = path; process.StartInfo.WorkingDirectory = Path.GetDirectoryName(path); } if (!path.Equals(process.StartInfo.WorkingDirectory)) { process.Start(); } } catch(System.ComponentModel.Win32Exception ex) { FormManager.DisplayException(ex, MessageBoxIcon.Information); } } 

如果您尝试打开的文件夹不存在,资源管理器将转到默认文件夹,在这种情况下为“我的文档”。 确保它存在。

这是我已经确定的交易:至少从Windows 8.1开始, “Explorer.exe”似乎在查找文件之前删除所有组合字符 。 您可以在c#或控制台中测试它(首先执行chcp 65001以进入unicode模式)。 如果你试图打开一个名为ป((泰语为“螃蟹”)的目标它将无法工作,但如果你删除元音标记以便你只有ป,它将起作用。 此外,如果您有一个名为ป的文件夹,并且您打开ป,,它将打开√文件夹!

这解释了为什么其他一些开发者没有问题; 问题不是非ascii :相反,它是具有可组合字符的文件名。 并非所有语言都使用它们,即使在使用它们的语言中,并非所有文件都都使用它们。

好消息是,有一种不同的方式可以打开这些没有这个问题的方法, @ bert-huijben在这个答案中对此进行了描述。

为了完整性,这里的版本类似于我最终使用的版本:

  [DllImport("shell32.dll", ExactSpelling = true)] public static extern void ILFree(IntPtr pidlList); [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern IntPtr ILCreateFromPathW(string pszPath); [DllImport("shell32.dll", ExactSpelling = true)] public static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags); public void SelectItemInExplorer(string path) { var pidlList = ILCreateFromPathW(path); if(pidlList == IntPtr.Zero) throw new Exception(string.Format("ILCreateFromPathW({0}) failed",path)); try { Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0)); } finally { ILFree(pidlList); } }