Process.Start() totally ignore the environment variables in PATH - c#

I found that my cmd window prompted by Process.Start() totally ignore my environment variables in PATH. It always said that "xxx is not internal or external commands". I tried run it manually and it worked. Therefore, I am sure the PATH has been set correctly.
I also tried to add the variable explicitly. It still did not work.
This is my code:
public static string ExecuteCommandSync(string command)
{
try
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("C:\\Windows\\System32\\cmd.exe", "/K " + command);
var length = command.Length;
procStartInfo.RedirectStandardOutput = false;
procStartInfo.UseShellExecute = false;
//Does not work
procStartInfo.EnvironmentVariables.Add("PATH", "C:\\Program Files\\Arm\\Arm Mobile Studio 2021.0");
procStartInfo.CreateNoWindow = false;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
}
catch (Exception objException)
{
return objException.ToString();
}
}

It is better when you did add the complete description of the error, in stead of "does not work"
System.ArgumentException: Value does not fall within the expected
range. at
System.Collections.Specialized.StringDictionaryWrapper.Add(String key,
String value) at ConsoleApp88.Program.ExecuteCommandSync(String
command) in
You cannot add PATH because it is already in the list of environment variables.
Solution can be to add the next statement, just before the add:
procStartInfo.EnvironmentVariables.Remove("PATH");

Related

Executing Batch File At This Directory

I have this code piece that used in my c# form project. I also have exp.bat file contains shell commands as below.
But whatever I do, it does not create .txt file at working directory.
#echo off
echo "hello" > test.txt
path = #"‪C:\Users\abc\Desktop\exp.bat";
startingPath = #"C:\Users\abc\Desktop\";
bool success = false;
try
{
System.Diagnostics.ProcessStartInfo ProcStartInfo = new
System.Diagnostics.ProcessStartInfo("cmd");
ProcStartInfo.RedirectStandardOutput = true;
ProcStartInfo.UseShellExecute = false;
ProcStartInfo.CreateNoWindow = false;
ProcStartInfo.RedirectStandardError = true;
System.Diagnostics.Process MyProcess = new System.Diagnostics.Process();
ProcStartInfo.Arguments = "/c start /wait"+path;
ProcStartInfo.WorkingDirectory = startingPath;
MyProcess.StartInfo = ProcStartInfo;
success = MyProcess.Start();
MyProcess.WaitForExit();
}
catch (Exception ex) { string s = ex.StackTrace.ToString();}
Originally posted by use Mofi in comments.
posting the same answer as is so this question is not counted in unanswered, question author also confirms in comments that the answer by Mofi was correct and it helped.
I think enough background, here is the comment as the answer.
In C# code use the method Environment.GetEnvironmentVariable to get the string value of predefined Windows environment variable USERPROFILE to build the paths for exp.bat and starting directory dynamically already within C# application. Or even better get current user desktop folder directly, see How to get a path to the desktop for the current user in C#? – Mofi Feb 22 at 12:25
You can easily achieve that by adding the following commands to the beginning of your bat file.
%~d0
cd %~dp0

Running cmd programmatically only returns some outputs [duplicate]

This question already has answers here:
Trying to get StandardOutput after running a console process
(2 answers)
Closed 5 years ago.
I'm running a CMD in c# programmatically and everything works fine, it will run whatever command I input but when I ask to return the output to the console, only some commands output gets returned.
For example if I write "ipconfig" as the command, it will return my ip info but if I write "/ipconfig", it will just return "/ipconfig" as appose to "/ipconfig is not recognized as an interal ..." you get the idea. I also tried it with deleting files, the file deletes just fine but if the file doesnt exist, it should output "could not find file" like it does it normal cmd. It seems it only gives me the output of a command thats runs and not one that doesnt even though I read the cmd till the end of anything it outputs. If this is the case is there anyway to get around this?
Code:
private void Form1_Load(object sender, EventArgs e)
{
string command = "/ipconfig";
string root = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
Console.WriteLine(Command(command, root));
}
public string Command(string command, string directory)
{
string commandOutput;
commandOutput = DateTime.Now + Environment.NewLine + command + Environment.NewLine;
ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.WorkingDirectory = directory;
procStartInfo.RedirectStandardError = true;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
commandOutput += proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
return commandOutput;
}
I'm pretty sure cmd.exe will write that to standard error, not standard output. If that is the case, you'll need to use proc.StandardError.ReadToEnd() to get the error message.

"The system cannot find the file specified" error on process.Start();

I am trying to get the process respond as a string so I can use it in different place in my code, this is the solution that I have so far:
const string ex1 = #"C:\Projects\MyProgram.exe ";
const string ex2 = #"C:\Projects\ProgramXmlConfig.xml";
Process process = new Process();
process.StartInfo.WorkingDirectory = #"C:\Projects";
process.StartInfo.FileName = "MyProgram.exe ";
process.StartInfo.Arguments = ex2;
process.StartInfo.Password = new System.Security.SecureString();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
try
{
process.Start();
StreamReader reader = process.StandardOutput;
string output = reader.ReadToEnd();
}
catch (Exception exception)
{
AddComment(exception.ToString());
}
But when I'm running this I get:
"The system cannot find the file specified" error in process.Start(); without
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
The code runs fine but it just open console window and all the process response is trow there so I can't use it as string.
Does anyone know why I am getting this error or maybe a different solution to my problem?
I suspect the problem is that the filename you're specifying is relative to your working directory, and you're expecting Process.Start to look there when starting the process - I don't believe it works that way when UseShellExecute is false. Try just specifying the absolute filename of the process you want to start:
process.StartInfo.FileName = #"C:\Projects\MyProgram.exe";
Note that I've also removed the space from the end of the string you were assigning for the FileName property - it's entirely possible that was casuing the problem too.
For System32 access if you are trying to RUN an x86 Application on x64 then you must use the "Sysnative" keyword instead of "System32" in your filename.
EG: instead of:
C:\Windows\System32\whoiscl.exe
It should be:
C:\Windows\Sysnative\whoiscl.exe
Hope this helps someone

C# process can not execute batch file (contain timeout command) correctly

I'd like to execute a batch file without showing terminal window
and I need to get the standard output contents.
Here is the batch file:
timeout /T 5
exit 0
Below is my partial C# code:
static void Main(string[] args)
{
bool ShowTerminal = true;
Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
string ExecContent = "\"" + args[0] + "\"";
proc.StartInfo.Arguments = "/c " + ExecContent;
proc.StartInfo.UseShellExecute = ShowTerminal;
proc.StartInfo.RedirectStandardError = !ShowTerminal;
proc.StartInfo.RedirectStandardInput = !ShowTerminal;
proc.StartInfo.RedirectStandardOutput = !ShowTerminal;
proc.Start();
proc.WaitForExit();
}
I found that variable ShowTerminal set true, then everything is going well
except I can not get standard output contents
But if variable ShowTerminal set false, timeout command will be skipped
Is there any solution for this problem? Thanks!
If you specify "redirect" options you should also provide their redirection streams (STDIN, STDOUT) and ensure they are being emptied/read/processed as CMD would expect.
Chances are good that 'timeout' is failing to detect any STDIN/STDOUT and therefore performs a noop.

Process.Start() fails to open the exe

I'm trying to launch an application from c# code. Below is the code.. But the exe gives the error "Application has encountered a problem and needs to close. Sorry for the inconvenience".
I'm passing the command values as
command = "\"C:\\Program Files\\Nimbuzz\\Nimbuzz.exe\"";
code:
private int ExecuteSystemCommand(string command)
{
procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = false;
proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
return proc.Id;
}
But the exe opens normally when opened from the desktop short cut. I dont know whats wrong. Please suggest.
You must specify the EXE you want to execute.
Process.Start("cmd.exe", ...)
It would appear that these articles answer the question:
ProcessStartInfo.UseShellExecute
ProcessStartInfo.FileName
Well I just found out that, I need to set the Working directory first before calling the Process.Start()
Directory.SetCurrentDirectory("C:\\Program Files\\Nimbuzz\\");

Categories