当完整pathparsing为64位目录时,无法从32位C#应用程序启动快捷方式(lnk)文件

我试图从C#应用程序启动开始菜单中的程序,几乎开始菜单中的所有项目都是快捷方式(lnk)文件。 当使用Process.Start启动这些文件时,我发现如果lnk文件的完整path指向C:\ Program Files目录,我得到“系统找不到指定的path”错误。 我在Windows中使用文件系统redirect进行了一些研究,所以我尝试禁用它,但我仍然得到相同的错误:

// disable file system redirection: IntPtr ptr = new IntPtr(); bool isWow64FsRedirectionDisabled = Wow64DisableWow64FsRedirection(ref ptr); // run the file: System.Diagnostics.Process.Start("c:\\splitter.lnk"); 

这将返回“系统找不到指定的path”。 但是,如果从“开始”>“运行”对话框启动c:\ splitter.lnk,程序运行得很好。 您可以在任何64位计算机上重现此问题,方法是为任何64位应用程序创build快捷方式,将其放在C驱动器上,然后尝试使用上面的代码运行它。

有没有更好的方法来启动.lnk文件来避免这个问题? 还是我没有正确禁用文件redirect?

编辑:我也尝试设置UseShellExecute为true让操作系统运行该文件,但仍然失败,这是有趣的,因为从开始>运行对话框运行相同的path工作得很好:

 Process process = new Process(); process.StartInfo.UseShellExecute = true; process.StartInfo.FileName = "c:\\splitter.lnk"; process.Start(); 

编辑2:我想,而不是试图直接启动LNK文件,我会得到它的目标,然后运行目标。 我试图使用如何解决C#中的.lnk和如何以编程方式跟随.lnk文件 ,但这两种方法返回完整path为C:\ Program Files文件(x86)\ Splitter.exe而不是C:\的实际path。 Program Files \ Splitter.exe。

也许我可以使用上面的方法之一来获得LNK文件的目标。 然后我可以看到目标是否包含Program Files(x86)。 如果是,请将其replace为程序文件并检查文件是否存在。 如果它存在于Program Files中,请运行它。 如果不是,请从Program Files(x86)位置运行该文件。 这将是一个混乱的解决方法,但我不知道还有什么要尝试在这一点上。 任何build议,将不胜感激。

Solutions Collecting From Web of "当完整pathparsing为64位目录时,无法从32位C#应用程序启动快捷方式(lnk)文件"

我可以通过使用Sam Saffron的示例脚本来解决这个问题, 如何解决C#中的.lnk问题 。 我修改了以下的ResolveShortcut函数:

 public static string ResolveShortcut(string filename) { // this gets the full path from a shortcut (.lnk file). ShellLink link = new ShellLink(); ((IPersistFile)link).Load(filename, STGM_READ); StringBuilder sb = new StringBuilder(MAX_PATH); WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0); string final_string = sb.ToString(); if (final_string.Length == 0) final_string = filename; // If the the shortcut's target resolves to the Program Files or System32 directory, and the user is on a // 64-bit machine, the final string may actually point to C:\Program Files (x86) or C:\Windows\SYSWOW64. // This is due to File System Redirection in Windows -- http://msdn.microsoft.com/en-us/library/aa365743%28VS.85%29.aspx. // Unfortunately the solution there doesn't appear to work for 32-bit apps on 64-bit machines. // We will provide a workaround here: string new_path = Validate_Shortcut_Path(final_string, "SysWOW64", "System32"); if (File.Exists(new_path) == true && File.Exists(final_string) == false) { // the file is actually stored in System32 instead of SysWOW64. Let's update it. final_string = new_path; } new_path = Validate_Shortcut_Path(final_string, "Program Files (x86)", "Program Files"); if (File.Exists(new_path) == true && File.Exists(final_string) == false) { // the file is actually stored in Program Files instead of Program Files (x86). Let's update it. final_string = new_path; } // the lnk may incorrectly resolve to the C:\Windows\Installer directory. Check for this. if (final_string.ToLower().IndexOf("windows\\installer") > -1) final_string = filename; if (File.Exists(final_string)) return final_string; else return filename; } public static string Validate_Shortcut_Path(string final_string, string find_what, string replace_with) { string final_string_lower = final_string.ToLower(); string find_what_lower = find_what.ToLower(); int find_value = final_string_lower.IndexOf(find_what_lower); if (find_value > -1) { // the shortcut resolved to the find_what directory, which can be SysWOW64 or Program Files (x86), // but this may not be correct. Let's check by replacing it with another value. string new_string = final_string.Substring(0, find_value) + replace_with + final_string.Substring(find_value + find_what.Length); if (File.Exists(new_string) == true && File.Exists(final_string) == false) { // the file is actually stored at a different location. Let's update it. final_string = new_string; } } return final_string; } 

如果有人知道有更好的方法来做到这一点,我愿意接受。 否则,我将使用此方法并接受此解决方法作为答案。