14

我有以下简单的 C# 应用程序,它只是尝试启动“jconsole.exe”,它在我的机器上位于 C:\Programs\jdk16\bin 中。

using System;
using System.Diagnostics;

namespace dnet {
  public class dnet {
    static void Main( string[] args ) {
      try {
        Process.Start("jconsole.exe");
        Console.WriteLine("Success!");
      } catch (Exception e) {
        Console.WriteLine("{0} Exception caught.", e);
      }
    }
  }
}

如果我的 PATH 环境变量设置为

c:\windows;c:\windows\sytem32;c:\programs\jdk16\bin

它完美地工作。但是,如果 PATH 环境变量设置为

c:\windows;c:\windows\sytem32;c:\\programs\jdk16\bin

(注意“c:”和“programs”之间的两个反斜杠),它会因 win32 异常而失败。

System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at dnet.dnet.Main(String[] args)

有趣的是,在我运行 .NET 程序并获得异常的同一命令提示符下,我只需键入“jconsole.exe”,程序就会启动。Windows 似乎可以轻松地在 PATH 中找到带有双反斜杠的可执行文件,但 Process.Start() 可以。

为什么 PATH 中的额外反斜杠会导致问题,以及如何解决该问题?我不知道我要调用的可执行文件在运行时位于何处,所以我宁愿依赖 PATH 变量。

4

3 回答 3

14

不太清楚为什么会出现问题。不过,我可以想到一种适用于我的机器的解决方案:

var enviromentPath = System.Environment.GetEnvironmentVariable("PATH");

Console.WriteLine(enviromentPath);
var paths = enviromentPath.Split(';');
var exePath = paths.Select(x => Path.Combine(x, "mongo.exe"))
                   .Where(x => File.Exists(x))
                   .FirstOrDefault();

Console.WriteLine(exePath);

if (string.IsNullOrWhiteSpace(exePath) == false)
{
    Process.Start(exePath);
}

我确实找到了一个段落,它给了我这个解决方案的想法。来自Process.Start 的文档

如果您在系统中使用引号声明了路径变量,则在启动在该位置找到的任何进程时,您必须完全限定该路径。否则系统将找不到路径。例如,如果 c:\mypath 不在您的路径中,并且您使用引号将其添加:path = %path%;"c:\mypath",则在启动时必须完全限定 c:\mypath 中的任何进程。

我阅读它的方式,即使PATH变量包含 Windows 能够使用的有效路径,Process.Start也无法使用它并且需要完全限定的路径

于 2012-09-12T17:33:55.270 回答
4

如果您首先创建一个ProcessStartInfo.

ProcessStartInfo psi = new ProcessStartInfo("jconsole.exe");
StringDictionary dictionary = psi.EnvironmentVariables;

// Manipulate dictionary...

psi.EnvironmentVariables["PATH"] = dictionary.Replace(@"\\", @"\");
Process.Start(psi);

您必须自己弄清楚如何操纵 PATH 让它为您工作。但这应该可以解决您的 PATH 变量可能遇到的任何问题。

于 2012-09-12T17:37:24.127 回答
3

接受的答案不正确。

cmd.exe 将首先查找具有可执行扩展名的应用程序。
因此,当您拥有文件pumapuma.bat进入时C:\Ruby\bin\puma.bat则将优先于puma.

如果c:\ruby\bin\puma.bat从开始c:\redmine,它将使用当前工作目录启动 puma c:\ruby\bin,并且您的 Web 应用程序将运行。
但是,如果您c:\ruby\bin\puma直接启动,它将使用当前工作目录启动 puma,c:\redmine随后会失败。

所以一个更正的版本看起来或多或少是这样的:

// FindAppInPathDirectories("ruby.exe");
public string FindAppInPathDirectories(string app)
{
    string enviromentPath = System.Environment.GetEnvironmentVariable("PATH");
    string[] paths = enviromentPath.Split(';');

    foreach (string thisPath in paths)
    {
        string thisFile = System.IO.Path.Combine(thisPath, app);
        string[] executableExtensions = new string[] { ".exe", ".com", ".bat", ".sh", ".vbs", ".vbscript", ".vbe", ".js", ".rb", ".cmd", ".cpl", ".ws", ".wsf", ".msc", ".gadget" };

        foreach (string extension in executableExtensions)
        {
            string fullFile = thisFile + extension;

            try
            {
                if (System.IO.File.Exists(fullFile))
                    return fullFile;
            }
            catch (System.Exception ex)
            {
                Log("{0}:\r\n{1}",
                     System.DateTime.Now.ToString(m_Configuration.DateTimeFormat, System.Globalization.CultureInfo.InvariantCulture)
                    , "Error trying to check existence of file \"" + fullFile + "\""
                );

                Log("Exception details:");
                Log(" - Exception type: {0}", ex.GetType().FullName);
                Log(" - Exception Message:");
                Log(ex.Message);
                Log(" - Exception Stacktrace:");
                Log(ex.StackTrace);
            } // End Catch

        } // Next extension

    } // Next thisPath


    foreach (string thisPath in paths)
    {
        string thisFile = System.IO.Path.Combine(thisPath, app);

        try
        {
            if (System.IO.File.Exists(thisFile))
                return thisFile;
        }
        catch (System.Exception ex)
        {
            Log("{0}:\r\n{1}",
                 System.DateTime.Now.ToString(m_Configuration.DateTimeFormat, System.Globalization.CultureInfo.InvariantCulture)
                , "Error trying to check existence of file \"" + thisFile + "\""
            );

            Log("Exception details:");
            Log(" - Exception type: {0}", ex.GetType().FullName);
            Log(" - Exception Message:");
            Log(ex.Message);
            Log(" - Exception Stacktrace:");
            Log(ex.StackTrace);
        } // End Catch

    } // Next thisPath

    return app;
} // End Function FindAppInPathDirectories
于 2016-12-15T12:19:41.747 回答