PsExec 在从非常简单的 c# 或 c++ 执行时挂起。 gui程序编译为“windows应用程序”

发布于 2024-10-31 22:39:40 字数 4638 浏览 1 评论 0原文

我在从编译为“Windows 应用程序”(而不是“控制台应用程序”)的非常简单的 c# 或 c++ gui 程序执行时遇到 PsExec 挂起。在下面 下面的 C) 部分我粘贴了代码来重现问题,而 D) 部分下我粘贴了 C++ 代码来重现相同的问题。

当 psexec 挂起时,本地附加到 psexec 后的 Windbg 输出将粘贴在 B) 部分下。

我的程序在转储 A) 部分下粘贴的输出后挂起。

如果您将 psexec 命令替换为任何本地命令,例如 ProcessStartInfo("cmd.exe", "/c dir c:\windows\*.*");,则该程序可以正常工作。

我想知道是否有人经历过并找到了解决方案。非常感谢您的帮助。

谢谢, Sharrajesh


A) psexec 挂起时我的 c# 程序输出

PsExec v1.98 - 远程执行进程 版权所有 (C) 2001-2010 马克·鲁西诺维奇 Sysinternals - www.sysinternals.com

驱动器 C 中的卷没有标签。


B) 挂起时 psexec 的 Windbg 输出

3 Id:1614.15e4 挂起:1 Teb:7efac000 解冻 ChildEBP RetAddr 参数到子
02a3fe68 75a6d0c5 00000180 00000000 00000000 ntdll!NtReadFile+0x15 (FPO: [9,0,0]) 02a3fecc 75cb18aa 00000180 02a3ff44 00010000 KERNELBASE!ReadFile+0x118(FPO:[SEH]) 02a3ff14 00403bde 00000180 02a3ff44 00010000 kernel32!ReadFileImplementation + 0xf0(FPO:[SEH]) 警告:堆栈展开信息不可用。以下框架可能是错误的。 02a3ff2c 00000000 00291e48 00000000 02a5ff80 psexec+0x3bde


C) 重现问题的 C# 代码

using System;
using System.Windows.Forms;
using System.Diagnostics;

namespace WindowsFormsApplication1 {
  static class Program {
    static void DataReceiveHandler(object sender, DataReceivedEventArgs e) {
      Debug.WriteLine(e.Data);
    }

    public static void NotWorkingPsExec() {
      ProcessStartInfo startInfo = new ProcessStartInfo("psexec.exe",
        "\\\\raj-2k3-32 cmd.exe /c dir c:\\windows\\*.*");
      startInfo.UseShellExecute        = false;
      startInfo.CreateNoWindow         = true;
      startInfo.RedirectStandardOutput = true;
      startInfo.RedirectStandardError  = true;

      Process proc = new Process();
      proc.StartInfo           = startInfo;
      proc.ErrorDataReceived  += new DataReceivedEventHandler(DataReceiveHandler);
      proc.OutputDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
      proc.Start();
      proc.BeginErrorReadLine();
      proc.BeginOutputReadLine();
      proc.WaitForExit();
      Debug.WriteLine("Exit code = {0}", proc.ExitCode);
    }

    public static void WorkingPsExec() {
      ProcessStartInfo startInfo = new ProcessStartInfo("psexec.exe", 
        "\\\\raj-2k3-32 cmd.exe /c dir c:\\windows\\*.*");
      startInfo.UseShellExecute = false;

      Process proc = new Process();
      proc.StartInfo = startInfo;
      proc.Start();
      proc.WaitForExit();
      Debug.WriteLine("Exit code = {0}", proc.ExitCode);
    }

    static void Main() {
      NotWorkingPsExec();
      //WorkingPsExec(); //If uncommented will work 
    }
  }
}

D) 重现问题的 C++ 代码

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

HANDLE g_hStdoutRd = NULL;
HANDLE g_hStdoutWr = NULL;

void StartCommand(TCHAR *szCmdline);
void ReadOutput();
void ErrorExit(PTSTR);

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
  SECURITY_ATTRIBUTES saAttr;
  saAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
  saAttr.bInheritHandle       = TRUE;
  saAttr.lpSecurityDescriptor = NULL;
  if (!CreatePipe(&g_hStdoutRd, &g_hStdoutWr, &saAttr, 0))
    ErrorExit(TEXT("Stdout SetHandleInformation"));
  if (!SetHandleInformation(g_hStdoutRd, HANDLE_FLAG_INHERIT, 0))
    ErrorExit(TEXT("Stdout SetHandleInformation"));
  TCHAR szCmdline[] = TEXT("psexec.exe \\\\raj-2k3-32 cmd.exe /c dir /s c:\\windows\\*.*"); // Not Working
  //TCHAR szCmdline[] = TEXT("cmd.exe /c dir /s c:\\windows\\*.*"); // Working
  StartCommand(szCmdline);
  ReadOutput();
  return 0;
}

void StartCommand(TCHAR *szCmdline) {
  PROCESS_INFORMATION piProcInfo  = {0};
  STARTUPINFO         siStartInfo = {0};
  siStartInfo.cb         = sizeof(STARTUPINFO);
  siStartInfo.hStdError  = g_hStdoutWr;
  siStartInfo.hStdOutput = g_hStdoutWr;
  siStartInfo.dwFlags   |= STARTF_USESTDHANDLES;
  BOOL bSuccess = CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
  if (!bSuccess)
    ErrorExit(TEXT("CreateProcess"));
  else {
    CloseHandle(piProcInfo.hProcess);
    CloseHandle(piProcInfo.hThread);
  }
}

void ReadOutput() {
  if (!CloseHandle(g_hStdoutWr))
    ErrorExit(TEXT("StdOutWr CloseHandle"));
  for (;; ) {
    CHAR    chBuf[4096] = {0};
    DWORD   dwRead;
    BOOLEAN bSuccess    = ReadFile(g_hStdoutRd, chBuf, ARRAYSIZE(chBuf), &dwRead, NULL);
    if (!bSuccess || dwRead == 0)
      break;
    OutputDebugStringA(chBuf);
  }
}

void ErrorExit(PTSTR lpszFunction) {
  OutputDebugString(lpszFunction);
  ExitProcess(1);
}

I am experiencing PsExec hang while being executed from a very simple c# or c++ gui program compiled as "windows application" (not as "console application"). Under
section C) below I have pasted the code to reproduce the problem and under section D) I have pasted the c++ code to reproduce the same problem.

When the psexec hangs, the windbg output after being attached to psexec locally is pasted under section B).

My program hangs after dumping the output pasted under section A).

The program works fine if you replace psexec command with anything local e.g. ProcessStartInfo("cmd.exe", "/c dir c:\windows\*.*");

I was wondering if anybody experienced it and found the solution for it. Help will be greatly appreciated.

Thanks,
Sharrajesh


A) My c# program output when psexec hang

PsExec v1.98 - Execute processes remotely
Copyright (C) 2001-2010 Mark Russinovich
Sysinternals - www.sysinternals.com

Volume in drive C has no label.


B) Windbg output for psexec while hang

3 Id: 1614.15e4 Suspend: 1 Teb: 7efac000 Unfrozen
ChildEBP RetAddr Args to Child
02a3fe68 75a6d0c5 00000180 00000000 00000000 ntdll!NtReadFile+0x15 (FPO: [9,0,0])
02a3fecc 75cb18aa 00000180 02a3ff44 00010000 KERNELBASE!ReadFile+0x118 (FPO: [SEH])
02a3ff14 00403bde 00000180 02a3ff44 00010000 kernel32!ReadFileImplementation+0xf0 (FPO: [SEH])
WARNING: Stack unwind information not available. Following frames may be wrong.
02a3ff2c 00000000 00291e48 00000000 02a5ff80 psexec+0x3bde


C) The c# code to reproduce the problem

using System;
using System.Windows.Forms;
using System.Diagnostics;

namespace WindowsFormsApplication1 {
  static class Program {
    static void DataReceiveHandler(object sender, DataReceivedEventArgs e) {
      Debug.WriteLine(e.Data);
    }

    public static void NotWorkingPsExec() {
      ProcessStartInfo startInfo = new ProcessStartInfo("psexec.exe",
        "\\\\raj-2k3-32 cmd.exe /c dir c:\\windows\\*.*");
      startInfo.UseShellExecute        = false;
      startInfo.CreateNoWindow         = true;
      startInfo.RedirectStandardOutput = true;
      startInfo.RedirectStandardError  = true;

      Process proc = new Process();
      proc.StartInfo           = startInfo;
      proc.ErrorDataReceived  += new DataReceivedEventHandler(DataReceiveHandler);
      proc.OutputDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
      proc.Start();
      proc.BeginErrorReadLine();
      proc.BeginOutputReadLine();
      proc.WaitForExit();
      Debug.WriteLine("Exit code = {0}", proc.ExitCode);
    }

    public static void WorkingPsExec() {
      ProcessStartInfo startInfo = new ProcessStartInfo("psexec.exe", 
        "\\\\raj-2k3-32 cmd.exe /c dir c:\\windows\\*.*");
      startInfo.UseShellExecute = false;

      Process proc = new Process();
      proc.StartInfo = startInfo;
      proc.Start();
      proc.WaitForExit();
      Debug.WriteLine("Exit code = {0}", proc.ExitCode);
    }

    static void Main() {
      NotWorkingPsExec();
      //WorkingPsExec(); //If uncommented will work 
    }
  }
}

D) The c++ code to reproduce the problem

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

HANDLE g_hStdoutRd = NULL;
HANDLE g_hStdoutWr = NULL;

void StartCommand(TCHAR *szCmdline);
void ReadOutput();
void ErrorExit(PTSTR);

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
  SECURITY_ATTRIBUTES saAttr;
  saAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
  saAttr.bInheritHandle       = TRUE;
  saAttr.lpSecurityDescriptor = NULL;
  if (!CreatePipe(&g_hStdoutRd, &g_hStdoutWr, &saAttr, 0))
    ErrorExit(TEXT("Stdout SetHandleInformation"));
  if (!SetHandleInformation(g_hStdoutRd, HANDLE_FLAG_INHERIT, 0))
    ErrorExit(TEXT("Stdout SetHandleInformation"));
  TCHAR szCmdline[] = TEXT("psexec.exe \\\\raj-2k3-32 cmd.exe /c dir /s c:\\windows\\*.*"); // Not Working
  //TCHAR szCmdline[] = TEXT("cmd.exe /c dir /s c:\\windows\\*.*"); // Working
  StartCommand(szCmdline);
  ReadOutput();
  return 0;
}

void StartCommand(TCHAR *szCmdline) {
  PROCESS_INFORMATION piProcInfo  = {0};
  STARTUPINFO         siStartInfo = {0};
  siStartInfo.cb         = sizeof(STARTUPINFO);
  siStartInfo.hStdError  = g_hStdoutWr;
  siStartInfo.hStdOutput = g_hStdoutWr;
  siStartInfo.dwFlags   |= STARTF_USESTDHANDLES;
  BOOL bSuccess = CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
  if (!bSuccess)
    ErrorExit(TEXT("CreateProcess"));
  else {
    CloseHandle(piProcInfo.hProcess);
    CloseHandle(piProcInfo.hThread);
  }
}

void ReadOutput() {
  if (!CloseHandle(g_hStdoutWr))
    ErrorExit(TEXT("StdOutWr CloseHandle"));
  for (;; ) {
    CHAR    chBuf[4096] = {0};
    DWORD   dwRead;
    BOOLEAN bSuccess    = ReadFile(g_hStdoutRd, chBuf, ARRAYSIZE(chBuf), &dwRead, NULL);
    if (!bSuccess || dwRead == 0)
      break;
    OutputDebugStringA(chBuf);
  }
}

void ErrorExit(PTSTR lpszFunction) {
  OutputDebugString(lpszFunction);
  ExitProcess(1);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

£烟消云散 2024-11-07 22:39:40

PSExec 对我来说太随意了。我没有花精力按照你的方式重现这个问题,但我通过使用“PAExec”避免了我的麻烦,它是一个看似有价值的精神继承者:
http://www.poweradmin.com/PAExec/

PSExec was hanging for me too randomly. I haven't put the effort into recreating the issue your way, but I have avoided my troubles by using "PAExec", a seemingly worthy successor in spirit:
http://www.poweradmin.com/PAExec/

岁月如刀 2024-11-07 22:39:40

我遇到了类似的问题,这是由于 eula 造成的,这可能是你的问题:

可能的原因:

1) psiexec.exe 在首次运行期间显示 EULA 消息。

2)权限

3) dll 函数可能需要用户会话。

为避免这些问题,请尝试以下方案:

1) 使用“-accepteula”参数

2) 带“-s”参数

3) 使用“-i”参数

4) > 2 + 3 5) 2 + 3 + 1

请参阅:

I had a similar problem that was due to the eula, which may be yours:

Possible reasons:

1) psiexec.exe shows EULA message during first run.

2) Permissions

3) dll function can require user session.

To avoid these issues please try following scenarios:

1) with "-accepteula" argument

2) with "-s" argument

3) with "-i" argument

4) > 2 + 3 5) 2 + 3 + 1

See: http://www.appdeploy.com/messageboards/tm.asp?m=72376&mpage=1&key=𑪸

Even though I had checked the EULA several times

心安伴我暖 2024-11-07 22:39:40

还请在startInfo 上设置WorkingDirectory 属性,因为Sysinternals 实用程序使用文件的运行时解包,并且内核无法找到解包的(真正的)可执行文件。

Please also set the WorkingDirectory property on startInfo, as Sysinternals utilities use run-time unpacking of files and the kernel is unable to find the unpacked (real) exectutable file.

撑一把青伞 2024-11-07 22:39:40

构建一个运行 PsExec 的通用控制台应用程序PsKill 和他们所有的朋友。通过代码调用此 ConsoleApp,而不是调用 NotWorkingPsExec 方法,它就会正常工作。

Build a generic Console Application which runs PsExec & PsKill and all of their friends. Call this ConsoleApp through your code instead of calling the NotWorkingPsExec method, and it'll work just fine.

比忠 2024-11-07 22:39:40

我对此有一个简单的解决方案,

  1. C# 运行如下过程:

    Process.Start("启动run.bat xx.txt"); //称之为异步
    
    //然后我们编写一些代码,等待xx.txt出现并完成编写。
    
  2. run.bat 是:

    psexec.bat > %1 //重定向到文本文件
    出口
    
  3. psexec.bat 是:

    <前><代码>psexec.exe ................................
    出口

I have a simple solution for this,

  1. C# run the process like:

    Process.Start("start run.bat xx.txt");    //call it async
    
    //and then we make some code juse wait xx.txt appear and finish written .
    
  2. run.bat is :

    psexec.bat > %1           //redirect to a text file
    exit
    
  3. psexec.bat is:

    psexec.exe ..........................
     exit
    
寻找一个思念的角度 2024-11-07 22:39:40

流上的同步读取有效:

        ProcessStartInfo startInfo = new ProcessStartInfo("psexec.exe", @"\\localhost cmd.exe /c dir c:\windows\*.*");
        startInfo.UseShellExecute = false;
        startInfo.CreateNoWindow = true;
        startInfo.RedirectStandardOutput = true;
        //startInfo.RedirectStandardError = true;
        //startInfo.RedirectStandardInput = true;

        Process proc = new Process();
        proc.StartInfo = startInfo;
        //proc.ErrorDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
        //proc.OutputDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
        proc.Start();
        //proc.BeginErrorReadLine();
        //proc.BeginOutputReadLine();
        string output = proc.StandardOutput.ReadToEnd();
        proc.WaitForExit();
        Console.WriteLine(output);
        Console.WriteLine("Exit code = {0}", proc.ExitCode);

即使在这里,请注意 ReadToEnd() 应在 WaitForExit() 之前完成。

我相信 PSExec 总是遇到这样的问题。在Java服务下运行时,我们过去将输出重定向到nul,无法获取正在运行的进程的输出,但可以获取PSExec本身的输出。

请参阅下面给出的讨论:

http://forum.sysinternals .com/psexec-always-hangs-when-run-from-java_topic5013.html

http://forum.sysinternals.com/unusual-problem-with-psexecexe_topic6655.html

编辑:

关于 PSEXESVC 清理的注意事项:删除 C:\Windows (或 C:\Windows \system32 或两者)在终止挂起的 PSEXESVC 进程后。延迟的进程/文件会导致更多问题。

Synchronous read on the stream works:

        ProcessStartInfo startInfo = new ProcessStartInfo("psexec.exe", @"\\localhost cmd.exe /c dir c:\windows\*.*");
        startInfo.UseShellExecute = false;
        startInfo.CreateNoWindow = true;
        startInfo.RedirectStandardOutput = true;
        //startInfo.RedirectStandardError = true;
        //startInfo.RedirectStandardInput = true;

        Process proc = new Process();
        proc.StartInfo = startInfo;
        //proc.ErrorDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
        //proc.OutputDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
        proc.Start();
        //proc.BeginErrorReadLine();
        //proc.BeginOutputReadLine();
        string output = proc.StandardOutput.ReadToEnd();
        proc.WaitForExit();
        Console.WriteLine(output);
        Console.WriteLine("Exit code = {0}", proc.ExitCode);

Even here, note that the ReadToEnd() should be done before the WaitForExit().

I believe PSExec always had problems like this. When running under Java service, we used to redirect the output to nul and couldn't get the output of the running process, but can get the output of PSExec itself.

Refer to below given discussions:

http://forum.sysinternals.com/psexec-always-hangs-when-run-from-java_topic5013.html

http://forum.sysinternals.com/unusual-problem-with-psexecexe_topic6655.html

Edit:

Note on PSEXESVC cleanup: Delete the PSEXESVC.EXE file at C:\Windows ( or C:\Windows\system32 or both ) after killing the hung PSEXESVC process. Lingering process / file cause more problems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文