8

私はC#コマンドラインアプリケーションを持っており、それをWindowsで実行し、UNIXではmonoで実行する必要があります。ある時点で、コマンドラインから渡された任意のパラメーターのセットを指定してサブプロセスを起動したいと思います。例えば:

Usage: mycommandline [-args] -- [arbitrary program]

残念ながら、System.Diagnostics.ProcessStartInfoはargsの文字列のみを取ります。これは、次のようなコマンドの問題です。

./my_commandline myarg1 myarg2 -- grep "a b c" foo.txt

この場合、argvは次のようになります。

argv = {"my_commandline", "myarg1", "myarg2", "--", "grep", "a b c", "foo.txt"}

「abc」を囲む引用符はシェルによって削除されるため、ProcessStartInfoのarg文字列を作成するために引数を単純に連結すると、次のようになります。

args = "my_commandline myarg1 myarg2 -- grep a b c foo.txt"

それは私が望むものではありません。

argvをC#でのサブプロセス起動に渡すか、任意のargvをWindowsおよびLinuxシェルに有効な文字列に変換する簡単な方法はありますか?

どんな助けでも大歓迎です。

4

5 に答える 5

1

ウィンドウランドでは、それは本当に簡単です...System.Diagnostics.ProcessStartInfoオブジェクトに渡す文字列に引用符を追加します。

例: "./ my_commandline" "myarg1 myarg2 --grep \" abc \ "foo.txt"

于 2010-06-03T15:45:48.693 に答える
1

MSDNには、MSVisualCランタイムがによって返された文字列GetCommandLine()argv配列に解析する方法についての説明があります。

Win32環境でUnixの動作をエミュレートするためにlist2cmdline()Pythonのモジュールで使用されるPython標準ライブラリの関数にも興味があるかもしれません。subprocessargv

于 2010-06-02T19:06:51.920 に答える
1

提案してくれたすべての人に感謝します。最終的にshquote(http://www.daemon-systems.org/man/shquote.3.html)のアルゴリズムを使用しました。

/**
 * Let's assume 'command' contains a collection of strings each of which is an
 * argument to our subprocess (it does not include arg0).
 */
string args = "";
string curArg;
foreach (String s in command) {
    curArg = s.Replace("'", "'\\''"); // 1.) Replace ' with '\''
    curArg = "'"+curArg+"'";          // 2.) Surround with 's
    // 3.) Is removal of unnecessary ' pairs. This is non-trivial and unecessary
    args += " " + curArg;
}

私はこれをLinuxでのみテストしました。Windowsの場合、引数を連結するだけです。

于 2010-06-03T17:53:41.850 に答える
0

正規表現を使用して、文字列に何らかのスペースが含まれているかどうかを確認し、元の文字列を引用符で囲まれた新しい文字列に置き換えます。

using System.Text.RegularExpressions;
// ...
for(int i=0; i<argv.Length; i++) {
    if (Regex.IsMatch(i, "(\s|\")+")) {
        argv[i] = "\"" + argv[i] + "\"";
        argv[i].Replace("\"", "\\\"");
    }
}
于 2010-06-03T10:39:29.953 に答える
0

とを使用して新しいサブプロセスを実行する必要がありgrepますgrep

void runProcess(string processName, string args)
{
    using (Process p = new Process())
    {
        ProcessStartInfo info = new ProcessStartInfo(processName);
        info.Arguments = args;
        info.RedirectStandardInput = true;
        info.RedirectStandardOutput = true;
        info.UseShellExecute = false;
        p.StartInfo = info;
        p.Start();
        string output = p.StandardOutput.ReadToEnd();
        // process output
    }
}

次に、に電話をかけますrunProcess("grep", "a", "b", "c", "foo.txt");

編集:引数の処理を更新しました。

于 2010-06-02T18:20:54.590 に答える