1

自己展開型アプリケーションのホスティング パネルのように機能するものを開発しています。ファイル名と引数をパラメーターとして持ち、実行時にパネル Web ページに出力を与えるメソッドを作成しました。

これが私の方法です。

private string ExecuteCmd(string sysUser, SecureString secureString, string argument, string fileName)
{
    using (Process p = new Process())
    {
        p.StartInfo.FileName = fileName;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardOutput = true;

        p.StartInfo.UserName = sysUser;
        p.StartInfo.Password = secureString;

        p.StartInfo.Arguments = argument;
        p.Start();
        p.WaitForExit();

        StreamReader sr = p.StandardOutput;

        p.Close();

        string message = sr.ReadToEnd();

        return message;
    }
}

この方法を使用して (appcmd.exe を使用して) IIS にサイトを作成すると、コマンド プロンプトでこの実行可能ファイルを実行すると、すべての出力が得られます。しかし、DNS にエントリを作成する dnscmd.exe に関しては、何も得られません。StandardOutput は空になるだけです。管理者の資格情報を使用して、これらの実行可能ファイルを実行します。ちなみに、Windows Server 2012 Standard を使用しています。Server 2008 R2 でこの方法をまだテストしていませんが、とにかく結果は同じになると思います。

appcmd と dnscmd の実行可能ファイルが同じメソッドで異なる動作をするのを見るのは、ちょっと奇妙です。

ここで私が見逃しているのは何ですか?

ありがとう!

編集: StandardOutput と StandardError の両方が dnscmd.exe のエラーを返しています。

Edit2: ReadLine() を ReadToEnd() に変更しました。それは、いろいろなことを試したりして遊んでいたときに変えたものです。元のコードには ReadToEnd() がありました。

Edit3: ファイルパスと引数を含む完全なメソッド。これは IIS の場合で、問題なく出力が表示されます。

private string ExecuteAppCmd(string sysUser, SecureString secureString)
{
    using (Process p = new Process())
    {
        p.StartInfo.FileName = @"C:\Windows\System32\inetsrv\APPCMD.EXE";
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

        p.StartInfo.UserName = sysUser;
        p.StartInfo.Password = secureString;

        p.StartInfo.Arguments = " list site domain.com";
        p.Start();
        p.WaitForExit();

        StreamReader sr = p.StandardOutput;

        p.Close();

        string message = sr.ReadToEnd().Replace("\n", "<br />");

        return message;
    }
}

「appcmd list site domain.com」は、コマンド プロンプトでの domain.com の iis サイト構成を示しています。domain.com が iis にない場合、エラーが表示されます。いずれにせよ、出力があり、このコードで正常に動作します。

これは dnscmd 用です。これはasp.netページでジョブを実行しますが、StandardOutputでの出力を表示しません. ただし、出力はコマンド プロンプトに表示されます。

private string ExecuteDnsCmd(string sysUser, SecureString secureString)
{
    using (Process p = new Process())
    {
        p.StartInfo.FileName = @"C:\Windows\System32\DNSCMD.EXE";
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

        p.StartInfo.UserName = sysUser;
        p.StartInfo.Password = secureString;

        p.StartInfo.Arguments = " /zoneadd domain.com /primary";
        p.Start();
        p.WaitForExit();

        StreamReader sr = p.StandardError;

        p.Close();

        string message = sr.ReadToEnd().Replace("\n", "<br />");

        return message;
    }
}
4

1 に答える 1

0

dnscmd.exe を実行できるボックスはありませんが、他のすべてが機能すると主張しているため、エラーの処理と出力ストリームが何らかの形で絡み合っていることしか想像できません。このコードを試すと、唯一の違いは、このコードが別のスレッドでエラー ストリームと出力ストリームの両方を処理し、実行中にそれらの出力を収集することです。これが機能する場合、コードも問題ないはずです。

        // as there will not be an input stream so don't Redirect 
        p.StartInfo.RedirectStandardInput = false;

        // use a stringbuilder to capture everything
        var sb = new StringBuilder();
        // raise events on stdout and stderr and handle them
        p.EnableRaisingEvents = true;
        p.OutputDataReceived += (sender, args) => sb.AppendFormat("Out: {0}<br />",args.Data);
        p.ErrorDataReceived  += (sender, args) => sb.AppendFormat("Err: {0}<br />",args.Data);

        p.Start();

        // start consuming
        p.BeginOutputReadLine();
        p.BeginErrorReadLine();

        // wait for process to exit
        p.WaitForExit();

        p.Close();

        // obtain out stringbuilder value
        string message = sb.ToString();

        return message;
于 2013-09-15T12:38:10.477 に答える