4

I am kicking off PsExec using a C# .NET 4 process with the code

var startInfo = new ProcessStartInfo(psExecLocation)
{
    Arguments = string.Format(@"\\{0} -accepteula -u {1} -p {2} {3}", serverName, username, password, command),
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    CreateNoWindow = true,
    StandardErrorEncoding = Encoding.UTF8,
    StandardOutputEncoding = Encoding.UTF8,
    UseShellExecute = false
};

Using PsExec works fine when I am inside the same domain as my develoment machine (for ALL calls that I am making which is more than just this one I am running into issues with) and when doing simple DOS commands (rmdir and mkdir) cross domain (as I am doing them right before this call).

When I have it run the following command, however:

C:\7Zip\7za x "C:[File Path Includes Spaces]\__STAGING__\App01 [Trunk - STAGE_20121217.2].7z" -o"C:[File Path Includes Spaces]\__STAGING__\" -y -aoa

it never returns. I can see it START to return data (I am redirecting the output using the process and it starts to return what it did), but then it abruptly stops and just doen't do anything. It never returns after the call to

process.WaitForExit();

The odd part is that it DOES sucessfully complete. I can RDP into the server we are extracting the files in and I can see the files there, it's just the PsExec doesn't return anything. I've already tried removing the -y -aoa switches and moving the order around of things and nothing seems to work. FYI, the server we are trying to extract this at is a Windows Server 2003 edition and a Windows Server 2008 R2 edition.

As asked, here is exactly what I am doing to open the process using PsExec:

        try
        {
            using (var process = new Process())
            {
                var startInfo = new ProcessStartInfo(psExecLocation)
                    {
                        Arguments = string.Format(@"\\{0} -accepteula -u {1} -p {2} {3}", serverName, username, password, command),
                        RedirectStandardError = true,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true,
                        StandardErrorEncoding = Encoding.UTF8,
                        StandardOutputEncoding = Encoding.UTF8,
                        UseShellExecute = false
                    };

                process.StartInfo = startInfo;

                var processOutput = "";
                Action<object, DataReceivedEventArgs> action = (obj, eventArgs) =>
                    {
                        if (string.IsNullOrWhiteSpace(eventArgs.Data) == false)
                            processOutput += string.Format("{0}\r\n", eventArgs.Data);
                    };

                process.OutputDataReceived += new DataReceivedEventHandler(action);
                process.ErrorDataReceived += new DataReceivedEventHandler(action);

                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                process.WaitForExit();

                // There appears to be a fault in PsExec that has everything go to error even if it is output. This gets around that
                output = "";
                if (string.IsNullOrWhiteSpace(processOutput) == false)
                {
                    output = processOutput;

                    // error code 0 means it worked / succeeded. Any other "error code" means something failed
                    var loweredOutput = processOutput.ToLower().Replace("\r\n", "").Trim();
                    return loweredOutput.EndsWith("error code 0.") || loweredOutput.EndsWith("error code 0");
                }

                // if it got here, psexec didn't return anything. That SHOULD never happen (emphasis on should)
                return false;
            }
        }
        catch (Exception ex)
        {
            Logging.Logger.LogError(ex);
            output = "";
            return false;
        }
Chris Katz
  • 100
  • 9
  • Please show the code that you use to read the process output (which you redirect). – usr Dec 18 '12 at 20:27
  • Original question updated. – Chris Katz Dec 18 '12 at 20:49
  • 1
    When you launch psexec from the cmd prompt in exactly the same way, does the same problem occur? (as far as I can tell you are really doing everything right - I have done a similar thing in the past). – usr Dec 18 '12 at 21:04
  • I can run that 7Z command from the command prompt (on the server) and it works. I have not tried running it locally. I am trying that now. – Chris Katz Dec 18 '12 at 21:16
  • I also ran the full command from my development command prompt and it worked. – Chris Katz Dec 18 '12 at 21:22
  • if its hung on `WaitForExit` does that mean your psexec process is still in the task manager? (after its finished doing what it does) – wal Dec 18 '12 at 22:08
  • Assuming PSEXESVC is the process name, then yes. And being it shows back up every time I run the process, I believe it is. – Chris Katz Dec 18 '12 at 22:38
  • Maybe psexec is waiting on input? Maybe for credentials? Not sure how to test this theory. – usr Dec 18 '12 at 23:10
  • Not sure what input it's waiting for... This exact command works inside the domain and the credentials are valid. When I change the credentials to not be, it immediately returns with bad credentials. – Chris Katz Dec 19 '12 at 14:34
  • After seeing that it worked when calling command prompt directly, I even tried launching a command manually using: http://stackoverflow.com/questions/437419/execute-multiple-command-lines-with-the-same-process-using-net – Chris Katz Dec 19 '12 at 15:57
  • So 7z runs successfully and exits but its output is not fully returned by psexec because it somehow "stops". Did I get that exactly right?; Let's try to find out what psexec is doing: Can you wait until 7z has exited and look at the stacks of the threads of psexec using procexp.exe? You need to set it up for symbols. Maybe that tells us what it is waiting on. – usr Dec 19 '12 at 16:53
  • Could you please tell me how to set it up using symbols? It keeps complaining that I need to install "Microsoft Debugging Tools for Windows". Without looking at the symbols however, it currently has 8 threads all in a wait state. 6 appear to be psexec ones (with a state of Wait:Executive), 1 advapi32.dll (with a state of Wait:UserRequest) and 1 kernel32.dll (with a state of Wait:WrLpcReceive). To ME that seems to be expecting user input for some reason (but that is strictly a guess... I don't really know what I'm looking at). – Chris Katz Dec 19 '12 at 17:38

1 Answers1

0

This isn't really an answer, but I'm running into a very similar issue. I'm running in the same domain, but seeing the same results as described.

Everytime I run PsExec from either C# code or from PowerShell, the process appears to hang. When I watch the remote server, I see the PSEXESVC process spin up, along with the command that I was trying to run on the remote server. The command exits normally, but PSEXESVC seems to hang.

The remote command I'm passing is: cmd /c dir E:\temp

I've tested this from LINQPad with the CreateNoWindow set to false along with the redirects set to false and the command prompt that opens does return the expected output. As soon as I attempt to capture the output again, the process goes back into the hang state.

I know this used to work from C# using the same code a year or 2 ago, so I'm not sure what has changed to cause it to hang now.

JStinebaugh
  • 149
  • 2
  • 8