Two commands on a process - c#

I have an exe which I can run in console like below
util.exe argument1
I need to invoke this from a CSharp application which I can do like below
private string Command(string arg)
{
var p = new Process
{
StartInfo =
{
FileName = "util.exe",
Arguments = arg,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true,
UseShellExecute = false
}
};
var stdOutput = new StringBuilder();
p.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data);
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
return stdOutput.ToString();
}
var result = Command(argument1) //call
However there is an issue. util.exe authenticates user using the Windows logged in credentials. In the application I need to execute the commands as a different user(Like below)
util.exe login funcationaluser fuucntioanluserpwd
util.exe argument1
What is the right way for doing this? Can I reuse the process?
Edit: Please note the username and password is specific to util.exe , not a system username/password

Related

Determine if a command has been finished executing in CMD in C# [duplicate]

This question already has answers here:
Determining end of console output
(1 answer)
C# StandardOutput hangs, how can I detect it's waiting for input?
(2 answers)
Closed 2 years ago.
Introduction
I am creating a R.A.T (Remote Administration Tool) In c# with TCP client-server configurations.
Everything was going quite fine until I realized a need to detect whether or not a command has been finished executing in a command-prompt process created by my c# application.
Please have a look at the code below.
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void StartCMD()
{
ProcessStartInfo PSInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) => { /*Do something with e.Data*/ };
CMDProc.ErrorDataReceived += (s, e) => { /*Do something with e.Data*/ };
ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
}
What I Want To Achieve
As you may guess that ping command takes variable amount of time to complete depending upon the speed of the internet connection, now what I want is to run a method called CMDCommandExecuted() when a long running command like "ping" finished executing in the terminal which was invoked using the c# code ToCMDShell.WriteLineAsync("any dos command to execute");.
What I Had Tried Till Now
I tried to read the e.Data from the output stream received from the CMDProc.OutputDataReceived Event-Handler but had no luck, because maybe for some other long running commands other than the ping no data at all is being written to the output stream so it is not a bulletproof solution.
And yes I had tried to search for my solutions on the internet as well, yet no luck!
That's why I am here seeking for your help.
It appears that the WriteLineAsync doesn't complete until the long running command does (e.g. the command window is ready for new input), so you just need to Wait on the return from WriteLineAsync when you need to send more data, or know the previous command is done.
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void StartCMD() {
ProcessStartInfo PSInfo = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = "/k",
CreateNoWindow = false,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine($"ERR: {e.Data}");
var run = ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
// do some stuff
run.Wait(); // wait for long command to complete
ToCMDShell.WriteLine("exit"); //Done
}
Use CMDProc.WaitForExit() to wait for completion and CMDProc.ExitCode to get final status code.
If you get some data from the stream that indicates the process is hung or frozen or needs to be killed, call CMDProc.Kill().
If you get some data from the stream that indicates you should do something else, you can spawn other processes or send additional WriteLine calls to the process to do further processing.
The following program sends the ping command output back to me correctly. Maybe you just need that wait command or a console read line to give it time.
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MyNamespace
{
class Program
{
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void Main()
{
StartCMD();
}
public static void StartCMD()
{
ProcessStartInfo PSInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) =>
{
Console.WriteLine("PROC: {0}", e.Data);
if (e.Data != null && e.Data.Contains("Average ="))
{
// last line, you don't have to exit here, you could do something else instead...
ToCMDShell.WriteLine("exit");
}
};
CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine("PROC ERR: {0}", e.Data);
ToCMDShell.WriteLine("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
CMDProc.WaitForExit();
Console.WriteLine("Job done, press ENTER to quit");
Console.ReadLine();
}
}
}

Run bash from .Net Core independent from main process linux c#

Hi have a service which needs to execute it's updated shell script independent from the .Core process. I have tried /bin/bash, /bin/nohup and /bin/setsid. But every time the script stops the systemd service the script seems also to be stopped. How do I get this independent?
private static Process StartLinuxUpdateScript(string pathToUpdateScript, string pathToUpdateZip)
{
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/setsid",
UseShellExecute = true,
Arguments = $" bash {pathToUpdateScript} {pathToUpdateZip}"
}
};
return process;
}
maybe it helpfull:
public void RunProcess(string fileName, string arg)
{
var process = new Process
{
StartInfo =
{
RedirectStandardOutput = true,
RedirectStandardError = true,
FileName = fileName,
Arguments = arg ,
UseShellExecute = false,
CreateNoWindow = true
},
EnableRaisingEvents = true
};
process.Start();
string processOutput;
while ((processOutput = process.StandardError.ReadLine()) != null)
{
Console.WriteLine(processOutput);
}
process.Dispose();
}

Launch process that needs to trigger UAC in netcore

I often need to launch external processes so I wrote a convenient method to easily do that. One of these processes needs to trigger UAC in order to ask the user for their permission. I did some research and found that setting the Verb property of the ProcessStartInfo object to runas in addition to setting the UseShellExecute to true should do the trick.
private static void StartProcess(string fileName, string arguments, bool elevated)
{
var start = new ProcessStartInfo
{
UseShellExecute = false,
CreateNoWindow = true,
Arguments = arguments,
FileName = fileName
};
if (elevated)
{
start.Verb = "runas";
start.UseShellExecute = true;
}
int exitCode = 0;
using (var proc = new Process { StartInfo = start })
{
proc.Start();
proc.WaitForExit();
exitCode = proc.ExitCode;
}
if (exitCode != 0)
{
var message = string.Format(
"Error {0} executing {1} {2}",
exitCode,
start.FileName,
start.Arguments);
throw new InvalidOperationException(message);
}
}
However, the Verb property is not available in netcore therefore I can't figure out how to achieve the same result. Any suggestion?

C# pass password via StandardInput of Process

The next C# method invokes rasdial VPN-Name name *. * means enter password from keyboard. But I want to pass the password to the process from C# application.
public bool connect(UserCredentials userCredentials)
{
// "Dial" to VPN
var psi = new ProcessStartInfo("rasdial")//("cmd")
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
//CreateNoWindow = true,
UseShellExecute = false, // Unusable if Streams redirected
Arguments = $"{InterfaceName} {userCredentials.name} *"
};
var proc = new Process {
StartInfo = psi
//,EnableRaisingEvents = true
};
proc.Start();
// PASS PASSWORD VIA STDIN. Does not work. Keyboard input FORCED!
//proc.WaitForInputIdle();
proc.StandardInput.WriteLine(userCredentials.pass);
proc.WaitForExit();
return true;// proc.ExitCode == 0; // Can throws "Not exited yet"
}
Is there a way to pass the password to rasdial?
I can invoke rasdial VPN-Name login passwd. Such method is security lack. DEPRECATED. Any schoolboy can monitor process's args.
One workaround
static Process runProcRasdial()
{
ProcessStartInfo psi = new ProcessStartInfo("cmd") {
RedirectStandardInput=true,
RedirectStandardOutput=false,
UseShellExecute=false
};
var proc = new Process(){
StartInfo = psi,
EnableRaisingEvents = true,
};
proc.Start();
proc.StandardInput.WriteLine("rasdial rapa /disconnect");
proc.StandardInput.WriteLine("rasdial rapa Ivan paswd!");
//proc.Exited += Proc_Exited1;
proc.StandardInput.WriteLine("exit");
proc.WaitForExit();
return proc;
}
If pack paswd! to SecureString if could look like something normal.

Redirecting standard output of a process in C# (Permissiong bug)

I wrote an app in C# (WPF) which takes remote hosts data (using Psexec).
The app requires you to be with high privileges (Administrator).
I have this kind of code in my app:
var proc = new Process {
StartInfo = new ProcessStartInfo {
FileName = "psexec.exe",
Arguments = "\\\\" + ip + " ipconfig",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
proc.Start();
if (!proc.WaitForExit(60000))
proc.Kill();
output_error = proc.StandardError.ReadToEnd();
output_stan = proc.StandardOutput.ReadToEnd();
If i'm running the app from Visual Studio (In debug mode), i get an output, but when i'm running the app from the exe file the standard redirected output which is just empty.
Does anyone has a possible solution for this?
*The output which is redirected as an error is a standrad psexec output which says basiclly that the command worked just find (error 0).
Thx.
From MSDN:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// To avoid deadlocks, always read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
In particular note how you shouldn't wait before reading to the end of the stream otherwise you might be getting deadlocks.
I have modified your code to do it this way, and the following works fine for me:
static void Main(string[] args)
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "ping.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
proc.Start();
string output_error = proc.StandardError.ReadToEnd();
string output_stan = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
Trace.TraceInformation(output_stan);
}

Categories