在Windows 7下启动System.Diagnostics.Process时出现问题

我试图从.NET 3.51启动一个应用程序(操作系统,我的应用程序和我要启动的应用程序都是32位)。

启动Process的代码用于其他应用程序,但是有一个令我们头疼的问题。 如果我们在应用程序的图标上“双击”它,它按预期工作,这意味着它可以作为计算机中的应用程序正常工作。 直接双击.exe也可以。

操作系统是Windows 7 32位(家庭和/或专业)。

我们的.NET应用程序使用x86编译以避免出现问题。

启动“Processes”的代码位于我们制作的DLL(也是32位)内部,基本上它是一个简单的DLL,它包含一些“通用代码”,我们在整个代码中使用的常用方法,函数和内容。 其中一种方法看起来像这样:

public static bool FireUpProcess( Process process, string path, bool enableRaisingEvents, ProcessWindowStyle windowStyle, string arguments ) { if ( process != null ) { try { process.StartInfo.FileName = @path; if ( arguments != null ) { if ( arguments != String.Empty ) { process.StartInfo.Arguments = arguments; } } process.StartInfo.WindowStyle = windowStyle; process.EnableRaisingEvents = enableRaisingEvents; process.Start(); } catch { try { process.Kill(); } catch ( InvalidOperationException ) { } // The process is not even created return false; } } else { return false; } return true; } 

我不知道是谁编写了这种方法,但它已经使用不同的应用程序工作了大约六年,因此我认为它是“好的”。 但是,我们有一个客户使用的软件在通过该参数时不会启动。

论点是

  1. process是一个使用简单的“new Process();”创建的System.Diagnostics.Process。
  2. path是.exe“c:/path/to/my.exe”的完整路径。
  3. enableRaisingEvents为false
  4. windowStyle最大化(但已尝试过其他人)。

它给了一个糟糕的MessageBox …我很高兴永生。 它是西class牙语,但翻译应该很容易:

替代文字

它说:

应用程序错误程序(0x0eedfade)发生意外exception…

谷歌搜索0x0eedfade给出看起来可怕的奇怪结果,但事实是,如果我去.exe,我试图启动并双击它,它的工作完美。

对于记录 :如果我尝试启动其他东西(即:Notepad.exe,Adobe Acrobat Reader)它可以工作, Firefox不会打开,也不会显示错误。

这种“一些工作,一些没有”的行为使我相信Windows 7安全机制或类似的问题可能存在我不知道的问题。

我错过了什么或做错了什么?

更新 :好的; 我已经得到了该软件的副本。 这是一个混乱的软件,但它的工作原理。 现在我可以调试,我看到程序在使用我的FireUpProcess方法启动时FireUpProcess

正如建议我添加了WorkingDirectory代码,但这里是代码:

  public static bool FireUpProcess(Process process, string path, bool enableRaisingEvents, ProcessWindowStyle windowStyle) { if (process != null) { try { if ( !String.IsNullOrEmpty(@path) ) { process.StartInfo.FileName = @path; process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(@path); process.StartInfo.WindowStyle = windowStyle; // Suscribe to the exit notification process.EnableRaisingEvents = enableRaisingEvents; // Disable to prevent multiple launchs Framework.Check.LogWarning("LAUNCHING EXTERNAL DEVICE WITH PATH: " + path); process.Start(); // HERE The program reports the following: 

替代文字

这意味着,“程序无法启动,因为ddip.dll丢失…尝试重新安装bla bla”。

问题是,如果我从命令行执行相同的@path,程序将完美打开:

替代文字

这打开了程序。 如果我点击它位于“程序”菜单中的“快捷方式”,也会发生同样的情况。 该快捷方式中没有任何参数,只是对可执行文件的简单调用。

现在的问题是: 我的代码与其他方法有什么区别?

必须有不同的东西导致我的过程无法启动。

有任何想法吗?

更新和解决方案

我通过使用以下提供的答案之一使其工作。 事实certificate,没有人直接指出我的解决方案,但他们都给了我好的想法。

我在我们的应用程序中添加了一个应用程序清单(自vista时代以来应该已经拥有它,不知道它为什么不在第一个位置)。 我使用VStudio 2008添加的应用程序清单添加文件 – >应用程序清单。

在其中,我确保我们有这个:

  

我们不需要管理员或类似的东西,但显然Vista / 7需要知道它。

添加之后,该过程正确启动。

注意 :默认情况下UseShellExecute为true (如某些人所建议的那样),如果这是你想要的,你必须明确地将它变为false。

如果exe有清单,则应在调用Start之前在进程对象上将UseShellExecute设置为true。 无论如何,这不是一个坏主意。

您没有设置process.StartInfo.WorkingDirectory属性。 有很多写得不好的软件,假设工作目录将是存储EXE的目录。 至少添加这一行:

  process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(@path); 

然而,例外是相当奇怪的。 我绝对建议您告诉客户更新他们的反恶意软件工具。

正如Kate Gregory所指出的,如果你想“模仿”用户双击图标,你必须将UseShellExecute设置为true。 设置此标志使代码使用完全不同的路径,使用底层的Windows ShellExecute函数。

现在,我将补充一点,如果您在配备UAC的Windows(Vista,7,2008,…)上运行,您也可以尝试使用此处和此处所述的runas动词。

使用.NET,那将是:

 if (System.Environment.OSVersion.Version.Major >= 6) // UAC's around... { processStartInfo.Verb = "runas"; } 

我过去也遇到过类似的问题。 我通过执行cmd应用程序解决了它,如下所示:

 public static bool FireUpProcess(Process process, string path, bool enableRaisingEvents, ProcessWindowStyle windowStyle) { //if path contains " ", surround it with quotes. //add /c and the path as parameters to the cmd process. //Any other parameters can be added after the path. ProcessStartInfo psi = new ProcessStartInfo("cmd", "/c" + path )); psi.WorkingDirectory = System.IO.Path.GetDirectoryName(@path); psi.WindowStyle = windowStyle; // Suscribe to the exit notification process.EnableRaisingEvents = enableRaisingEvents; // Disable to prevent multiple launchs Framework.Check.LogWarning("LAUNCHING EXTERNAL DEVICE WITH PATH: " + path); process.Start(); ...} 

如果有可能,我会尝试使用Sysinternals的Process Monitor 。 启动时,可以取消选择工具栏上的“注册表和网络活动”(右侧的5个图标)。 然后,您只能看到进程和磁盘活动。 由于它看起来像找不到文件问题,您应该使用“filter”对话框(左侧的6.图标)从下拉列表中选择“进程名称”(默认为“体系结构”),然后输入失败的可执行文件名称。 这将极大地限制捕获的输出,以便您可以看到正在发生的事情。 然后启动exectuable并在结果列中检查NAME NOT FOUND结果。 这是搜索但未找到文件的位置。 如果你知道有问题的dll名称,你可以像往常一样用Ctrl + F搜索它来挖掘它。 然后,您可以比较工作应用程序中的不同搜索路径以及从应用程序启动的时间。

是否环境变量PATH在您的流程中具有不同的值? 可能是添加。 (当前目录)有助于修复dll搜索路径。 或者应用程序是从其他用户帐户启动的? 它也可能是一项新function,当应用程序将内容安装到Programm Files但没有权限时(只有管理员可以执行此操作),Windows会将写入重定向到用户配置文件中。 这是一种安全透明的方式,可以提高安全性。 但这可能导致例如在第一次应用程序启动期间某些配置文件在未经UAC对话框同意运行应用程序时部署到管理员配置文件中。 然后其他用户也可能启动应用程序但失败,因为附加配置文件位于Administrators配置文件中,而不是按照预期的方式位于Program Files中。

我相信Hans Passant走在正确的轨道上。 除了他说的,检查以确保ddip.dll和exe在同一目录中。 情况并非总是如此,因为还有其他方法可以在bin之外绑定程序集。 即,GAC和AssemblyResolve事件。 考虑到您的情况,我认为GAC没有理由参与其中。 检查为AssemblyResolve事件中的任何挂钩启动的exe代码。 如果它被挂钩,您可能需要更新实现以允许另一个进程启动它。

因为你得到一个关于丢失的DLL的例外,我对路径分隔符问题的答案几乎没有信心。 尽管如此,您有应用程序代码,因此请validation它是否引用了ddip.dll。 这将使您充分相信您实际上引用了正确的.exe,因此它不仅仅是命令提示符的路径分隔符问题(EG误解空格)。