and*_*l85 4 c# windows process.start winforms
我正在尝试从C#应用程序启动"开始"菜单中的程序,并且"开始"菜单中的几乎所有项目都是快捷方式(lnk)文件.当使用Process.Start启动这些文件时,如果lnk文件的完整路径指向C:\ Program Files目录,我发现我收到"系统无法找到指定的路径"错误.我在Windows中对文件系统重定向进行了一些研究,所以我尝试禁用它,但我仍然得到同样的错误:
// disable file system redirection:
IntPtr ptr = new IntPtr();
bool isWow64FsRedirectionDisabled = Wow64DisableWow64FsRedirection(ref ptr);
// run the file:
System.Diagnostics.Process.Start("c:\\splitter.lnk");
Run Code Online (Sandbox Code Playgroud)
这将返回"系统找不到指定的路径".但是,如果我从"开始">"运行"对话框启动c:\ splitter.lnk,则程序运行正常.您可以通过为任何64位应用程序创建快捷方式,将其放在C驱动器上,并尝试使用上面的代码运行它来在任何64位计算机上重现此问题.
是否有更好的方法来启动.lnk文件以避免此问题?或者我没有正确禁用文件重定向?
编辑:我也尝试将UseShellExecute设置为true以使操作系统运行该文件,但仍然失败,这很有趣,因为从开始>运行对话框运行相同的路径工作正常:
Process process = new Process();
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = "c:\\splitter.lnk";
process.Start();
Run Code Online (Sandbox Code Playgroud)
编辑2:我认为不是直接尝试启动LNK文件,而是获取目标,然后运行目标.我尝试使用如何在c#中解析.lnk以及如何以编程方式跟踪.lnk文件,但这两种方法都返回完整路径为C:\ Program Files(x86)\ Splitter.exe而不是C:\的实际路径Program Files\Splitter.exe.
也许我可以使用上述方法之一来获取LNK文件的目标.然后我可以看到目标是否包含Program Files(x86).如果是,请将其替换为Program Files并检查文件是否存在.如果它存在于Program Files中,请运行它.如果没有,请从Program Files(x86)位置运行该文件.这将是一个混乱的解决方法,但我不知道还有什么可以尝试.任何建议,将不胜感激.
通过在如何解决c#中的.lnk中使用Sam Saffron的示例脚本,我能够为此问题提供解决方法.我将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;
}
Run Code Online (Sandbox Code Playgroud)
如果有人知道更好的方法,我愿意接受各种想法.否则,我将使用此方法并接受此变通方法作为答案.
| 归档时间: |
|
| 查看次数: |
2265 次 |
| 最近记录: |