代码之家  ›  专栏  ›  技术社区  ›  Martin Marconcini

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

  •  5
  • Martin Marconcini  · 技术社区  · 15 年前

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

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

    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. 过程
    2. 路径 是.exe的完整路径c:/path/to/my.exe。
    3. 启用提升事件
    4. 窗式

    它提供了一个糟糕的消息框,我已经高兴地永生。它是西班牙语的,但翻译应该很容易:

    alt text

    应用程序错误 程序(0x0eedfead)在发生意外异常

    用谷歌搜索0x0eedfead会得到奇怪的结果,看起来很吓人,但事实是,如果我转到我试图启动的.exe并双击它,它会工作得很好。

    记录在案 :如果我尝试启动其他程序(即:Notepad.exe、Adobe Acrobat Reader),它会工作, 但是 Firefox没有打开,也没有显示错误。

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

    更新 :好的;我得到了软件的副本。这是一个凌乱的软件,但它工作。现在我可以调试了,我看到当用我的 FireUpProcess 方法。

    按照建议,我添加了工作目录代码,但代码如下:

        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。

    alt text

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

    我的代码和其他方法有什么区别?

    一定有一些不同的东西导致我的过程没有开始。

    有什么想法吗?

    我通过使用下面提供的答案之一来实现它。结果没有人直接告诉我解决办法,但他们都给了我一些好主意。

    我们的 应用程序(从vista时代就应该有了,不知道为什么它一开始就不在那里)。我使用VStudio 2008添加文件添加的应用程序清单->应用程序清单。

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

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

    添加之后,进程将正确启动。

    笔记 :UseShellExecute是 默认情况下(如某些人所建议的那样),如果这是您想要的,则必须显式地将其设置为false。

    6 回复  |  直到 15 年前
        1
  •  5
  •   Kate Gregory    15 年前

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

        2
  •  8
  •   Hans Passant    15 年前

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

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

        3
  •  3
  •   Simon Mourier    15 年前

    正如凯特·格雷戈里指出的,如果你想“模仿”用户双击图标,你 将UseShellExecute设置为true。设置此标志使代码使用完全不同的路径,使用底层窗口 ShellExecute

    现在,我要补充一点,如果你在一个安装了UAC的Windows(Vista,7,2008,…)上运行,你可能还应该尝试使用 符文 所解释的动词 here here .

    if (System.Environment.OSVersion.Version.Major >= 6)  // UAC's around...
    {
       processStartInfo.Verb = "runas";
    }
    
        4
  •  1
  •   Kell    15 年前

    我过去也遇到过类似的问题。我通过执行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(); ...}
    
        5
  •  1
  •   Alois Kraus    15 年前

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

        6
  •  0
  •   P.Brian.Mackey    15 年前

    我相信汉斯·帕桑特是在正确的轨道上。除了他所说的,检查以确保ddip.dll和exe位于同一目录中。情况并非总是如此 other ways 将程序集绑定到bin外部。即,GAC和AssemblyResolve事件。考虑到你的情况,我看不出GAC有什么牵连。检查启动的exe代码是否有钩子指向 AssemblyResolve

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

    推荐文章