Here's something that I want to achieve:
Lets say I'm preparing abc.exe (console application).
I want to invoke cmd.exe and then launch abc.exe through cmd. And I won't be keeping cmd.exe in my projects folder. I'll be using it from system32 folder from user's machine.
Is it possible?
As mentioned in comments, you can use Process.Start(pathToExe) to launch a new process.
You can start your program in a new cmd with cmd /C start "Title" "C:\path\to\app.exe":
string cmdPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
string exePath = System.Reflection.Assembly.GetEntryAssembly().Location;
ProcessStartInfo newCmd = new ProcessStartInfo(cmdPath);
newCmd.Arguments = String.Format(#"/C start ""{0}"" ""{1}""", "WindowTitle", exePath);
Process.Start(newCmd);
You probably want some sort of conditional around that in order to not fork bomb yourself
Related
I have a program which wraps around some Windows SDK executables and opens them in a separate CMD window.
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/C signtool.exe [args] & pause";
process.StartInfo.Verb = "runas";
process.Start();
Right now, I have the Windows SDK folder added to my system's Path environment variable. Is there a way to programmatically add the Windows SDK folder to the Path environment variable of the user OR run the process with the SDK folder added to the Path variable of that particular CMD window?
This is the folder I need added to each CMD window's Path variable:
C:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86
This sub-process must run as administrator. It does not need to receive the output of the child process.
Use a ProcessStartInfo and its Environment property instance to set this up.
var startInfo = new ProcessStartInfo();
var defaultPath = startInfo.Environment["PATH"];
var newPath = "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.16299.0\\x86" + ";" + defaultPath;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/c set > D:\\env.txt";
startInfo.Verb = "runas";
startInfo.Environment["PATH"] = newPath;
startInfo.UseShellExecute = false; // required to use Environment variables
Process.Start(startInfo);
There are a number of hurdles to overcome here.
As you've discovered, the Environment and EnvironmentVariables properties of ProcessStartInfo cannot be used when UseShellExecute is true (an exception is thrown). But Verb only works when UseShellExecute is false (the Verb is silently ignored). This comes down to the differences between CreateProcess (the core Win32 function) and ShellExecute/ShellExecuteEx (the shell function).
As another commenter suggested, you might try setting the environment in the parent process and then starting the child process. However, elevated processes don't inherit the environment from a non-elevated parent process.
I would be willing to bet that there is a way to do what you want using a correct series of Win32 calls to get an elevated token and then calling something like CreateProcessAsUser. I am also willing to bet it'll be a little error-prone and ugly in C# because of the necessary struct marshaling. So instead of trying to figure that out for you, I'll offer another suggestion:
Just programmatically write a batch script that sets the environment and invokes signtool.exe. You can then invoke that batch script using the runas verb as you're currently doing.
I am trying to get the output of a process. I've achieved this by using a .bat, which contains the following text:
program.exe > output.txt < input.txt
where program.exe is my executable, output.txt is the file I want to output the data to and input.txt is just an empty file since the program wants key inputs from time to time. The .bat file works perfectly when I run it myself, but when I attempt to run it using C# code, it just doesn't finish properly.
I am trying to run it using the following code:
Process.Start(path);
I've tried a lot of different stuff but this is the code that I last tried but none of my attempts worked. Also, the .bat file doesn't run properly when you run it as an administrator and the C# program I am using is requiring administrator permissions. Could this be the issue and not the actual process running?
You need to run the process cmd.exe /c [path] (aka the process is "cmd.exe", and your arguments are $"/c {path}".
When you're on the command prompt you get "program execution" and ".bat/.cmd interactive scripting". Since you want to execute a batch file you need to tell CreateProcess that cmd.exe is what's actually running it.
In ProcessStartInfo you should set UseShellExecute to false, then set WorkingDirectory in the path where you found that the bat is working correctly.
Below is an example to make you understand better:
using (Process MyProcess = new Process())
{
var MyProcessInfo = new ProcessStartInfo()
{
UseShellExecute = false,
WorkingDirectory = "path",
FileName = "file.exe",
Arguments = "args"
};
MyProcess.StartInfo = MyProcessInfo;
MyProcess.Start();
}
The issue was just what I thought. The .bat file doesn't work properly when launched from an elevated app. To fix it I used this:
Process.Start("explorer.exe", path);
Worked perfectly. Fixed it really quickly but thought I'd leave this here if anybody finds himself stuck with the same thing.
Ok, so I'm having an issue starting the the Windows XP mode VM through a c# program. The command I'm using is vmwindow -file "absolute path to vmcx file" , but the problem is that the command does not work with the cmd prompt that my program kicks off. So, it's very weird. I can go to command prompt on my computer and run this command on my computer and it works, but if i have the same command on my c# program, the command prompt that pops up tells me the "vmwindow" is not a recognized command. I even looked at the paths of each of the command prompts and they're different, but they still both contain "C:\Windows\system32\" which is where vmwindow.exe exists. So, I navigate on the command prompt window that my program populated and the file "vmwindow.exe" is not there, but if I open a command prompt window from my computer and navigate to that folder, it exists there. I can't think of anything else as I already made sure they're both running in administrator mode, and also i tried starting a bat file which contained that command instead of running the command directly. Hope anyone knows anything about this. Here is the code I'm using:
private void button1_Click(object sender, EventArgs e)
{
Process process = new System.Diagnostics.Process();
ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
startInfo.WorkingDirectory = #"<my path>";
startInfo.Arguments = "/k vmwindow.exe -file \"<path to vcmx file>\\Windows XP Mode.vmcx\"";
process.StartInfo = startInfo;
process.Start();
}
What you can do is using Powershell. It has a native integration for Hyper V control and is easy to call from c#
You can see all HV-cmdlets here
a simple command to start your machine would be
Start-VM "Windows 8.1 Pro" -Computername HV-Host1
// etcetc
Stop-VM "Windows 8.1 Pro" -Save
So this should be something like this in C#
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("Start-VM "Windows 8.1 Pro" -Computername HV-Host1");
}
Probably it's because of the bitness setting you compile your program with. ("Platform target" and "Prefer 32-bit" settings under the build tab of the project).
32 and 64 bit processes see different files under System32.
See https://stackoverflow.com/a/950011
I have the below code to launch a cmd prompt and from that cmd prompt launch putty.exe with and IP address at the end.
private void btnRouter_Click(Object sender, EventArgs e)
{
MessageBox.Show((string)((Button)sender).Tag);
System.Diagnostics.Process cmd = new System.Diagnostics.Process();
cmd.StartInfo.FileName = #"C:\windows\system32\cmd.exe";
cmd.StartInfo.UseShellExecute = true;
cmd.Start();
cmd.StandardInput.WriteLine("Putty.exe " + ((string)((Button)sender).Tag));
cmd.WaitForExit();
}
Problem is I keep getting an error "StandardIn has not been redirected." from Visual Studio and when I try typing putty.exe in the command window that gets launched I get
"'putty.exe' is not recognized as an internal or external command,
operable program or batch file." which is REALLY weird because if I go to the run line, type cmd and then putty.exe it opens up immediately ever since I added the absolute folder path to the putty application to my system environment path.
Is there a reason the CMD opened from Visual Studio isn't using my Environment Path?
Still don't know why it is happening, however I went back to some previous code and put a copy of putty.exe in my debug folder and it launched successfully this time.
private void btnRouter_Click(Object sender, EventArgs e)
{
MessageBox.Show((string)((Button)sender).Tag);
System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "Putty.exe ";
startInfo.Arguments = ((string)((Button)sender).Tag);
myProcess.StartInfo = startInfo;
myProcess.Start();
}
This line will be causing the "StandardIn has not been redirected." error since you are trying to write to stdin and that handle has not be properly setup for input:
cmd.StandardInput.WriteLine("Putty.exe " + ((string)((Button)sender).Tag));
As to this question:
Is there a reason the CMD opened from Visual Studio isn't using my Environment Path?
When a parent process starts a child process that child process will inherit the environment of it's parent.
In other words the new cmd window you're starting will be inheriting the Visual Studio environment, but that does not mean the Visual Studio environment is the same as the environment of the command prompt.
You can test this by starting a command line prompt, running Visual Studio from that command line prompt and then creating your child cmd process.
Now your cmd process should have an environment matching the original command line plus any changes that Visual Studio added to it's copy of the environment.
Use the runas command.
http://technet.microsoft.com/en-us/library/cc771525.aspx
Can you run dir ?
I am writing a small utility to execute svn commands using c# program
Here is the key line in my program
System.Diagnostics.Process.Start("CMD.exe", #"svn checkout C:\TestBuildDevelopment\Code");
As I assume, the above code should be able to do svn check out and download all the code to the local path mentioned above. But what's happening is that, the command prompt opens up with the default path of the c# project and does nothing.
If I run this svn command in command line it works fine. But when I run using C# it just pops up the command prompt without executing the svn checkout operation. Any idea on what is going wrong?
You don t have to run CMD.exe. CMD.exe ist just a program that calls other assemblies.
You can call svn.exe directly with your argument checkout ... (but isnt there a url missing?)
Process.Start("svn.exe", #"checkout C:\TestBuildDevelopment\Code");
you may also try this:
Process proc = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "svn.exe";
startInfo.CreateNoWindow = true;
startInfo.Arguments = "checkout ...";
proc.StartInfo = startInfo;
if(proc.Start()) {
proc.WaitForExit();
}
You need to add the parameter /c. Try:
Process.Start("CMD.exe", #"/c svn checkout C:\TestBuildDevelopment\Code");
The parameter /c means that the cmd should execute the command and exit.
As Jon notes, svnsharp would be a good choice here; but IMO the problem is shelling cmd.exe, rather than the exe you actually want to run:
Process.Start(#"path\to\svn.exe", #"checkout ""C:\TestBuildDevelopment\Code""");
although a ProcessStartInfo would make it easier to set the working path etc.