I'm trying to run a remote batch file - already located on the remote machine - using PsExec, called via Process in C#. I've confirmed that all required files already exist, but believe I may have a problem with my syntax, as the redirected output indicates that it can't find the file specified.
The machine against which PsExec runs is dynamic, which is the myArray[0].MachineName value (this pulls in without issue).
wsStopProcess.StartInfo.FileName = #"C:\Windows\system32\PsExec.exe";
wsStopProcess.StartInfo.Arguments = #" \\" + myArray[0].MachineName + #"D:\stopprofile.bat";
wsStopProcess.StartInfo.UseShellExecute = false;
wsStopProcess.StartInfo.CreateNoWindow = true;
wsStopProcess.StartInfo.RedirectStandardOutput = true;
wsStopProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
wsStopProcess.Start();
Any ideas on what appears to be formatted incorrectly? I'm guessing it's too many backslashes (or not enough!) somewhere.
I think the main problem is you do not have a space between the two arguments.
Try this:
wsStopProcess.StartInfo.Arguments = #"\\" + myArray[0].MachineName + #" D:\stopprofile.bat";
I would also warn you that I could not get psexec to work 100%, despite trying many different things.
Try this:
wsStopProcess.StartInfo.Arguments = #"\\" + myArray[0].MachineName + #" D$\stopprofile.bat";
So instead of using : try $ sign. Also setting breakpoint on the above line while debugging will help you to see the exact path.
Related
I have created a script using Python2.7 and compiled it using pyinstaller into an exe of the same name, in this case "GeneralStats.py" turns into "GeneralStats.exe" using --onefile and -w arguments.
When called with C# I use:
var pythonDirectory = (Directory.GetCurrentDirectory());
var filePathExe1 = Path.Combine(pythonDirectory + "\\Python\\GeneralStats.exe");
Process.Start(filePathExe1);
When called outside of C#, so in my local files I can run the .exe and the result is a text file with lots of values in (Running correctly).
However, when ran with C# in this format, I get an error that "GeneralStats returned -1!"
Which I have had issues with before, but it was a simple python error that when I returned to my code and ran it, I would receive an error that I overlooked.
This time my python code returns no errors and works outside of C#.
Any ideas of why this could be? I can provide any code or file directories necessary, please just ask if you feel it would help with debugging.
EDIT:
Solved by removing:
var filePathExe1 = Path.Combine(pythonDirectory + "\\Python\\GeneralStats.exe");
Process.Start(filePathExe1);
And replacing with:
ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = Path.Combine(pythonDirectory + "\\Python");
_processStartInfo.FileName = #"GeneralStats.exe";
_processStartInfo.CreateNoWindow = true;
Process myProcess = Process.Start(_processStartInfo);
You need to set the working directory for the Process - it is probably trying to load files from its working directory but isn't finding them.
See, e.g. this:
Use the ProcessStartInfo.WorkingDirectory property to set it prior to starting the process. If the property is not set, the default working directory is %SYSTEMROOT%\system32.
Set it to the path where GeneralStats.exe is.
I'm trying to run this command with several quotation marks:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server="10.10.10.10:9999" -user-data-dir=C:\filterbypass www.example.com"
I've tried adding backslashes to the before C and after com, no luck
Tried assigning it to a string
string \"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server="10.10.10.10:9999" -user-data-dir=C:\filterbypass www.example.com\"
with hopes to run the command like that, but still nothing.
try
{
System.Diagnostics.Process.Start(#"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server="10.10.10.10:9999" -user-data-dir=C:\filterbypass www.example.com");
}
catch { }
Can anyone show me where I'm going wrong here? Thanks,
You need to separate the binary to run from the arguments. I would recommend using ProcessStartInfo to make this clearer:
var info = new ProcessStartInfo
{
FileName = #"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
Arguments = "--proxy-server=10.10.10.10:9999 " +
#"--user-data-dir=C:\filterbypass " +
"www.example.com"
};
var process = Process.Start(info);
(Note the use of -- for the user-data-dir switch, by the way - it looks like all the command line flags are prefixed with --, not -. It's possible that it works both ways...)
no error. no exception. Second and Third produce a file f[1]/[2]. but not first. why? I verify using debug that the command is good. and using the command I capture from debug , cut and past to command line, I can produce the file[f0].
string[] f = new string[4];
f[0] = "SNICKER.reg.txt";
f[1] = "SNDIS.reg.txt";
f[2] = "SNICS.reg.txt";
f[3] = "Ssmf.xml";
//First
Run_Process("REG", "EXPORT HKEY_LOCAL_MACHINE\\SOFTWARE\\sridge\\Snicker " + f[0] + " /y");
//Second
Run_Process("REG", "EXPORT HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\services\\SNDIS " + f[1] + " /y");
//Third
Run_Process("REG", "EXPORT HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\SClass " + f[2] + " /y");
private static void Run_Process(string exe_name, string arg)
{
Process myProcess = new Process();
try
{
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.FileName = exe_name;
//myProcess.StartInfo.Arguments = "/C getLH.exe > feed.txt";
myProcess.StartInfo.Arguments = arg;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
myProcess.WaitForExit();
}
catch (Exception ep)
{
Console.WriteLine(exe_name + " " + arg + ". Error: " + ep.Message);
}
}
When your app runs on a 64bit OS and you try to access the registry you could end up reading the values in the wrong folders.
This happens when you compile for x86 Platform, and thus your code is emitted as 32bit code.
In this scenario the registry redirector kicks in and changes your hand made registry paths that point to folders inside HKLM\SOFTWARE to HKLM\SOFTWARE\Wow6432Node.
The reasoning behind this behavior is complex and you could try to read something here
Said that, I still cannot understand really well what happen when we put in this scenario the REG program executed as a process launched from an application built with AnyCPU. This application should be executed as a 64bit code but, for some reason, the REG program executed is the 32 bit version (yes, there are two version of REG.EXE, one in system32 and one in SysWow64) and this version search your data in the wrong path. Perhaps this is related to the current value of the PATH environment variable.
As a side note. One of the worst decision ever made by Microsoft is to allow applications to store their configuration data in the registry. I really suggest to change this behavior, if possible
UPDATE
I can confirm that on a 64bit OS, a console application compiled as AnyCPU running the code that executes the REG.EXE command as above launches the 32bit version of REG.EXE from the WINDOWS\SYSWOW64. I have checked with ProcMon and I cannot explain why this happens. It is not related to the PATH env variable because I have only the path to C:\WINDOWS\SYSTEM32
Check out Process.start: how to get the output? and try to use that method to see the output of your command. I don't think there will be any exception, because it will only catch the exception of that block of code, not the exception of outside program that you attempt to 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 ?
Given code was a part of the code used to run a jar file on c# environment. Complete Code
strArguments = " -jar "+ Argument list;
processJar.StartInfo.FileName = "\"" + #"java" + "\"";
processJar.StartInfo.Arguments = strArguments;
processJar.StartInfo.WorkingDirectory =; \\Give the working directory of the application;
processJar.StartInfo.UseShellExecute = false;
processJar.StartInfo.RedirectStandardOutput = true;
I know that processJar.StartInfo.FileName should contain the jave.exe so that the respective file will be triggered when the process gets started. But the above given code also runs successfully.
Question:
What does "\"" + #"java" + "\"" here? If I provide such input will the system itself will search java.exe?
They simply ensure that the string will be "java" (with the quotes).
This is normally needed when you have a path that contains spaces.
Windows requires the path to be quoted if it contains spaces (for example "C:\Program Files").
As for finding the executable - if the path to the java executable is in the %PATH% environment variable, it will be found.
In this case they seem superfluous.
its the exe name which needs to be launched