来自sysinternals的stdout和psexec.exe的问题

时间:2011-07-26 12:23:43

标签: c#

我搜索并阅读了sysinternals中psexec.exe与c#和stdout无法正常工作的问题。我现在试图找出如何只调用具有以下内容的批处理文件,而不是使用System.Diagnostics.Process来调用psexec:

test.bat包含以下行:

psexec.exe \\hostname -u user -p password ipconfig /all >c:\test.txt

test.txt将保存在运行我的c应用程序并执行psexec的主机上。

当我执行以下操作时:

System.Diagnostics.Process psexec_run = new System.Diagnostics.Process();
psexec_run.StartInfo.FileName = "cmd.exe";
psexec_run.StartInfo.Arguments = @"/c """ + cur_dir + @"\test\test.bat""";
psexec_run.StartInfo.UseShellExecute = false;
psexec_run.Start();
psexec_run.WaitForExit();

我看到cmd窗口弹出,它运行了一些但不确定是什么然后消失了。

如果我执行以下内容:

System.Diagnostics.Process psexec_run = new System.Diagnostics.Process();
psexec_run.StartInfo.FileName = cur_dir + "\\test\\psexec.exe";
psexec_run.StartInfo.Arguments = @"\\hostname -u user -p password ipconfig /all";
psexec_run.StartInfo.UseShellExecute = false;
psexec_run.Start();
psexec_run.WaitForExit();

然后我看到命令窗口打开,它运行psexec,这需要几秒钟,我很快就会看到我需要的输出,但我无法捕获输出或将其写入文件。

我想我现在的问题是因为psexec不能与stdout一起工作如何从psexec命令中捕获输出以将其写入文件???

请参阅以下链接了解psexec的问题,关于这个url的最后一个回复提到了一种将进程输出写入文件而不使用stdout的方法,我是c#的新手,我无法弄清楚如何编写进程没有使用标准输出的输出:(

http://forum.sysinternals.com/psexec-fails-to-capture-stdout-when-launched-in-c_topic19333.html

根据下面的回复我尝试了以下内容:

ProcessStartInfo psi = new ProcessStartInfo(cur_dir + "\\test\\psexec.exe",    @"\\hostname -u user -p password ipconfig /all");                   
psi.RedirectStandardOutput = true;         
psi.RedirectStandardError = true;         
psi.UseShellExecute = false;          
Process p = Process.Start(psi);          
StreamReader myStreamReader = p.StandardOutput;          
// Read the standard output of the spawned process.                         
string sOutput = myStreamReader.ReadToEnd(); 

我做了ReadToEnd所以我会确保它得到了所有的输出,它没有!由于某种原因,它只是它的第一行ipconfig输出。它打开的cmd窗口也从未因某种原因而关闭。即使使用CreateNoWindow = true,代码也会挂起。所以psexec和stdout再次出现问题我认为?因为我可以在本地主机上使用ipconfig / all命令运行此代码,而不是使用psexec ...

我希望避免使用stdout并以某种方式找到一种方法来获取此命令的输出,或者除非有其他东西我在看?另外,不要为任何人做更多的工作,但如果你从sysinternals d / l psexec.exe并使用远程主机上的命令测试它,你会看到。我在这个上花了2天时间:(试图弄清楚如何使用psexec或者找一些其他快速方法在主机上执行远程命令并获得ouptput。

更新:

我放弃了c#代码中的psexec,我看到很多关于psexec吃输出的帖子,有一个子窗口进程等等 直到我的头疼:)所以我试图运行一个批处理文件并输出到一个文件,这是没有意义...

我有一个批处理文件test.bat,其中包含以下内容

psexec.exe \\\hostname -u name -p password ipconfig /all >c:\test.txt

当我运行以下代码时:

ProcessStartInfo psi = new ProcessStartInfo(cur_dir + @"\test\test.bat");

psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
Process p = Process.Start(psi);

p.WaitForExit();

cmd窗口来得非常快,并且创建了test.txt文件但是0字节没有信息。

所以,如果我使用psexec命令在windows cmd行中运行批处理文件,它的工作原理非常好!! ???

然后验证psexec是我将批处理文件更改为:

的问题
ipconfig /all >c:\test.txt

我执行上面的代码并且工作正常在test.txt文件中创建输出.. ??? !!!!

为什么不使用psexec我错过了什么?如果它是psexec,有没有人 关于如何在远程Windows主机上执行命令并获取我的任何建议 输出???

5 个答案:

答案 0 :(得分:2)

我对这个问题的答案对我有用。

希望其他人会发现它很有用。

我真的花了最后两个小时用这个撕掉我的头发。 psexec工具使用正常的命令提示符运行完全正常,但是当尝试重定向流时,它会截断输出并且只返回一半输出。

最后我如何解决我的问题是一个小问题。我将命令的输出传送到文本文件并将其读回以从函数返回它。

我还必须将UseShellExecute设置为true。没有它,它仍然无法工作。这显示了控制台窗口的不幸副作用。为了解决这个问题,我将窗口样式设置为隐藏,嘿它可以工作!!!

继承我的代码:

string ExecutePSExec(string command)
{
    string result = "";
    try
    {
        string location = AppDomain.CurrentDomain.BaseDirectory;

        // append output to file at the end of this string:
        string cmdWithFileOutput = string.Format("{0} >{1}temp.log 2>&1", command,location );


        // The flag /c tells "cmd" to execute what follows and exit
        System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + cmdWithFileOutput);

        procStartInfo.UseShellExecute = true;       // have to set shell execute to true to 
        procStartInfo.CreateNoWindow = true;
        procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;      // as a window will be created set the window style to be hiddem

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo = procStartInfo;
        proc.Start();
        proc.WaitForExit();


        // now read file back.
        string filePath = string.Format("{0}temp.log", location);
        result = System.IO.File.ReadAllText(filePath);
    }
    catch (Exception objException)
    {
        // Log the exception
    }

    return result;
}

及其用法:

string command = @"psexec.exe -l -u domain\username -p password /accepteula \\192.168.1.3 netstat -a -n";

ExecutePSExec(command);

答案 1 :(得分:2)

我有完全相同的问题。当我使用psexec运行时,我得到了“Windows ip config。”作为第一行。我尝试使用paexec它运作良好。我使用了Marius的代码。

注意:如果你不使用参数中的第一个cmd / c,那么即使你将目标定义为\\ remoteserver

,命令也只能在本地计算机上运行
 ProcessStartInfo psi = new ProcessStartInfo("cmd.exe");
                        psi.Arguments = @"cmd/c C:\paexec.exe \\\192.168.2.5 -s  -u test.local\administrator -p Password1 cmd /c ipconfig";
                        psi.CreateNoWindow = true;
                        psi.RedirectStandardOutput = true;
                        psi.RedirectStandardError = true;
                        psi.UseShellExecute = false;
                        Process p = Process.Start(psi);

                        System.IO.StreamReader myStreamReader1 = p.StandardOutput;

                        p.WaitForExit();


                        string sOutput = myStreamReader1.ReadToEnd();

答案 2 :(得分:1)

您确定源代码是否正确?这个链接有点老了......也许它固定了!

下面举例说明如何重定向标准输出并通过streamreader将整个输出放入字符串中:

        ProcessStartInfo psi = new ProcessStartInfo("tftp.exe");

        // preferences for tftp process
        psi.CreateNoWindow = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;
        psi.UseShellExecute = false;

        Process p = Process.Start(psi);

        StreamReader myStreamReader = p.StandardOutput;

        p.WaitForExit();

        // Read the standard output of the spawned process.                
        string sOutput = myStreamReader.ReadToEnd();

答案 3 :(得分:1)

我找到了解决方案。显然psexec不会用c sharp工作。所以我想出了一些wmi代码连接到一个远程主机,它的工作完美! :)

我使用microsoft的WMICodeCreator.exe为远程主机上的进程方法创建C#的wmi代码,哇,这个工具很棒,因为wmi代码对我来说有点混乱。

答案 4 :(得分:0)

psexec的输出转到StandardError而不是StandardOutput。我不知道为什么会这样。以下代码段访问它。

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.RedirectStandardError = true;

Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();

errors = process.StandardError.ReadToEnd();

process.Close();