PsExec hang while being executed from a very simple c# or c++ gui program compiled as "windows application"

sharrajesh picture sharrajesh · Apr 13, 2011 · Viewed 11.2k times · Source

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);
}

Answer

Johnny Kauffman picture Johnny Kauffman · Oct 16, 2012

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/