I have a cmd command to start/stop application pool in server/windows and it works:
My problem is same code doesnt work in c#, code returns no error or info.
C# Code:
public static string StopAppPoolCmd
{
get { return "cd %SYSTEMROOT%/System32/inetsrv & appcmd stop apppool /apppool.name:\"{0}\""; }
}
public static string StartAppPoolCmd
{
get { return "cd %SYSTEMROOT%/System32/inetsrv & appcmd start apppool /apppool.name:\"{0}\""; }
}
// Run Commands
var cmd = new System.Diagnostics.Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
/* execute "dir" */
cmd.StandardInput.WriteLine(string.Format(start ? StartAppPoolCmd : StopAppPoolCmd, serviceName));
//flush object
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
//
// OUTPUT
var result = Tools.CleanShellOutput(cmd.StandardOutput.ReadToEnd());
Console.WriteLine(result);
Related
i am trying to call and collect the data returned by the CMD command query user.
Calling this via cmd from the Windows-startbar gives me a normal result.
Calling this via this c# function give 0 output.
public void callQueryUser()
{
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe");
Process p = Process.Start(psi);
string cmd = string.Format(#"/c query user");
psi.Arguments = cmd;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.WaitForExit();
string result = p.StandardOutput.ReadToEnd();
MessageBox.Show(result);
}
I checked and the Window says command cant befound... I also check if they are both the same cmd.exe and thats also true. It seems like calling the cmd.exe via C# makes somewhat of a differences.
Anyone any idea what i could check next ?
It's not necessary to use cmd to retrieve the information you want using Process. However, if your OS is 64-bit, your program is running as 32-bit, and you're trying to access %windir%\System32\query.exe, you need to use %windir%\Sysnative\query.exe instead.
Try the following:
Option 1:
public void callQueryUser()
{
string queryPath = string.Empty;
//use 'Sysnative' to access 64-bit files (in System32) if program is running as 32-bit process
//use 'SysWow64' to access 32-bit files on 64-bit OS
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
queryPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "Sysnative", "query.exe");
else
queryPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "query.exe");
Debug.WriteLine("queryPath: " + queryPath);
// create new instance
ProcessStartInfo startInfo = new ProcessStartInfo(queryPath);
startInfo.Arguments = "user"; //arguments
startInfo.CreateNoWindow = true; //don't create a window
startInfo.RedirectStandardError = true; //redirect standard error
startInfo.RedirectStandardOutput = true; //redirect standard output
startInfo.UseShellExecute = false; //if true, uses 'ShellExecute'; if false, uses 'CreateProcess'
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
//create new instance
using (Process p = new Process { StartInfo = startInfo, EnableRaisingEvents = true })
{
//subscribe to event and add event handler code
p.ErrorDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
//ToDo: add desired code
Debug.WriteLine("Error: " + e.Data);
}
};
//subscribe to event and add event handler code
p.OutputDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
//ToDo: add desired code
Debug.WriteLine("Output: " + e.Data);
string result = e.Data;
MessageBox.Show(result);
}
};
p.Start(); //start
p.BeginErrorReadLine(); //begin async reading for standard error
p.BeginOutputReadLine(); //begin async reading for standard output
//waits until the process is finished before continuing
p.WaitForExit();
}
}
Option 2:
public void callQueryUser()
{
string queryPath = string.Empty;
//environment variable windir has the same value as SystemRoot
//use 'Sysnative' to access 64-bit files (in System32) if program is running as 32-bit process
//use 'SysWow64' to access 32-bit files on 64-bit OS
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
queryPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "Sysnative", "query.exe");
else
queryPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "query.exe");
Debug.WriteLine("queryPath: " + queryPath);
// create new instance
ProcessStartInfo startInfo = new ProcessStartInfo(queryPath);
startInfo.Arguments = "user"; //arguments
startInfo.CreateNoWindow = true; //don't create a window
startInfo.RedirectStandardError = true; //redirect standard error
startInfo.RedirectStandardOutput = true; //redirect standard output
startInfo.UseShellExecute = false; //if true, uses 'ShellExecute'; if false, uses 'CreateProcess'
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
//create new instance
using (Process p = new Process { StartInfo = startInfo, EnableRaisingEvents = true })
{
p.Start(); //start
//waits until the process is finished before continuing
p.WaitForExit();
string result = p.StandardOutput.ReadToEnd();
MessageBox.Show(result);
}
}
Resources:
Accessing files from System32 directory using 32 bit application on 64 bit machine
Process Class
ProcessStartInfo Class
Environment.GetEnvironmentVariable Method
I am getting wired problem with a process that is started by my c# application,in my application i start a process that runs a ffmpeg command which executes well but when in any how if i closes my application then that process still continues to executes.
private static bool RunRecordProcess(string command)
{
Process process = new Process();
try
{
ProcessStartInfo processStartInfo = new
ProcessStartInfo(Application.StartupPath +
FFMPEG_EXE_FILE_PATH);
processStartInfo.UseShellExecute = false;
processStartInfo.Arguments = "-hide_banner -loglevel 8 " +
command;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
processStartInfo.CreateNoWindow = true;
processStartInfo.Verb = "";
process.EnableRaisingEvents = true;
process.StartInfo = processStartInfo;
process.Start();
string error = process.StandardError.ReadToEnd();
if (error.Length > 0)
{
if (!process.HasExited)
{
process.Kill();
//throw new Exception("Failure some error occured");
}
}
process.WaitForExit();
}
catch(Exception ex)
{
process.Kill();
ExceptionHandler.handleException(ex);
return false;
}
return true;
}
What i want is when my application exits my process that is started by the application will automatically exit so that no useless process will be using my system Cpu.
Thankyou!
You should create job object (CreateJobObject function in kernel32). There is more description:
https://tulisanlain.blogspot.com/2016/08/kill-child-process-when-parent-exit-c.html
I am launching an exe using below code.I am able to run exe successfully but it haults for user input which asks user to enter a character'y' or 'n'(i.e. yes/No).What I want is that while running exe (silent installation i.e. no cmd window is available or no user interaction) i should be able to pass 'y' character as user input.
Below is my code
public bool launchExe(exeFilepath)
{
bool status = true;
try
{
using (var myProcess = new Process())
{
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.UseShellExecute = true;
myProcess.EnableRaisingEvents = true;
myProcess.StartInfo.WorkingDirectory = exeFilepath;
myProcess.StartInfo.FileName = "Launcher.exe";
myProcess.Start();
myProcess.WaitForExit();
if (myProcess.ExitCode == 0)
status = true;
else
status = false;
}
}
catch (Exception ex)
{
Logger.Information(ex.Message);
status = false;
}
return status;
}
Use ProcessStartInfo.RedirectStandardInput to write to your launched Process:
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.EnableRaisingEvents = true;
myProcess.StartInfo.WorkingDirectory = exeFilepath;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.Start();
Thread.Sleep(1000); // wait 1 second
StreamWriter myStreamWriter = myProcess.StandardInput;
myStreamWriter.WriteLine("y");
I am simply trying to open the console and write a single line and execute it with the console staying open once the line is written. Currently, the command line is opening blank and not writing anything. Any way to fix this?
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = false;
cmd.Start();
cmd.StandardInput.WriteLine("echo hello");
cmd.StandardInput.WriteLine("pause");
cmd.WaitForExit();
This will fix it:
cmd.StartInfo.RedirectStandardOutput = false;
This works perfect for me:
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.RedirectStandardInput = true;
//cmd.StartInfo.RedirectStandardOutput = true;
cmd.Start();
cmd.StandardInput.WriteLine("pause");
System.Threading.Thread.Sleep(5000);
cmd.StandardInput.WriteLine(" ");
cmd.StandardInput.WriteLine("dir /p");
cmd.StandardInput.WriteLine("exit");
cmd.WaitForExit();
}
}
}
You could most likely just issue a pause:
cmd.StandardInput.WriteLine("pause");
Should solve it.
Remember to add:
cmd.StartInfo.RedirectStandardInput = false;
If that does not work then most likely still an issue, as reported at Microsoft regarding CMD specifically and output. See: http://connect.microsoft.com/VisualStudio/feedback/details/609801/unable-to-redirect-only-the-standard-input-of-process-cmd-exe-or-batch-file-from-windows-form-application
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.Arguments = "/K \"echo hello\"";
cmd.Start();
What I'm trying to do
Launch PSExec to open CMD on a remote computer passing "Net Use * \Server\Share" command
Launch PSExec again and remove the share i just created.
I can't seem to figure out how to get the drive letter that the wild card used.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = #"\\Server\PStools\PSExec.exe";
p.StartInfo.Arguments = #"\\ComputerName -e -s cmd.exe ""/C Net USE * \\Server\Share /Persistent:NO""";
p.Start();
The net use command with a wildcard will pick the first available drive letter in the sequence from Z to A. It reports the selected drive letter in the console output like so:
C:\>net use * \\server\share
Drive Z: is now connected to \\server\share.
The command completed successfully.
C:\>_
So what you need is to capture the output of the PSExec command and parse it to find the allocated drive letter.
I haven't tried this with PSExec as yet, but this is the code I use for capturing the output of commands via cmd.exe:
static class CommandRunner
{
static StringBuilder cmdOutput = new StringBuilder();
public static string Run(string command)
{
if (string.IsNullOrWhiteSpace(command))
return null;
using (var proc = new Process())
{
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c " + command;
proc.StartInfo.LoadUserProfile = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.UseShellExecute = false;
proc.EnableRaisingEvents = true;
proc.OutputDataReceived += proc_DataReceived;
proc.ErrorDataReceived += proc_DataReceived;
try
{
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
catch (Exception e)
{
cmdOutput.AppendLine("***Exception during command exection***");
cmdOutput.AppendLine(e.Message);
cmdOutput.AppendLine("*** ***");
}
}
return cmdOutput.ToString();
}
static void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
cmdOutput.AppendLine(e.Data);
}
}
To get the output of a command on the local machine call it like this:
string output = CommandRunner.Run("net use");
Shouldn't be too hard to add a method that executes commands on a remote PC using PSExec instead of the local cmd.exe. Something similar to the following:
public static string Remote(string target, string command, string peFlags = "-e -s")
{
if (string.IsNullOrWhiteSpace(command))
return null;
using (var proc = new Process())
{
proc.StartInfo.FileName = #"C:\PSTools\PSExec.exe";
proc.StartInfo.Arguments = string.Format(#"\\{0}{1} cmd.exe ""/c {2}""", target, peFlags == null ? "" : " " + peFlags, command);
proc.StartInfo.LoadUserProfile = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.EnableRaisingEvents = true;
proc.OutputDataReceived += proc_DataReceived;
try
{
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
catch
{ }
}
return cmdOutput.ToString();
}
NOTE: I removed the stderr redirection here because I want only the output of the remote program, not the various lines added to the output by PSExec.