Hi i am able to execute a remote process using Wmi and was able to get return Value and Process Id of the Process. Is there any way to get the Output of the Process which was started by Wmi. Eg. If i start an exe which prints something in console will i be able to get those values using this Api. Any help is appreciated.
You must redirect the output to a file, then read the file across the network.
Use the CMD.EXE /S /C option to do this.
Example command line to run Program.exe:
CMD.EXE /S /C " "c:\path\to\program.exe" "argument1" "argument2" > "c:\path\to\stdout.txt" 2> "c:\path\to\stderr.txt" "
Then connect to server like this \\servername\c$\path\to\stdout.txt to read the stdout results.
Note: Pay careful attention to the extra quotes around the command to run. These are necessary to ensure the command line is interpreted correctly.
You can use psexec to execute the program.exe and get the stdout by pipe
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while p.poll() is None:
line = p.stdout.readline()
line = line.strip().decode('gbk')
if line:
print('Subprogram output: [{}]'.format(line))
if p.returncode == 0:
print('Subprogram success')
return True
else:
print('Subprogram failed')
return False
Related
Trying to validate a Logstash config file. When running the following line from a Windows command line:
C:> C:\Logstash\bin\logstash -t -f C:\Logstash\config\my.config
I can then check the result using
echo %errorlevel%
which returns 1 in case of a syntax error. Now I want to do this programatically in C#, so:
using System.Diagnostics;
var logstashProcess = Process.Start(#"C:\Logstash\bin\logstash", #"-t -f C:\Logstash\config\my.config");
logstashProcess.WaitForExit();
return logstashProcess.ExitCode == 0;
The problem is that it always returns true (exit code is zero) - even when the config file is totally messed up.
My guess: since C:\Logstash\bin\logstash is a shell script, the zero I get is the shell itself running successfully - not the Logstash process (which is executed from within that script using jruby). Any idea on how to get the real return value? Will a batch file work? (I prefer not to add an extra script to the party at this point)
I have a C# assembly that processes an xml file and at the end spits out the results to the console.
e.g. Console.WriteLine(_header.ToString());
I can load this dll in powershell and call the right method like this:
[sqlproj_doctor.sqlprojDoctor]::ProcessXML($file) | out-file ./test.xml
All is well.
The problem begins when I want to redirect the output. For some reason stdout is empty. What am I missing? I need to be further process the output of this dll.
Note: If I compile the same code as an executable, it correctly populates the standard output stream and I can redirect the output.
another note: as a workaround, I changed the method from void to string, and can now manipulate the returned string.
When you call [Console]::WriteLine('SomeText'), it write to PowerShell process stdout, not to command output, and so it can not be redirected from inside same PowerShell process, by standard PowerShell operators, like this:
[Console]::WriteLine('SomeText')|Out-File Test.txt
You have to spawn new PowerShell process, and redirect output of that new process:
powershell -Command "[Console]::WriteLine('SomeText')"|Out-File Test.txt
In case if some command use [Console]::WriteLine to write to console, you can capture that output without starting new PowerShell instance:
$OldConsoleOut=[Console]::Out
$StringWriter=New-Object IO.StringWriter
[Console]::SetOut($StringWriter)
[Console]::WriteLine('SomeText') # That command will not print on console.
[Console]::SetOut($OldConsoleOut)
$Results=$StringWriter.ToString()
$Results # That variable would contain "SomeText" text.
Although this does not help if command does not use [Console]::WriteLine, but write to stdout stream directly:
$OldConsoleOut=[Console]::Out
$StringWriter=New-Object IO.StringWriter
[Console]::SetOut($StringWriter)
$Stdout=[Console]::OpenStandardOutput()
$Bytes=[Console]::OutputEncoding.GetBytes("SomeText"+[Environment]::NewLine)
$Stdout.Write($Bytes,0,$Bytes.Length) # That command will print on console.
$Stdout.Close()
[Console]::SetOut($OldConsoleOut)
$Results=$StringWriter.ToString()
$Results # That variable will be empty.
I have a process P, which calls the PSEXEC executable, and passes it an argument. My issue is that the output from my C# program is not the same from when I call exactly the same command directly into a command prompt.
Here is the output I expect (when ran from CMD):
Server Name Server Load
-------------------- ------------
601CTXD04 0
601CTXD05 0
...
601CTXP03 0
And here is the actual output (when ran from my program):
Server Name Server Load
-------------------- ------------
601CTXD04 0
So when I run the command from my C# program, I only get 1 server. I call the process the following way :
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = cServer.psexec; //Path to the PSEXEC executable
p.StartInfo.Arguments = "-accepteula \\\\601ctxp01 qfarm /load /continue";
p.Start();
string output = p.StandardOutput.ReadToEnd();
string[] lines = Regex.Split(output, "\\r\\n");
I really do not understand why, the exact same command ran from CMD does not give the same output when ran from a C# process. Please let me know what I am doing wrong as I am currently oblivious to my mistake.
You need to call p.WaitForExit() after p.StandardOutput.ReadToEnd(), otherwise you won't get all of the output from the process. Don't put it directly after p.Start() - you may get a deadlock. See http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput%28v=vs.110%29.aspx
It seems the issue was with PsExec itself (a Sysinternal utility) as I have tried an alternative called PAExec and the same command works fine, so I am using this one in my code instead.
Be sure to have the.
p.WaitForExit()
method after the line where you read the output. Here is an explanation from MSDN: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput(v=vs.110).aspx
I'm trying to troubleshoot why the following function isn't working.
public void RunCmd()
{
string strCmdText;
strCmdText = "/C [enter command stuff here]";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
However whenever I try to run it or throw in some breakpoints, command opens, shows an error, and then closes really quickly (so quickly that I can't read anything).
Is there a way I can halt the program or figure out what's going on? Breakpoints don't seem to be working.
When I directly type it in Command Prompt instead of running it via this c# script, it the command works fine.
try this:
strCmdText = "/K [enter command stuff here]";
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
Maybe try adding a pause command?
There are a various options. Using /K will prevent the window from closing.
You can also edit your command to add a SLEEP after the main call. For example, the following will wait 2 seconds before exiting:
public void RunCmd()
{
string strCmdText = "/C \"[enter command stuff here]\" & \"SLEEP 2\"";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
Process.Start has two parameters there: the process name and the arguments to pass to the process. CMD is having a problem understanding what the argument "[enter" is. If it is not an argument CMD understands, it will immediately exit.
cin.get()
That waits for a keyboard press from the user.
create temp folder under c: then append " < c:\temp\log.txt" to the end of command. this writes the output to a file
In addition to the tip about using /K vs /C to create a shell that 'lingers', you'll probably want to inject an empty "set" command to see what environmental variables (and paths) are set in the spawned shell. In all likelihood, the difference between the successful run of your script in your own shell session and the one that fails in the spawned shell, is the environment settings in which it is run.
I'm trying to copy a file over to a networked folder on a mapped drive. I tested out COPY in my command line which worked, so I thought I'd try automating the process within C#.
ProcessStartInfo PInfo;
Process P;
PInfo = new ProcessStartInfo("COPY \"" + "c:\\test\\test.txt" + "\" \"" + "w:\\test\\what.txt" + "\"", #"/Z");
PInfo.CreateNoWindow = false; //nowindow
PInfo.UseShellExecute = true; //use shell
P = Process.Start(PInfo);
P.WaitForExit(5000); //give it some time to finish
P.Close();
Raises an exception : System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
What am I missing? Would I have to add anything else to the command parameters?
I've tried File.Copy but it doesn't appear to work (File.Exists("<mappeddriveletter>:\\folder\\file.txt");) brings up false.
This SO post contains an example
Run Command Prompt Commands
how to do it right. You need to call cmd.exe with /c copy as a parameter.
Well, for the technical bit: copy in itself is not an executable, but merely a command interpreted by cmd. So basically, you'd have to start cmd.exe as a process, and pass it a flag that makes it run the copy command (which you'll also have to supply as a parameter).
Anyways, I'd side with Promit and recommend looking into File.Copy or something similar.
e: Ah, missed your comment on Promit's answer when I posted this.
Wouldn't it be a lot easier to use File.Copy ?