11

.NETのProcessStartInfoクラスのインとアウトを理解するのに問題があります。私はこのクラスをFFmpegのような.exeプログラムを問題なく実行するために使用します。

しかし、ProcessStartInfoを使用して、それだけを含む単純なfoo.cmdのような.cmdプログラムを開始すると、@echo Hello world何も出力されません。

    ProcessStartInfo oInfo = new ProcessStartInfo(@"C:\Program Files (x86)\itms\foo.cmd")
    {
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    };

    using (Process p = new Process())
    {
        p.StartInfo = oInfo;
        p.OutputDataReceived += new DataReceivedEventHandler(transporter_OutputDataReceived);

        p.Start();

        p.BeginOutputReadLine();

        p.WaitForExit();
    }

private void transporter_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Response.Write(e.Data + " - line<br/>");
}

たくさんの例を見てきました。人々はcmd.exeを使用して.cmdプログラムを開始し、これを試しましたが、成功しませんでした。プログラムは無期限にロードを続けます。

    ProcessStartInfo oInfo = new ProcessStartInfo("cmd", "/c start foo.cmd")
    {
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true,
        CreateNoWindow = true,
        WorkingDirectory = @"C:\Program Files (x86)\itms"
    };

WindowsおよびMacでコマンドラインツールを使用すると、foo.cmdプログラムが正常に機能して出力されます。

誰かが私のためにこれをわかりやすく説明してくれませんか。

ありがとう

編集

ローカルで実行すると、コードは正しく動作します。ウェブサイトでコードを実行すると問題が発生します。プログラムの実行が許可されていないか、出力が何らかの理由で無効になっています。

cmd.exeのみが出力「cmd」を返します。「/cdir」は、たとえば現在のフォルダの内容に関する情報を返します。

これは実際には許可の問題でしょうか?

4

4 に答える 4

18

私は自分で答えを見つけ、興味のある人のために解決策を投稿します。

問題の原因はIISがユーザーとプロセスを処理する方法にあるため、問題の原因をデバッグするのはかなり困難です。

私が思ったように、コード自体には何の問題もありませんでした。

答え

IISでは、WebサイトはAppPoolで実行されています。AppPoolにはユーザーIDが割り当てられます。デフォルトのIDは、ApplicationPoolIdentityという名前の仮想組み込みアカウントです。このユーザーには、(私が知る限り)外部のバッチ/コマンドスクリプトを呼び出す権限がありません。

新しいプロセスを開始するときに管理ユーザーにユーザー名、パスワード、およびドメインを提供しても、何も解決しませんでした。概念全体を誤解しているだけかもしれません。

webconfigで使用<identity impersonate="true" userName="domain\user" password="pass" />しても、何も解決されませんでした。これは、割り当てられたAppPoolユーザーがまだすべてのプロセスの作成者であるためと思われます。

私を本当に悩ませたのは、.exeファイルは実行できたが、.cmdまたは.batファイルは実行できなかったことです。

私にとっての解決策は、バッチスクリプトを実行する権限を持つ新しいユーザーを作成し、そのユーザーをIISのAppPoolユーザーとして選択することでした。

編集:コメントで述べたように、この特定のファイルサーバーはネットワーク共有上にあるため、作業しているユーザーはActiveDirectoryサーバー上に作成されます。ユーザーは、Webサーバー上のローカルサーバーグループIIS_IUSRSの一部であり、実行可能プログラムが保存されているフォルダーで読み取り/書き込み/実行の特権を持っています。

Edit2:このソリューションは、ユーザーがローカルサーバーグループIIS_IUSRSの一部であり、実行可能プログラムが格納されているフォルダーで読み取り/書き込み/実行特権を持っている限り、ローカルユーザーアカウントでも機能します。

于 2012-07-23T13:37:54.327 に答える
1

これはわずかに変更されたコードですが、クラスに関するより良いアイデアが得られるはずです

ProcessStartInfo info = new ProcessStartInfo(); 
info.Arguments = "/C C:\Program Files (x86)\itms\foo.cmd"; 
info.WindowStyle = ProcessWindowStyle.Hidden; 
info.CreateNoWindow = true; 
info.FileName = "cmd.exe"; // or C:\Program Files (x86)\itms\foo.cmd with no info.Arguments 
info.UseShellExecute = false; 
info.RedirectStandardOutput = true; 
using (Process process = Process.Start(info)) 
{ 
    using (StreamReader reader = process.StandardOutput) 
    { 
        string result = reader.ReadToEnd(); 
        Console.WriteLine(result);
    } 
} 

これにより、cmdウィンドウの出力がコンソールにリダイレクトされます。必要に応じて調整してください。

于 2012-07-20T08:15:22.257 に答える
1

このように使用する必要があります

   using (Process p = Process.Start(oInfo))
    {
.....

理由は、Process.Start()とProcess.Star(startinfo)の動作がわずかに異なるためです。

Process.Start() -このProcessコンポーネントのStartInfoプロパティで指定されたプロセスリソースを開始(または再利用)し、それをコンポーネントに関連付けます。

戻り値

タイプ:System.Booleanプロセスリソースが開始された場合はtrue。新しいプロセスリソースが開始されていない場合(たとえば、既存のプロセスが再利用されている場合)はfalse。

Process.Start(StartInfo) -プロセス開始情報(たとえば、開始するプロセスのファイル名)を含むパラメーターで指定されたプロセスリソースを開始し、リソースを新しいプロセスコンポーネントに関連付けます。

戻り値

タイプ:System.Diagnostics.Processプロセスリソースに関連付けられている新しいプロセスコンポーネント。プロセスリソースが開始されていない場合(たとえば、既存のプロセスが再利用されている場合)はnull。

于 2012-07-20T08:17:18.210 に答える
0

(アプリケーションプールの新しいユーザーを作成する代わりに)私にとってうまくいったのは、組み込みアカウントの「ローカルシステム」(Windows Server 2012R2のIIS8.5)に切り替えることでした。

于 2020-11-21T19:32:20.713 に答える