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

时间:2010-10-29 11:33:04

标签: c# .net windows-7 system.diagnostics

我正在尝试从.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. 进程是使用简单的“new Process();”创建的System.Diagnostics.Process。
  2. 路径是.exe“c:/path/to/my.exe”的完整路径。
  3. enableRaisingEvents 为false
  4. windowStyle 已最大化(但已尝试过其他人)。
  5. 它给了一个糟糕的MessageBox ...我很高兴永生。它是西班牙语,但翻译应该很容易:

    alt text

    它说:

    应用程序错误 程序(0x0eedfade)在......

    发生意外异常

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

    对于记录:如果我尝试启动其他东西(即:Notepad.exe,Adobe Acrobat Reader),它可以正常工作, Firefox无法打开并且没有没有显示错误。

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

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

    更新:好的;我已经得到了该软件的副本。这是一个混乱的软件,但它的工作原理。现在我可以调试,我发现程序在使用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:
    

    alt text

    这意味着,“由于缺少ddip.dll,程序无法启动...请尝试重新安装bla bla”。

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

    alt text

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

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

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

    有什么想法吗?

    更新和解决方案

    我使用以下提供的答案之一使其成功。事实证明,没有人直接指出我的解决方案,但他们都给了我很好的想法。

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

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

    <requestedExecutionLevel level=“asInvoker” uiAccess=“false” />
    

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

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

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

6 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:3)

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

现在,我将补充一点,如果您在配备UAC的Windows(Vista,7,2008,...)上运行,您可能还应该尝试使用 runas 动词解释为herehere

使用.NET,即:

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

答案 3 :(得分:1)

过去我遇到过类似的问题。我通过执行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(); ...}

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

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