运行命令提示符命令

有没有办法从C#应用程序中运行命令提示符命令?如果有,我将如何执行以下操作:

copy /b Image1.jpg + Archive.rar Image2.jpg

这基本上是在JPG图像中嵌入一个RAR文件。我只是想知道是否有一种方法可以在C#中自动执行此操作。

1256188 次浏览

是的,有(参见Matt Hamilton评论中的链接),但使用. NET的IO类会更容易和更好。您可以使用File. ReadAllBytes读取文件,然后使用File. WriteAllBytes编写“嵌入式”版本。

这就是你所要做的从C#运行shell命令

string strCmdText;
strCmdText= "/C copy /b Image1.jpg + Archive.rar Image2.jpg";
System.Diagnostics.Process.Start("CMD.exe",strCmdText);

编辑:

这是为了隐藏cmd窗口。

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();

编辑2:

重要的是参数以/C开头,否则它将不起作用。正如@李嘉诚@李嘉诚所说:/C执行字符串指定的命令,然后终止

虽然从技术上讲,这并不能直接回答提出的问题,但它确实回答了如何做原始海报想做的事情的问题:组合文件。如果有的话,这篇文章是为了帮助新手理解实例亨特和康斯坦丁在说什么。

这是我用来组合文件(在本例中是jpg和zip)的方法。请注意,我创建了一个缓冲区,该缓冲区被zip文件的内容填充(以小块而不是在一个大读操作中),然后缓冲区被写入jpg文件的后面,直到到达zip文件的末尾:

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);
}
}
}
}
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);

尝试RameshVel的解决方案,但我无法在我的控制台应用程序中传递参数。如果有人遇到同样的问题,这里有一个解决方案:

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());

这是一个简单且代码较少的版本。它也会隐藏控制台窗口-

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();

参考Microsoft.VisualBasic

Interaction.Shell("copy /b Image1.jpg + Archive.rar Image2.jpg", AppWinStyle.Hide);

出于某种原因,上述答案都没有帮助,似乎它们掩盖了错误,使一个人的命令难以排除故障。所以我最终选择了这样的东西,也许它会帮助其他人:

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();

您可以在一行中使用CliWrap执行此操作:

var result = await Cli.Wrap("cmd")
.WithArguments("copy /b Image1.jpg + Archive.rar Image2.jpg")
.ExecuteBufferedAsync();


var stdOut = result.StandardOutput;

您可以使用以下方法来实现这一点(如其他答案中提到的):

strCmdText = "'/C some command";
Process.Start("CMD.exe", strCmdText);

当我尝试上面列出的方法时,我发现我的自定义命令无法使用上面一些答案的语法。

我发现更复杂的命令需要用引号封装才能工作:

string strCmdText;
strCmdText = "'/C cd " + path + " && composer update && composer install -o'";
Process.Start("CMD.exe", strCmdText);

您可以使用简单地以.bat格式扩展名编写代码,批处理文件的代码:

c:/ copy /b Image1.jpg + Archive.rar Image2.jpg

使用此c#代码:

Process.Start("file_name.bat")

如果你想让cmd窗口保持打开状态或者想在w的/wpf中使用它,那么就像这样使用它

    string strCmdText;
//For Testing
strCmdText= "/K ipconfig";


System.Diagnostics.Process.Start("CMD.exe",strCmdText);

/K

将保持cmd窗口打开

如果你想在异步模式下运行命令-并打印结果。你可以你这个类:

    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
}
}


}

这也可以通过C标准库的P/援引函数来完成。

using System.Runtime.InteropServices;


[DllImport("msvcrt.dll")]
public static extern int system(string format);


system("copy Test.txt Test2.txt");

输出:

      1 file(s) copied.

这可能有点难读,所以我提前道歉。这是我久经考验的方法,可能有更简单的方法,但这是我把代码扔到墙上,看看是什么卡住了

如果它可以用批处理文件完成,那么可能过于复杂的工作是让c#编写一个. bat文件并运行它。如果你想要用户输入,你可以将输入放入变量并让c#将其写入文件。它将以这种方式进行试验和错误,因为它就像用另一个木偶控制木偶一样。

这是一个例子,在这种情况下,该功能是用于清除打印队列的windows论坛应用程序中的按钮。

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);


}

如果您想要用户输入,那么您可以尝试这样的操作。

这用于将计算机IP设置为静态,但询问用户IP、网关和dns服务器是什么。

您将需要这个才能工作

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);


}

就像我说的。它可能有点过于复杂,但它永远不会失败,除非我写错了批处理命令。

您可以使用RunProcessAsTask包并像这样轻松地异步运行您的进程:

var processResults = await ProcessEx.RunAsync("git.exe", "pull");
//get process result
foreach (var output in processResults.StandardOutput)
{
Console.WriteLine("Output line: " + output);
}

我有以下方法,我用它来从C#运行命令提示符命令

在第一个参数中传递您要运行的命令

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;
}
}