How use cmd command in c# program? - c#

I want cmd command in my c# winforms program. I want use command to compress file with 7zip.
In normal cmd i use cd "C:\Program Files(x86)\7-Zip" & 7z.exe a -tzip "C:\xyz\test\txt" "C:\xyz\test\txt" -m0=BZip2 -mx5
string zip = #"/c C:\Program Files(x86)\7-Zip";
string file = #"/c C:\xyz\txt";
string conv = "/c & 7z.exe a -tzip";
string method = "/c -m0=BZip2 -mx5";
System.Diagnostics.ProcessStartInfo proc = new System.Diagnostics.ProcessStartInfo();
proc.FileName = #"C:\windows\system32\cmd.exe";
proc.Arguments = #"/c cd" + zip + conv + file + file + method;
System.Diagnostics.Process.Start(proc);
Doesn't work my code. How can i use this command in my program. I want compress file when i click in button

Something like this:
// File (exe) to start: combination of folder and exe
string fileName = Path.Combine(
// Let's not hardcode "C:\Program Files(x86)" and alike
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
#"7-Zip",
#"7z.exe");
// If desired arguments are
// a -tzip "C:\xyz\test\txt" "C:\xyz\test\txt" -m0=BZip2 -mx5
// we can join them as
string arguments = string.Join(" ",
#"a",
#"-tzip", //TODO: you may want to have these values
#"""C:\xyz\test\txt""", // as variables like file, conv, method etc.
#"""C:\xyz\test\txt""",
#"-m0=BZip2",
#"-mx5");
ProcessStartInfo procInfo = new ProcessStartInfo() {
FileName = fileName, // We want to start fileName
Arguments = arguments, // With arguments
}
// Process is IDisposable, do not forget to Dispose HProcess handle
using (var process = Process.Start(procInfo)) {
// It's fire and forget implementation, if you want to wait for results
// add process.WaitForExit();
// process.WaitForExit(); // uncomment, if you want to pause
}

You seem to have made a mistake with your arguments.
Your current command line will be:
C:\windows\system32\cmd.exe /c cd/c C:\Program Files(x86)\7-Zip/c & 7z.exe a -tzip/c C:\xyz\txt/c C:\xyz\txt/c -m0=BZip2 -mx5
The spurious /c everywhere is not going to help and neither are the lack of spaces.
I'm guessing what you meant to run was these two commands in succession:
cd C:\Program Files(x86)\7-Zip
7z.exe a -tzip C:\xyz\txt C:\xyz\txt -m0=BZip2 -mx5
Which means you should change your code to:
string zip = #" C:\Program Files(x86)\7-Zip";
string file = #" C:\xyz\txt";
string conv = " & 7z.exe a -tzip";
string method = " -m0=BZip2 -mx5";
This will produce:
C:\windows\system32\cmd.exe /c cd C:\Program Files(x86)\7-Zip & 7z.exe a -tzip C:\xyz\txt C:\xyz\txt -m0=BZip2 -mx5

Related

Parameters from bat file to sql script not working

I have a C# application calling a bat file:
new string[] { branchName + ".Order", "Order.bak", "Order"}
var arguments = String.Format("\"{0}\"\"{1}\"\"{2}\"\"{3}\"", stringse[0], stringse[1], stringse[2], sqlPath + "\\");
var psi = new System.Diagnostics.ProcessStartInfo(filename)
{
RedirectStandardOutput = true,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
UseShellExecute = false,
Arguments = arguments
};
Process createDBs = Process.Start(psi);
System.IO.StreamReader myOutput = createDBs.StandardOutput;
while (!createDBs.HasExited)
{
string output = myOutput.ReadToEnd();
LogStep(output);
}
The bat file looks like this:
#echo off
REM ************************************************
REM * RestoreDB script for use by Development Team *
REM ************************************************
#echo %1 %2 %3 %4
#echo Restore of database started...
SQLCMD -S (local) -d Master -i RestoreDB.sql -v varDatabaseName=%1 varDatabaseBackupFileName= %2 varLogicalName= %3 varSQLDataFolder= %4
#echo Restore of database finished...
pause
The Sql script looks receive these parameters like this:
SET #DatabaseName = N'$(varDatabaseName)'
SET #DatabaseBackupFileName = N'$(varDatabaseBackupFileName)'
SET #LogicalName = N'$(varLogicalName)'
SET #SQLDataFolder = N'$(varSQLDataFolder)'
(Can't paste complete code due to security reasons)
Now my problem is that I don't think I'm passing the variables from bat to sql script correctly.
When calling the bat file out of C# it echo's the values
When calling the sql directly out of command prompt it works correctly, so I know my sql script is working:
SQLCMD -S (local) -d Master -i RestoreDB.sql -v varDatabaseName="Piet.Order.Test" varDatabaseBackupFileName="Order.bak" varLogicalName="Order" varSQLDataFolder="C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\"
I don't get any errors back to my C# application, so when running my application it just runs and calls the bat with parameters, the call from bat to sql seems to go wrong.Is it a format problem with my parameters. I tried single quotes '%1' and tried doubele quotes "%1", nothing seems to work.Can anybody shine some light.Any way maybe how I can retrieve the error that is happening with the call to sql
You need to add a space between arguments
var arguments = String.Format("\"{0}\" \"{1}\" \"{2}\" \"{3}\"",
stringse[0], stringse[1], stringse[2], sqlPath + "\\");
In these scenarios (debugging parameters) could be very useful to start the command processor and leave the console window open after the execution of the program
var arguments = String.Format("/K {4} \"{0}\" \"{1}\" \"{2}\" \"{3}\"",
stringse[0], stringse[1], stringse[2], sqlPath + "\\", filename);
and call the command processor in the ProcessStartInfo
var psi = new System.Diagnostics.ProcessStartInfo("cmd.exe")

Execute a program from the cmd with arguments

I have a program that needed running from the cmd with arguments, say the execute file called
program.exe
And i need to run it from the cmd with args, the whole command in the cmd look like this:
c:\ram\program.exe /path = c:\program files\NV
As you can see the path is : "c:\ram\"
The execute file is : "program.exe"
The args that i need to send is : /path = c:\program files\NV
How can i do it ?
I try to open process like this :
string strArguments = #"/path = c:\program files\NV";
Process p = new Process();
p.StartInfo.FileName = "program.exe";
p.StartInfo.WorkingDirectory = "c:\\ram\\";
p.StartInfo.Arguments = strArguments;
p.Start();
And its not good, i figure that the problem could be that i'm not accessing the exe file from the CMD, maybe i'm wrong...any body got idea how can i do it ?
Thanks
Try these things
p.StartInfo.FileName = "c:\\ram\\program.exe"; without setting Working Directory
and this one is more likely the source of the problem
string strArguments = #"/path = ""c:\program files\NV""";
When there is a space in a path, you have to enclose the whole path in quotation marks. The complete code is as follows
string strArguments = #"/path=""c:\program files\NV""";
Process p = new Process();
p.StartInfo.FileName = #"c:\ram\program.exe";
p.StartInfo.Arguments = strArguments;
p.Start();
It should do exactly what are you trying to do.
1.run "cmd.exe".
2.go to this dir: "c:\ram\" (in the cmd of course).
3.execute the file "program.exe" with this argument: "/path = c\:program files\NV"
It takes the program.exe in the c:\ram\ folder and executes it using cmd with the specified arguments.

Trying to use cmd via c#

I am trying to use a cmd command prompt that works just fine when I use it in a normal cmd window via Windows --> Start --> cmd
My code looks like this
"C:\Program Files\Rapid-I\RapidMiner5\scripts\rapidminer.bat" -f
"C:\Users\user\.RapidMiner5\repositories\Local Repository\test.rmp"
That works just fine.
The problem is when I am trying to write this code in C# by opening a cmd window via C#
This is the c# code
ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd", "/c \"C:\\Program Files\\Rapid-I\\RapidMiner5\\scripts\\rapidminer.bat\" -f \"C:\\Users\\user\\.RapidMiner5\\repositories\\Local Repository\\test.rmp\"");
You can see I quoted the same way like the code that work in the regular cmd
But I am getting a can't recognize program files.
Try this:
string fullPath = #"C:\Program Files\Rapid-I\RapidMiner5\scripts\rapidminer.bat";
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = Path.GetFileName(fullPath);
p.WorkingDirectory = Path.GetDirectoryName(fullPath);
p.Arguments = #"/c -f ""C:\Users\user\.RapidMiner5\repositories\Local Repository\test.rmp""";
Process.Start(p);
I modified my original code to add arguments to your process.
One last thing you could try is putting your original command into a batch file and calling the batch file from your ProcessStartInfo object like so:
C#:
string fullPath = #"C:\Program Files\Rapid-I\RapidMiner5\scripts\run.bat";
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = Path.GetFileName(fullPath);
p.WorkingDirectory = Path.GetDirectoryName(fullPath);
Process.Start(p);

rebuild wmi classes with c#

i am writing c# code to rebuild the wmi classes. i found that it can be done with the help of these command as discussed here :
Regsvr32 %SystemRoot%\System32\wbem\wmidcprv.dll
cd /d %windir%\system32\wbem
for %i in (*.dll) do RegSvr32 -s %i
for %i in (*.exe) do %i /RegServer
i have tried passing these command in cmd and reading the output as :
Process objProcess = new Process();
objProcess.StartInfo.UseShellExecute = false;
objProcess.StartInfo.RedirectStandardOutput = true;
//objProcess.StartInfo.CreateNoWindow = true;
//objProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
string cmd1=#"Regsvr32 %SystemRoot%\System32\wbem\wmidcprv.dll";
string cmd2=#"cd /d %windir%\system32\wbem";
string cmd3=#"for %i in (*.dll) do RegSvr32 -s %i";
string cmd4 = #"for %i in (*.exe) do %i /RegServer";
string strFinal = cmd1 + "\n" + cmd2 + "\n" + cmd3 + "\n" + cmd4;
//string cmd1=#"Regsvr32 %SystemRoot%\System32\wbem\wmidcprv.dll cd /d %windir%\system32\wbem for %i in (*.dll) do RegSvr32 -s %i for %i in (*.exe) do %i /RegServer";
objProcess.StartInfo.FileName = string.Format("cmd.exe");
objProcess.StartInfo.Arguments = string.Format(strFinal);
try
{
objProcess.Start();
}
catch
{
throw new Exception("Error");
}
StreamReader strmReader = objProcess.StandardOutput;
string strTempRow = string.Empty;
while ((strTempRow = strmReader.ReadLine()) != null)
{
Console.WriteLine(strTempRow);
}
if (!objProcess.HasExited)
{
objProcess.Kill();
}
Can one share idea how to achieve this by code not manually.
I assume you have problems executing ms-dos commands, not reading the output.
Have you tried creating a batch file with those commands and executing it with system process class?
First of all, create the batch file with those commands and execute it manually. If it's works fine then just execute it as you done before.
System.Diagnostics.Process.Start("wmiBuilder.bat");

Run Command Prompt Commands

Is there any way to run command prompt commands from within a C# application? If so how would I do the following:
copy /b Image1.jpg + Archive.rar Image2.jpg
This basically embeds an RAR file within JPG image. I was just wondering if there was a way to do this automatically in C#.
this is all you have to do run shell commands from C#
string strCmdText;
strCmdText= "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
System.Diagnostics.Process.Start("CMD.exe",strCmdText);
EDIT:
This is to hide the cmd window.
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
process.StartInfo = startInfo;
process.Start();
EDIT 2:
It is important that the argument begins with /C, otherwise it won't work. As #scott-ferguson said: /C carries out the command specified by the string and then terminates.
Tried RameshVel's solution but I could not pass arguments in my console application. If anyone experiences the same problem here is a solution:
using System.Diagnostics;
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.WriteLine("echo Oscar");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
var proc1 = new ProcessStartInfo();
string anyCommand;
proc1.UseShellExecute = true;
proc1.WorkingDirectory = #"C:\Windows\System32";
proc1.FileName = #"C:\Windows\System32\cmd.exe";
proc1.Verb = "runas";
proc1.Arguments = "/c "+anyCommand;
proc1.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(proc1);
None of the above answers helped for some reason, it seems like they sweep errors under the rug and make troubleshooting one's command difficult. So I ended up going with something like this, maybe it will help someone else:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"C:\Program Files\Microsoft Visual Studio 14.0\Common7\IDE\tf.exe",
Arguments = "checkout AndroidManifest.xml",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
WorkingDirectory = #"C:\MyAndroidApp\"
}
};
proc.Start();
Though technically this doesn't directly answer question posed, it does answer the question of how to do what the original poster wanted to do: combine files. If anything, this is a post to help newbies understand what Instance Hunter and Konstantin are talking about.
This is the method I use to combine files (in this case a jpg and a zip). Note that I create a buffer that gets filled with the content of the zip file (in small chunks rather than in one big read operation), and then the buffer gets written to the back of the jpg file until the end of the zip file is reached:
private void CombineFiles(string jpgFileName, string zipFileName)
{
using (Stream original = new FileStream(jpgFileName, FileMode.Append))
{
using (Stream extra = new FileStream(zipFileName, FileMode.Open, FileAccess.Read))
{
var buffer = new byte[32 * 1024];
int blockSize;
while ((blockSize = extra.Read(buffer, 0, buffer.Length)) > 0)
{
original.Write(buffer, 0, blockSize);
}
}
}
}
if you want to run the command in async mode - and print the results. you can you this class:
public static class ExecuteCmd
{
/// <summary>
/// Executes a shell command synchronously.
/// </summary>
/// <param name="command">string command</param>
/// <returns>string, as output of the command.</returns>
public static void ExecuteCommandSync(object command)
{
try
{
// create the ProcessStartInfo using "cmd" as the program to be run, and "/c " as the parameters.
// Incidentally, /c tells cmd that we want it to execute the command that follows, and then exit.
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
// The following commands are needed to redirect the standard output.
//This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
Console.WriteLine(result);
}
catch (Exception objException)
{
// Log the exception
Console.WriteLine("ExecuteCommandSync failed" + objException.Message);
}
}
/// <summary>
/// Execute the command Asynchronously.
/// </summary>
/// <param name="command">string command.</param>
public static void ExecuteCommandAsync(string command)
{
try
{
//Asynchronously start the Thread to process the Execute command request.
Thread objThread = new Thread(new ParameterizedThreadStart(ExecuteCommandSync));
//Make the thread as background thread.
objThread.IsBackground = true;
//Set the Priority of the thread.
objThread.Priority = ThreadPriority.AboveNormal;
//Start the thread.
objThread.Start(command);
}
catch (ThreadStartException )
{
// Log the exception
}
catch (ThreadAbortException )
{
// Log the exception
}
catch (Exception )
{
// Log the exception
}
}
}
if you want to keep the cmd window open or want to use it in winform/wpf then use it like this
string strCmdText;
//For Testing
strCmdText= "/K ipconfig";
System.Diagnostics.Process.Start("CMD.exe",strCmdText);
/K
Will keep the cmd window open
Yes, there is (see link in Matt Hamilton's comment), but it would be easier and better to use .NET's IO classes. You can use File.ReadAllBytes to read the files and then File.WriteAllBytes to write the "embedded" version.
with a reference to Microsoft.VisualBasic
Interaction.Shell("copy /b Image1.jpg + Archive.rar Image2.jpg", AppWinStyle.Hide);
This can also be done by P/Invoking the C standard library's system function.
using System.Runtime.InteropServices;
[DllImport("msvcrt.dll")]
public static extern int system(string format);
system("copy Test.txt Test2.txt");
Output:
1 file(s) copied.
Here is little simple and less code version. It will hide the console window too-
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
process.Start();
I have the following method, which I use to run the command prompt commands from C#
In first parameter pass the command you want to run
public static string RunCommand(string arguments, bool readOutput)
{
var output = string.Empty;
try
{
var startInfo = new ProcessStartInfo
{
Verb = "runas",
FileName = "cmd.exe",
Arguments = "/C "+arguments,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = false
};
var proc = Process.Start(startInfo);
if (readOutput)
{
output = proc.StandardOutput.ReadToEnd();
}
proc.WaitForExit(60000);
return output;
}
catch (Exception)
{
return output;
}
}
You can achieve this by using the following method (as mentioned in other answers):
strCmdText = "'/C some command";
Process.Start("CMD.exe", strCmdText);
When I tried the methods listed above I found that my custom command did not work using the syntax of some of the answers above.
I found out more complex commands need to be encapsulated in quotes to work:
string strCmdText;
strCmdText = "'/C cd " + path + " && composer update && composer install -o'";
Process.Start("CMD.exe", strCmdText);
you can use simply write the code in a .bat format extension ,the code of the batch file :
c:/ copy /b Image1.jpg + Archive.rar Image2.jpg
use this c# code :
Process.Start("file_name.bat")
You can use RunProcessAsTask pacakge and run your process async and easily like this:
var processResults = await ProcessEx.RunAsync("git.exe", "pull");
//get process result
foreach (var output in processResults.StandardOutput)
{
Console.WriteLine("Output line: " + output);
}
This may be a bit of a read so im sorry in advance. And this is my tried and tested way of doing this, there may be a simpler way but this is from me throwing code at a wall and seeing what stuck
If it can be done with a batch file then the maybe over complicated work around is have c# write a .bat file and run it. If you want user input you could place the input into a variable and have c# write it into the file. it will take trial and error with this way because its like controlling a puppet with another puppet.
here is an example, In this case the function is for a push button in windows forum app that clears the print queue.
using System.IO;
using System;
public static void ClearPrintQueue()
{
//this is the path the document or in our case batch file will be placed
string docPath =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//this is the path process.start usues
string path1 = docPath + "\\Test.bat";
// these are the batch commands
// remember its "", the comma separates the lines
string[] lines =
{
"#echo off",
"net stop spooler",
"del %systemroot%\\System32\\spool\\Printers\\* /Q",
"net start spooler",
//this deletes the file
"del \"%~f0\"" //do not put a comma on the last line
};
//this writes the string to the file
using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "test.bat")))
{
//This writes the file line by line
foreach (string line in lines)
outputFile.WriteLine(line);
}
System.Diagnostics.Process.Start(path1);
}
IF you want user input then you could try something like this.
This is for setting the computer IP as static but asking the user what the IP, gateway, and dns server is.
you will need this for it to work
public static void SetIPStatic()
{
//These open pop up boxes which ask for user input
string STATIC = Microsoft.VisualBasic.Interaction.InputBox("Whats the static IP?", "", "", 100, 100);
string SUBNET = Microsoft.VisualBasic.Interaction.InputBox("Whats the Subnet?(Press enter for default)", "255.255.255.0", "", 100, 100);
string DEFAULTGATEWAY = Microsoft.VisualBasic.Interaction.InputBox("Whats the Default gateway?", "", "", 100, 100);
string DNS = Microsoft.VisualBasic.Interaction.InputBox("Whats the DNS server IP?(Input required, 8.8.4.4 has already been set as secondary)", "", "", 100, 100);
//this is the path the document or in our case batch file will be placed
string docPath =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//this is the path process.start usues
string path1 = docPath + "\\Test.bat";
// these are the batch commands
// remember its "", the comma separates the lines
string[] lines =
{
"SETLOCAL EnableDelayedExpansion",
"SET adapterName=",
"FOR /F \"tokens=* delims=:\" %%a IN ('IPCONFIG ^| FIND /I \"ETHERNET ADAPTER\"') DO (",
"SET adapterName=%%a",
"REM Removes \"Ethernet adapter\" from the front of the adapter name",
"SET adapterName=!adapterName:~17!",
"REM Removes the colon from the end of the adapter name",
"SET adapterName=!adapterName:~0,-1!",
//the variables that were set before are used here
"netsh interface ipv4 set address name=\"!adapterName!\" static " + STATIC + " " + STATIC + " " + DEFAULTGATEWAY,
"netsh interface ipv4 set dns name=\"!adapterName!\" static " + DNS + " primary",
"netsh interface ipv4 add dns name=\"!adapterName!\" 8.8.4.4 index=2",
")",
"ipconfig /flushdns",
"ipconfig /registerdns",
":EOF",
"DEL \"%~f0\"",
""
};
//this writes the string to the file
using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "test.bat")))
{
//This writes the file line by line
foreach (string line in lines)
outputFile.WriteLine(line);
}
System.Diagnostics.Process.Start(path1);
}
Like I said. It may be a little overcomplicated but it never fails unless I write the batch commands wrong.

Categories

Resources