14

私のマシンでは C:\Programs\jdk16\bin にある "jconsole.exe" を単に起動しようとする次の簡単な C# アプリケーションがあります。

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」の間の 2 つのバックスラッシュに注意してください)、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

問題が発生する理由がよくわかりません。ただし、私のマシンで機能する 1 つのソリューションを考えることができます。

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);
}

このソリューションのアイデアを与えてくれた1つのパラを見つけました。Process.Startのドキュメントから

システムで引用符を使用して宣言されたパス変数がある場合、その場所で見つかったプロセスを開始するときに、そのパスを完全に修飾する必要があります。そうしないと、システムはパスを見つけられません。たとえば、c:\mypath がパスになく、引用符を使用して追加する場合: path = %path%;"c:\mypath"、開始時に c:\mypath 内のすべてのプロセスを完全に修飾する必要があります。

PATHWindowsが使用できる有効なパスが変数に含まれていたとしても、私がそれを読む方法は、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\、 thenpuma.batが よりも優先されpumaます。

c:\ruby\bin\puma.batから開始c:\redmineすると、現在の作業ディレクトリc:\ruby\binで puma が開始され、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 に答える