1// Declare the api calls.
2[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
3static extern IntPtr AllocConsole();
4[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
5static extern bool FreeConsole();
6[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
7private static extern int CloseHandle(IntPtr handle);
8[DllImport("user32.dll")]
9static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
10[DllImport("kernel32.dll", SetLastError = true)]
11static extern IntPtr GetConsoleWindow();
12
13// Wrap the call to diagnostic.process in the api calls.
14// pay attention as its this that makes it work!
15protected override int ExecuteCommand(ProcessStartInfo startInfo)
16{
17 TextWriter writer = Console.Out;
18 IntPtr handle = AllocConsole();
19 try
20 {
21 if (!IntPtr.Zero.Equals(handle))
22 {
23 Console.SetOut(writer);
24 ShowWindow(GetConsoleWindow(), 0);
25 }
26
27 Log(LogSeverity.Debug, "PsExec is executing the following command '{0}", Command);
28 return base.ExecuteCommand(startInfo);
29 }
30 finally
31 {
32 if (!IntPtr.Zero.Equals(handle))
33 {
34 CloseHandle(handle);
35 FreeConsole();
36 }
37 }
38}
39
40
41// process start for psexec
42protected override ProcessStartInfo GetProcessStartInfo()
43{
44 string batchFileName = CreateBatchFile();
45 string psexecfileName =
46 Path.Combine((string.IsNullOrEmpty(PsExecPath) ? GetExecutingPath() : PsExecPath),
47 "psexec.exe");
48 string args = CreatePsExecArguments(batchFileName);
49
50 ProcessStartInfo result = new ProcessStartInfo(psexecfileName, args)
51 {
52 // The following commands are needed to
53 // redirect the standard output.
54 // This means that it will be redirected to
55 // the Process.StandardOutput StreamReader.
56 RedirectStandardOutput = true,
57 RedirectStandardError = true,
58 UseShellExecute = false,
59 // Do not create the black window.
60 CreateNoWindow = true,
61 };
62 return result;
63}
64
65private string CreatePsExecArguments(string fileName)
66{
67 const string psExecArgFmt = "\\\\{0} -u \"{1}\" -p \"{2}\" -c -f {3}";
68 return string.Format(psExecArgFmt,
69 HostName,
70 string.IsNullOrEmpty(UserDomain) ? UserName : string.Format("{0}\\{1}", UserDomain, UserName),
71 UserPassword,
72 fileName);
73}
74
75
76
77// base.ExecuteCommand
78protected virtual int ExecuteCommand(ProcessStartInfo startInfo)
79{
80 // Now we create a process, assign its ProcessStartInfo and start it
81 Process process = new Process {StartInfo = startInfo};
82 process.OutputDataReceived += ((sender, e) =>
83 {
84 if (!string.IsNullOrEmpty(e.Data))
85 Log(LogSeverity.Output, e.Data);
86 });
87 process.ErrorDataReceived += ((sender, e) =>
88 {
89 if (!string.IsNullOrEmpty(e.Data))
90 Log(LogSeverity.Error, e.Data);
91 });
92
93 if (string.IsNullOrEmpty(startInfo.WorkingDirectory))
94 {
95 startInfo.WorkingDirectory = GetExecutingPath();
96 }
97 if (!string.IsNullOrEmpty(UserName))
98 {
99 startInfo.Domain = UserDomain;
100 startInfo.UserName = UserName;
101 startInfo.Password = ToSecureString(UserPassword);
102 }
103
104 process.Start();
105
106 process.BeginOutputReadLine();
107 process.BeginErrorReadLine();
108
109 process.WaitForExit();
110
111 // Return the process exit code.
112 return process.ExitCode;
113}
114
115