简体   繁体   中英

Pass more arguments to an already opened cmd prompt in C#

I want to loop through all images in a folder, retrieve each image's name and pass an argument using the name. This is what I have:

foreach (string imageFile in Directory.EnumerateFiles(filePath))
{
    //Get image name and save it as string
    string args = "something"; //a line of argument with image name in it
    Process.Start("cmd", @"/c cd C:\Tesseract-OCR && " + args);
}

The problem with above code is that, for each image file, it will open up a new command prompt. Instead, I want something like:

Process.Start("cmd", @"/k cd C:\Tesseract-OCR");
foreach (string imageFile in Directory.EnumerateFiles(filePath))
{
    //For each imageFile I have, pass an argument to the opened cmd prompt
}

There are a few methods, but generally the simplest is to create a batch file with all of the commands you want to execute then pass that as a parameter to cmd .

Something like this:

string imageFolder = @"C:\Path\To\Images";
string batchFile = @"C:\Temp\cmds.cmd";
string outputFile = @"C:\Temp\cmds.log";

// substitute your own command here.  "{0}" will be substituted for filename 
string command = @"attrib ""{0}"" >> """ + outputFile + @"""";

// delete the batch file if it exists
if (File.Exists(batchFile))
    File.Delete(batchFile);

// create batch file from content of image folder
using (var writer = File.CreateText(batchFile))
{
    writer.WriteLine("@echo off");

    foreach (var file in Directory.EnumerateFiles(imageFolder, "*.jpg"))
        writer.WriteLine(command, file);
}

// Delete the output file if it exists
if (File.Exists(outputFile))
    File.Delete(outputFile);

// Execute the batch
var p = Process.Start("cmd", @"/c """ + batchFile + @"""");
p.WaitForExit();

After that completes you can grab the content of the output file and parse it for results. If you need a break between the outputs, just echo something distinctive between each one. Maybe something like:

// create batch file from content of image folder
using (var writer = File.CreateText(batchFile))
{
    writer.WriteLine("@echo off");

    foreach (var file in Directory.EnumerateFiles(imageFolder, "*.jpg"))
    {
        writer.WriteLine(@"echo -----Start: {0}>>""{1}""", file, outputFile);
        writer.WriteLine(command, file);
        writer.WriteLine(@"echo -----End: {0}>>""{1}""", file, outputFile);
    }
}

That way you get the filename in the output as well to help with parsing.


Another option is to use full stream redirection to streams that you can write commands to and read responses from. This would allow you to have a command prompt running somewhere in the background that you can issue commands to. Seems simple, but honestly it takes a lot of work to get just right. If you want to go this way I'd suggest redirecting all three standard streams.

为什么程序不创建包含所有要执行的文件/命令的批处理文件,然后使用Process.Start执行该批处理文件?

You can use Directory.GetFiles() to get a string array of all the files in a directory. Then use String.Join() to merge the array into one long string of file names separated by space. I would also wrap each item in quotes if your path or files contain spaces.

const string QUOTE = "\"";
const string SPACE = " ";
const string SEPARATOR = QUOTE + SPACE + QUOTE;

string[] files = Directory.GetFiles(filePath, "*.png");
string allFiles = QUOTE + String.Join(SEPARATOR, files) + QUOTE;
Console.WriteLine(@"cmd.exe /c cd C:\Tesseract-OCR && " + allFiles);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM