Show cmd commands on C# winform Application - c#

I need to write a small utility to rebuild solution. I am using below code to do the same.
string solutionFile = #"E:\Projects\TFS\Code\WebSite.sln";
string cmd1 = #"""C:\Program Files\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" x86" + " &devenv " + "\"" + solutionFile + "\"" + " /rebuild release";
cmd1 = "\"" + cmd1 + "\"";
String command = String.Format("{0} {1}", #"/k ", cmd1);
ProcessStartInfo cmdsi = new ProcessStartInfo("cmd.exe")
{
UseShellExecute = false,
RedirectStandardOutput = true
};
cmdsi.Arguments = command;
using (Process cmd = Process.Start(cmdsi))
{
using (StreamReader reader = cmd.StandardOutput)
{
string result = reader.ReadToEnd();
listBox1.Items.Add(result);
}
}
If you will observe in command prompt then you can see executions output but same thing is not getting reflected in list box.
Please help to solve this issue.
Thank you in advance.

You can redirect the output to a temporary file and then can read the file like-
string cmd1 = "help > e:/temp.txt"; //e:/temp.txt is temporary file where the output is redirected.
String command = String.Format("{0} {1}", #"/k ", cmd1);
ProcessStartInfo cmdsi = new ProcessStartInfo("cmd.exe")
{
//You don't need to read console outputstream
//UseShellExecute = false,
//RedirectStandardOutput = true
};
cmdsi.Arguments = command;
using (Process cmd = Process.Start(cmdsi))
{
//Check if file exist or you can wait till the solution builds completely. you can apply your logic to wait here.
if (File.Exists("E:/temp.txt"))
{
//Read the files here
string[] lines = File.ReadAllLines("E:/temp.txt");
//Do your work here
}
}

You can do it async:
string solutionFile = #"E:\Projects\TFS\Code\WebSite.sln";
string batFile = #"C:\Program Files\Microsoft Visual Studio 11.0\VC\vcvarsall.bat";
string args = "x86" + " &devenv " + "\"" + solutionFile + "\"" + " /rebuild release";
ProcessStartInfo cmdsi = new ProcessStartInfo(batFile)
{
Arguments = args,
UseShellExecute = false,
RedirectStandardOutput = true
};
using (Process cmd = new Process())
{
cmd.StartInfo = cmdsi;
cmd.OutputDataReceived += (sender, args) => listBox1.Items.Add(string.IsNullOrEmpty(args.Data) ? string.Empty : args.Data);
cmd.Start();
}

Related

cmd windows not showing output

I'm having an issue where my cmd windows is just blank when executed from code. I've searched here and there for some solutions. And tried a few different things myself.
Running it with a normal .bat file works just fine.. But just not from my C# application.
Note: the ffmpeg is being run perfectly, but just not showing anything in the cmd window when executed from code.
image at the bottom.
I'll update this if I find a solution.. Unless you guys do it first ;)
Code:
private async void RunFfmpeg()
{
await Task.Run(() =>
{
String destFolder = null;
String sourceFolder = null;
int listCount = 0;
this.Dispatcher.Invoke(() =>
{
destFolder = textDest.Text;
sourceFolder = textSource.Text;
listCount = listFiles.Items.Count;
});
foreach (FileInfo fileC in listFiles.Items)
{
//Changing old extension to mp4
string oldFileName = fileC.ToString();
string newFileName = null;
string[] extension = oldFileName.Split('.');
newFileName = extension[0] + ".mp4";
string newDir = destFolder + "\\" + extension[0];
DirectoryInfo createDir = new DirectoryInfo(newDir);
if (!createDir.Exists)
{
createDir.Create();
}
//Gathering folders and all I need...
string output = "\"" + destFolder + "\\" + extension[0] + "\\" + newFileName + "\"";
string input = "\"" + sourceFolder + "\\" + oldFileName + "\"";
var startInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = "cmd.exe",
//Arguments = $"-i {input} {output}",
Arguments = $"/c ffmpeg -i {input}" + " -c:a copy -c:v copy " + $"{output}",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = false,
WorkingDirectory = Directory.GetCurrentDirectory()
};
Process p = new Process();
p.StartInfo = startInfo;
p.OutputDataReceived += P_OutputDataReceived;
p.Start();
p.WaitForExit();
}
});
}
Here is where I read the output:
private void P_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
//string cmdBox = cmdOutput.Text;
//cmdOutput.AppendText(cmdBox);
//cmdOutput.Clear();
cmdOutput.AppendText(e.Data);
});
}

How do I pass a command to the command prompt using Visual C#?

I am creating a Visual C# application that fills in the correct parameters in the command prompt to retrieve iTunes Sales and Trends data. My goal is to pass a string to the command prompt but I've only gotten as far is to locating the right directory. Below is the code I currently have.
string argument = (#"c/ java Autoingestion Credentials.properties " + lblVenderID.Text + " " + ddlReportType.Text + " " + ddlDateType.Text + " " + ddlReportSubtype.Text + " " + txtDate.Text);
System.Diagnostics.ProcessStartInfo process = new System.Diagnostics.ProcessStartInfo();
process.FileName = "cmd.exe";
process.WorkingDirectory = "C:/iTunes Sales Report/AutoIngestion";
System.Diagnostics.Debug.WriteLine(argument);
process.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
System.Diagnostics.Process.Start(process);
As you can in the picture, it locates to the directory that I hard coded in, but it does not display the string of text that actually runs the command I want it to run.
If there is a way to display the text in the command line before pressing enter to run the command automatically that would be great. Any feedback would be appreciated.
If you are trying to run a cmd and write to it then this should do it:
var processInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
WorkingDirectory = "C:/iTunes Sales Report/AutoIngestion",
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = false
};
var process = new Process {StartInfo = processInfo };
process.Start();
// This will write your command and excute it
process.StandardInput.WriteLine(argument);
process.WaitForExit();
If you want to view the output, here is how:
string output = string.Empty;
string error = string.Empty;
//If you want to read the Output of that argument
using (StreamReader streamReader = process.StandardOutput)
{
output = streamReader.ReadToEnd();
}
//If you want to read the Error produced by the argument *if any*
using (StreamReader streamReader = process.StandardError)
{
error = streamReader.ReadToEnd();
}

Open Visual Studio command prompt from C# code

I am trying to open Visual studio Command prompt using C# code.
Here is my code
private void Execute(string vsEnvVar)
{
var vsInstallPath = Environment.GetEnvironmentVariable(vsEnvVar);
// vsEnvVar can be VS100COMNTOOLS, VS120COMNTOOLS, VS140COMNTOOLS
if (Directory.Exists(vsInstallPath))
{
var filePath = vsInstallPath + "vsvars32.bat";
if (File.Exists(filePath))
{
//start vs command process
Process proc = new Process();
var command = Environment.GetEnvironmentVariable("ComSpec");
command = #"" + command + #"";
var batfile = #"E:\Test\vstest.bat";
var args = string.Format("/K \"{0}\" \"{1}\"" ,filePath, batfile);
proc.StartInfo.FileName = command;
proc.StartInfo.Arguments = args;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.UseShellExecute = false;
proc.Start();
}
else
{
Console.WriteLine("File Does not exists " + filePath);
}
}
}
But the args string is not getting properly formatted.
I am getting below formatted string
"/K \"C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Tools\\vsvars32.bat\" \"E:\\Test\\vstest.bat\""
extra "\" is getting added.
Please point out what I am missing.
Thanks
The string is being formatted as you asked, but you have asked for the wrong thing. "E:\Test\VStest.bat" is being passed as an argument to VCVars.bat, but I suspect you want it to be executed after it.
Try this:
var args = string.Format("/S/K \" \"{0}\" && \"{1}\" \"" ,filePath, batFile);
This should produce:
"/S/K \" \"C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Tools\\vsvars32.bat\" && \"E:\\Test\\vstest.bat\" \" \"
Which as a string is:
/S/K " "C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools\vsvars32.bat" && "E:\Test\vstest.bat" "

Output not proper when calling batch file programatically

I was trying to automate server patch installation for my product and I came to know about Wix Toolset.
I was hoping to get the JBoss Version in my installer. The command to get the same is standalone.bat --version from cmd.
So from my installer I created one CustomAction where I tried to run it and get the output.
public static string runRunnableBatch(string path){
Process exploitVersionService = new Process();
string runnableBinPath = path;
exploitVersionService.StartInfo.WorkingDirectory = path + "bin";
exploitVersionService.StartInfo.FileName = path + "bin\\standalone.bat";
exploitVersionService.StartInfo.CreateNoWindow = false;
exploitVersionService.StartInfo.Arguments = string.Format("--version");
exploitVersionService.StartInfo.UseShellExecute = false;
exploitVersionService.StartInfo.RedirectStandardOutput = true;
exploitVersionService.StartInfo.RedirectStandardInput = false;
exploitVersionService.Start();
exploitVersionService.WaitForExit();
// /*
string opt = "";
while (!exploitVersionService.StandardOutput.EndOfStream){
opt += exploitVersionService.StandardOutput.ReadLine();
}
// */
//using (StreamWriter writer = new StreamWriter("D:\\_log.txt"))
//using (StreamReader reader = exploitVersionService.StandardOutput){
// writer.AutoFlush = true;
// for (; ; ){
// string textLine = reader.ReadLine();
// if (textLine == null)
// break;
// writer.WriteLine(textLine);
// }
//}
//StreamReader exploitVersionFeed = exploitVersionService.StandardOutput;
//string output = exploitVersionFeed.ReadToEnd();
return opt;
}
When I was doing that, all I got as output was the first line of the whole output string.
I needed the whole string in my code so that from regular expression I could extract the version.
Also tried with
public static string runRunnableBatch(string path){
string executableBinPath = path + "bin";
string executableBinPath_BatchCmd = "cd " + "\"" + executableBinPath + "\"";
string outputFileName = "TempVerInfoHolder.txt";
string outputFilePath = executableBinPath+#"\TempVerInfoHolder1.txt";
string versionRetriever_BatchCmd = #"standalone.bat --version > " + "\""+outputFilePath+"\"";
string partitionName_BatchCmd = #Strings.Utils.getPartitionFromPath(path);
// Creating command sequence
SortedList<int, string> commandSequence = new SortedList<int, string>();
// ~ d:
commandSequence.Add(1, partitionName_BatchCmd);
// ~ cd %path%
commandSequence.Add(2, executableBinPath_BatchCmd);
// ~ standalone.bat --version > %filename%
commandSequence.Add(3, versionRetriever_BatchCmd);
runCommandFromSequence(commandSequence);
// Run together
return "";
}
private static void runCommandFromSequence(SortedList<int, string> commandSequence){
Process seqCmdExecHost = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = false;
seqCmdExecHost.StartInfo = psi;
seqCmdExecHost.Start();
using (StreamWriter writer = seqCmdExecHost.StandardInput) {
if (writer.BaseStream.CanWrite) {
foreach (int item in commandSequence.Keys){
MessageBox.Show(seqCmdExecHost.Id.ToString());
MessageBox.Show(commandSequence[item]);
writer.WriteLine(commandSequence[item]);
}
}
string opt = "";
while (!seqCmdExecHost.StandardOutput.EndOfStream){
opt += seqCmdExecHost.StandardOutput.ReadLine();
}
MessageBox.Show("Exited? " + seqCmdExecHost.HasExited);
MessageBox.Show("O/P? " + opt);
}
}
I have tried some other way as well. Switching the commented code of the above function was one of them.
Output getting while doing it from code level
Calling "D:\Servers\VA\XYZ\JBoss-7.1.1-Final\bin\standalone.conf.bat
Output while running the same command manually from cmd
Calling D:\Servers\VA\XYZ\JBoss-7.1.1-Final\bin\standalone.conf.bat
======================================================================
JBoss Bootstrap Environment
JBOSS_HOME: D:\Servers\VA\XYZ\JBoss-7.1.1-Final
JAVA: C:\Program Files\Java\jdk1.7.0_67\bin\java
JAVA_OPTS
======================================================================
Listening for transport dt_socket at address: 8787
19:08:08,333 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA
JBoss AS 7.1.1.Final "Brontes"
Press any key to continue . . .
My observation is, the stream is getting closed once the nested standalone.conf.bat is getting called from standalone.bat.
If any workaround available to get the full output in string/buffer/stream, would be appreciated.
Thanks
What you could do is call the Command line Application instead of calling the batch file
exploitVersionService.StartInfo.WorkingDirectory = path + "bin";
exploitVersionService.StartInfo.FileName = "cmd.exe";
exploitVersionService.StartInfo.CreateNoWindow = false;
exploitVersionService.StartInfo.Arguments = string.Format(" /c \"{0}\" --version",path + "bin\\standalone.bat");
I found one work around to do achieve this.
I created the batch file programmatically and ran it with cmd.
public static void createBatchToGetVersion(string path)
{
CustomLogger.getInstance().debug("Started creating batch file");
BatchOps.executableBinPath = path + "bin";
CustomLogger.getInstance().debug("Ëxecutable bin path: " + BatchOps.executableBinPath);
BatchOps.tempBatchFileName = "JBossVerCmd.bat";
BatchOps.holderFileName = #"JBossVerHolder.txt";
BatchOps.absoluteHolderPath = Strings.Utils.normalize(executableBinPath) + holderFileName;
CustomLogger.getInstance().debug("Normalized absoluteHolderPath: " + BatchOps.absoluteHolderPath);
CustomLogger.getInstance().debug("Checking if JBOSS_HOME entered by user actuallty points to JBOSS");
if (!File.Exists(Strings.Utils.normalize(executableBinPath) + "standalone.bat"))
{
CustomLogger.getInstance().error("standalone.bat not found. JBOSS_HOME Dir is not correctly entered");
throw new CustomExceptions.DirectoryNotAcceptableException("Bad directory is assigned to JBOSS_HOME or JBOSS_HOME structure corrupted");
}
/*
* Batch file formation.
* Contains:
* Start file
* D:
* cd D:\Fusion Server\jboss 7.1.1\bin
* #echo | call standalone.bat --version > sample.txt
* #echo Done
* End file
* #echo is required here because it exits the cmd when completed whithout having the user pressing any key
*/
string changePartition_cmd = Strings.Utils.getPartitionFromPath(path);
string changeDirectory_cmd = #"cd " + BatchOps.executableBinPath;
string getVersion_cmd = #"#echo | call standalone.bat --version > " + holderFileName;
string exitCmd = #"#echo Done";
CustomLogger.getInstance().debug("Command to be written on batch file");
CustomLogger.getInstance().debug("\r\n" + changePartition_cmd + "\r\n" + changeDirectory_cmd + "\r\n" + getVersion_cmd + "\r\n" + exitCmd);
SortedList<int, string> commandSequence = new SortedList<int, string>();
CustomLogger.getInstance().debug("Initializing command sequence.");
commandSequence.Add(1, changePartition_cmd);
commandSequence.Add(2, changeDirectory_cmd);
commandSequence.Add(3, getVersion_cmd);
commandSequence.Add(4, exitCmd);
// Will create one if file never existed and open one delete the content and set the pointer to the begnning
// if already existed
StreamWriter batchFileWriter = null;
try
{
CustomLogger.getInstance().debug("Establishing stream to and from temp batch file");
batchFileWriter = new StreamWriter(tempBatchFileName);
CustomLogger.getInstance().debug("Command sequence ready to be written on temp batch file.");
Perform.writeToStreamFromSequence(batchFileWriter, commandSequence);
CustomLogger.getInstance().debug("Command sequence successfully written");
}
catch (IOException ex)
{
CustomLogger.getInstance().error("Error while writing command sequence.\n" + ex.ToString());
// throw exception to CustomAction
throw new IOException("Error while writing commandSequence");
}
finally
{
// Not required. Stream already closed in writeToStreamFromSequence
}
}
public static void runTempBatchFile()
{
Process seqCmdExecHost = new Process();
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", #"/c " + BatchOps.tempBatchFileName);
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
seqCmdExecHost.StartInfo = procStartInfo;
seqCmdExecHost.Start();
seqCmdExecHost.WaitForExit();
seqCmdExecHost.Close();
}
I found the moment i was doing
procStartInfo.UseShellExecute=true;
procStartInfo.RedirectStandardOutput=true
It was giving the first line of output. Dont know why?. If anyone has any idea about it please explain.
Thanks

Run a command line program as Administrator

I need to run this as an administrator
string cname = Environment.UserDomainName + "\\" + Environment.UserName;
string resetTrust = "netdom /resetpwd /s:server01 /ud:" + cname + "/pd:" + textBoxPassword.Text.Trim();
String output = ExecuteCommandAsAdmin(resetTrust);
MessageBox.Show(output);
Here is the method ExecuteCommandAsAdmin
public static string ExecuteCommandAsAdmin(string command)
{
string cname = Environment.UserDomainName + "\\" + Environment.UserName;
ProcessStartInfo procStartInfo = new ProcessStartInfo()
{
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
FileName = "runas.exe",
Arguments = "/user:" + cname + "\"cmd /K " + command + "\""
};
using (Process proc = new Process())
{
proc.StartInfo = procStartInfo;
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
if (string.IsNullOrEmpty(output))
output = proc.StandardError.ReadToEnd();
return output;
}
}
If you know a better way to do this, please let me know. I am not storing the password. Just passing it so it can be executed. If the wrong person enters the wrong password, nothing happens since they aren't an Admin.
Thank You
Use runas /user:name#domain cmd

Categories

Resources