Cmd not elevating when redirecting input/output - c#

I'm trying to run automated installations via CMD commands. The programs output progress and I need to capture that output and calculate total progress in a nice window. In my understanding it is impossible to elevate and redirect at the same time. I've tried...
Running cmd elevated and feeding it commands.
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Verb = "runas",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
proc.Start();
proc.StandardInput.WriteLine("command");
Running cmd with command as an argument
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/C " + "command",
Verb = "runas",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
proc.Start();
To no effect. Is there any tricks to this? Elevating after input/output has been captured? I need this to work. Would this be possible with psexec?

If you own the installer programs, you can rewrite them so that they do not use standard streams as a means of communication, but for example named pipes. If you don't, you can write a wrapper program that runs elevated (you run it with UseShellExecute), does not use the standard streams, but runs the installer programs and redirects their input (you run them without UseShellExecute) reporting progress to the nonelevated main program via named pipes or some other means. I hope this diagram makes it clearer:
non-elevated.exe
\
\ named pipes
\
elevated-wrapper.exe (ran with UseShellExecute=true)
\
\ redirected standard streams
\
installer-program.exe (ran with UseShellExecute=false and redirected streams)

Related

Running a batch file from a .NET 6.0 Windows Service in a window

This is supposed to be simple but I don't understand why it's not working. I'm trying to run a batch file (that runs a console application) from a .NET 6.0 Windows Service with this content:
#echo off
cd "C:\MyFolder"
MyExecutable.exe
pause
and I have this code:
var command = "\"C:\\Users\\Administrator\\Desktop\\mybatchfile.bat\"";
ProcessStartInfo start = new()
{
FileName = "cmd.exe",
Arguments = $"/c {command}",
UseShellExecute = false,
CreateNoWindow = false,
ErrorDialog = false,
RedirectStandardError = false,
RedirectStandardOutput = false,
WindowStyle = ProcessWindowStyle.Normal
};
Process.Start(start);
What's happening is that my console application (MyExecutable.exe) is executed, yet I do not see the Command window for it. It's launched in the background despite CreateNoWindow set to false and WindowStyle set to ProcessWindowStyle.Normal.

Programmatically execute commands in Windows Terminal using wsl

I am trying to run a python program in Ubuntu using wsl. I need to access Windows Terminal from C# application and execute commands in wsl. I am able to open the Windows Terminal. But cannot programmatically execute multiple commands after it.
I tried the below code. But the StandardInput.WriteLine is not working as I expected.
StartInfo = new ProcessStartInfo
{
FileName = #"wt.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = false,
Arguments = "wsl"
}
})
{
proc.Start();
proc.BeginOutputReadLine();
proc.StandardInput.WriteLine("cd Ubuntu/MyProject");
proc.StandardInput.WriteLine("python3 MyProgram.py ABC.wav");
}

Popup dialog from server to remote computer in local network

I'm trying to popup a dialog with some questions from a local network server
and receive the users answers, something like a winforms window, using c#.
Are there any recommendations for a way of doing this?
The solution I found was using PsExec tools.
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "path of psExec",
Arguments = $"psexec -i -s \\\\{machineName} {path}",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
proc.WaitForExit();`

ProcessStartInfo start "cmd.exe" to run "nvm" commands to install node versions pop up a program association error

I am trying to automate the machine setup using net core 2.0 with a console application, and I need to run some nvm commands to configure node versions.
I am trying to run a .bat file with the nvm commands that I need, but I am getting the following error:
This file does not have a program associated with it for performing this action. Please install a program or, if one is already installed, create an association in the Default Programs control panel.
If I execute the .bat file directly from cmd it works ok, but when my console app run it I get this error.
The 'file.bat' commands are:
nvm version
nvm install 6.11.4
nvm use 6.11.4
nvm list
npm --version
My csharp function to run the command:
public static int ExecuteCommand()
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", $"/C file.bat")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true
};
process = Process.Start(processInfo);
process.OutputDataReceived += (s, e) =>
{
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine("cmd >" + e.Data);
Console.ResetColor();
};
process.BeginOutputReadLine();
process.ErrorDataReceived += (s, e) =>
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.Data);
Console.ResetColor();
};
process.BeginErrorReadLine();
process.WaitForExit();
exitCode = process.ExitCode;
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
return exitCode;
}
My expectation is to have this working, because after that I will need to run several other commands, like npm install, gulp install, etc.
Any idea of what could be happening?
Based purely on testing, if you change this section:
processInfo = new ProcessStartInfo("cmd.exe", $"/C file.bat")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true
};
to not use the constructor arguments and instead manually set parameters like:
processInfo = new ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = $"/C file.bat",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true
};
should do the trick. Not sure on why, since from github code on ProcessStartInfo the constructor merely receives arguments and stores them on respective properties (FileName and Arguments).

Start process with IO stream redirection

How to start process and run command like this:
mysql -u root --password="some-password" < "some-file.sql"
Is it possible to do with process.Start()?
I need cross-platform solution (we cannot use cmd.exe).
Yes, this is possible through the System.Diagnostics.Process class. You need to set RedirectStandardInput to true, after which you can write the content of a file redirect the standard input of a process, and write the contents of the file to the Process.StandardInput (which is a StreamWriter)
This should get you started:
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "mysql.exe", // assumes mysql.exe is in PATH
Arguments = "-u root --password=\"some-password\"",
RedirectStandardInput = true,
UseShellExecute = false
},
};
process.Start();
process.StandardInput.Write(File.ReadAllText("some-file.sql"));
Update: this is pretty well documented [here](
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.redirectstandardinput)

Categories