Run CheckDisk with RedirectStandardOutput - c#

Running ChkDsk without redirecting StandardOutput works without an error like this:
var processStartInfo = new ProcessStartInfo(#"chkdsk.exe", "D:");
processStartInfo.UseShellExecute = false;
var process = Process.Start(processStartInfo);
process.WaitForExit();
if (process.ExitCode != 0)
throw new Exception("did not work");
When redirecting StandardOutput, the process ends with ExitCode 3.
var processStartInfo = new ProcessStartInfo(#"chkdsk.exe", "D:");
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
var process = Process.Start(processStartInfo);
process.WaitForExit();
if (process.ExitCode != 0)
throw new Exception("did not work");
Doing the same thing with e.g. net use and redirected StandardOutput works without an error
var processStartInfo = new ProcessStartInfo(#"net ", "use");
Why? How can chkdsk be executed and StandardOutput be redirected?
Environment: Win 7 Pro x64, UAC disabled, Logged on as Administrator, Dot Net 4.0, VS 2012, WPF Application

I just ran this code with no problem and with an exit code of 0.
var cd = RunProcessDirect("chkdsk.exe", "c:", false);
protected ConsoleData RunProcessDirect(string processPath, string args,
bool isHidden)
{
Process process = SetupProcess(processPath, args, isHidden);
process.Start();
ConsoleData data = new ConsoleData();
data.StandardOutput = process.StandardOutput.ReadToEnd();
data.StandardError = process.StandardError.ReadToEnd();
data.ExitCode = process.ExitCode;
return data;
}
private Process SetupProcess(string processPath, string args,
bool isHidden)
{
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = isHidden
? ProcessWindowStyle.Hidden
: ProcessWindowStyle.Normal;
startInfo.CreateNoWindow = isHidden;
startInfo.FileName = processPath;
startInfo.Arguments = args;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
process.StartInfo = startInfo;
return process;
}
public class ConsoleData
{
public string StandardOutput { get; set; }
public string StandardError { get; set; }
public int ExitCode { get; set; }
}
cd.StandardOutput contained all the text output from the program, cd.StandardError was empty, and cd.ExitCode is 0.
Don't worry about the IsHidden stuff, that is just extra flair on my method that I didn't feel like taking off.

You must be running Visual Studio as Administrator and it will execute or you can add a application manifest file(add->new item->general->application manifest file) and changing this line <requestedExecutionLevel level="asInvoker" uiAccess="false" /> to this <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> which will just promp you to restart visual studio as administrator.

Simple answer, start a console process on non console application; if you would like to redirect standard output, please do a redirect standard input as well (even you are not using it).
So, just add below two lines in your code, it will work.
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardError = true;

This code works, runs chkdsk via cmd, and writes into log whole chkdsk output.
public int StartCheckDisc()
{
var process = new Process
{
StartInfo =
{
CreateNoWindow = false,
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd",
Arguments = "/C chkdsk C:",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true
}
};
process.Start();
var output = process.StandardOutput.ReadToEnd();
var exitCode = process.ExitCode;
var errorCode = process.StandardError.ReadToEnd();
Log.Instance.Info(output);
Log.Instance.Info(exitCode);
Log.Instance.Info(errorCode);
process.WaitForExit();
return exitCode;
}

Related

Run windows command without cmd.exe from C#

I am attempting to run a windows command (e.g. whoami) without calling cmd.exe (or powershell) directly using C#.
Within VB this is possible using CreateObject(WScript.Shell) it obviously does not have to be the same method as within the VB, although that would be nice, but I just do not want to call cmd.exe directly.
How would I be able to achieve this?
This runs a console program, waits for exit and reads the output. I changed the cmd to ping since that takes longer and I can verify no console window opens.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "ping.exe";
startInfo.Arguments = "google.com";
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
// This wasn't needed
//startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process processTemp = new Process();
processTemp.StartInfo = startInfo;
processTemp.EnableRaisingEvents = true;
try
{
processTemp.Start();
textBox1.Text = processTemp.StandardOutput.ReadToEnd();
processTemp.WaitForExit();
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
You could call whoami.exe and capture the output directly.
The key is UseShellExecute = false to run the executable directly.
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #$"{Environment.ExpandEnvironmentVariables("%systemroot%")}\system32\whoami.exe",
Arguments = // Put any command line arguments here
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
string line = proc.StandardOutput.ReadToEnd();

How to run this app with hidden or even minimized console?

var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"C:\Program Files\CPUID\CPU-Z\cpuz.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
for(; ; )
{
process.Start();
Thread.Sleep(20000);
process.Kill();
}
This program need to be hidden or even minimized?
Can someone explain to me how to upgrade this?
Add these lines to your code
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;

Problem with running batch files from within my application

I've been trying to create a simple application to backup my Windows Server databases aswell as a whole server backup.
For this I want to use batch files which are being executed by my application.
I tried several approaches but for some reason it always fails so I'd be happy if you could help me out.
Batch file BACKUPSERVER:
wbadmin start backup -backupTarget:D: -include:C: -allCritical -quiet
I have to run the bat as administrator or it fails due to missing permissions.
C# code:
static Task<int> RunProcessAsync(string fileName)
{
............
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Verb = "runas";
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C \"D:\\SQLBACKUP\\BACKUPSERVER.bat\"";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
Debugging says 'wbadmin wasnt found'. 'runas' activated or not doesn't make any difference.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = fileName;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = false;
// startInfo.Verb = "runas";
var process = new Process
{
StartInfo = { FileName = fileName },
EnableRaisingEvents = true
};
process.StartInfo = startInfo;
process.Exited += (sender, args) =>
{
tcs.SetResult(process.ExitCode);
process.Dispose();
};
process.Start();
Also doesn't work.
Any ideas?
EDIT:
I'm able to run commands like shutdown but wbadmin doesn't work whatsoever...
This is how I solved the problem:
Make sure ure compiling for 64bit if u intend to use your application on 64bit system, otherwise it will redirect to different subfolders and wont find 'wbadmin.exe'.
Run wbadmin with ProcessStart or run a batch but without direct cmd input, so use this with filename = batch file or wbadmin with startInfo.Arguments:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = fileName;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = false;
// startInfo.Verb = "runas";
var process = new Process
{
StartInfo = { FileName = fileName },
EnableRaisingEvents = true
};
process.StartInfo = startInfo;
process.Exited += (sender, args) =>
{
tcs.SetResult(process.ExitCode);
process.Dispose();
};
process.Start();
Make sure u request administrator rights

running cmd in c# answer yes to prompt

I'm running the below command from c#. There is a prompt that will be shown that I want to answer "yes" to how can I do this with the current code
If I run this as a batch script I can just do
echo y | pscp.exe -batch -pw password E:\\Certs\\client.conf me#<ip>:/home/user
which works - but unsure how I can replicate this using the below
string pscpPath="-batch -pw password E:\\Certs\\client.conf me#<ip>:/home/user";
ExecuteCopyCerts("pscp.exe", pscpPath);
Function:
public Boolean ExecuteCopyCerts(string fileName, string arguments)
{
txtLiveHubStatus.Text = "";
try
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(fileName, arguments);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
return proc.ExitCode == 0;
}
}
Set RedirectStandardInput to true
procStartInfo.RedirectStandardInput = true
and then write to StandardInput
proc.StandardInput.WriteLine("yes");
To reiterate what Hesam said though the prompt is Y, not yes. This is the prompt for the cert, which only occurs on the first call to each new linux machine. I use this code today in one of our applications.
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "pscp";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = false;
psi.Arguments = $"-r -p -pw {passWord} \"{localFileNamePath}\" {userName}#{hostName}:{remotePath}";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
using (Process process = new Process())
{
process.StartInfo = psi;
process.Start();
process.StandardInput.WriteLine("Y");
process.WaitForExit();
}

Redirect process input and use shell execute

Is it possible to redirect just stdin but also allow stdout to be written to the console?
I have a process which starts child processes and needs to read the output of those processes, but also display it in the console. Is it possible? I tried to just create my own console process but I can't write to it unless I UseShellExecute and the purpose is to show the output in the console.
protected void startp() {
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = "/k";
//Can't redirect output without UseShellExecute = false
psi.RedirectStandardInput = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = false;
p.StartInfo = psi;
p.Start();
//Can't write to StandardInput with UseShellExecute = true
p.StandardInput.WriteLine("#ECHO OFF");
p.StandardInput.WriteLine("echo | set /p=Child Process");
Console.ReadLine();
p.StandardInput.WriteLine("exit");
}

Categories

Resources