如何在C#中执行一个cmd命令,然后在同一个窗口执行另一个跟随的命令?

5

我正在尝试开发一个程序,它可以通过一键操作来设置活动分区,省去了使用cmd命令的时间和技能。

我已经研究过System.Management名称空间,但是无法弄清楚如何使用它 :(

所以我只好使用CMD,我已经用C#编写了一个模块应用程序,基本上我想运行"DISKPART",然后在cmd窗口中启动diskpart,然后要求它选择“磁盘0”,然后选择“分区1”,最后选择“active”。

在CMD中自己完成这个操作很容易,但在应用程序中却证明很棘手 :( 我已经成功地让它在一个窗口中通过Process.Start运行DiskPart,然后让它打开一个新窗口并运行下一段代码,但因为新窗口还没有运行diskpart cmd,所以它不起作用>:(

有什么建议吗?

谢谢!

Ash


你不能将你的命令写入一个临时的.bat文件,然后使用Process.Start运行它吗? - IVlad
5个回答

4
只要您不对输出做出决策,就可以在C#应用程序中构建批处理文件,并通过Process.Start(...)启动该文件。 您需要生成两个文件。 第一个是runDiskPart.bat
diskpart /s myScript.dp
第二个是myScript.dp
...一些命令...
exit
显然,名称是完全任意的,但/s指令需要引用第二个文件的名称。

批处理文件听起来非常有趣,我已经成功启动了“diskpart”,但是和之前一样的问题是如何硬编码下一步该做什么?在我的屏幕上显示“DISKPART>”等待输入,现在我该如何添加命令以使其工作?顺便说一句,谢谢你们的快速回复! :) - Ash
就我所知,我是通过在命令提示符中运行“diskpart /?”找到了所有这些信息。 - Austin Salonen
啊!太棒了!谢谢你!我查看了帮助文件,但我很少使用DOS,以前也从未使用过批处理文件。这太棒了!非常感谢你! Ash - Ash

3

经过搜索,我认为你可以通过使用脚本文件来实现你想要的功能。请参阅此文

因此,在创建包含所需命令的script.txt文件后,您可以使用Process.Start运行diskpart /s script.txt


3

这可能需要一些阅读时间,提前向您道歉。这是我亲自尝试并测试过的方法,可能有更简单的方式,但这是我不断试错后总结出来的。

简而言之,这段代码可用于解决此问题。

抱歉,这个代码实际上没有经过测试。理论上是有效的。

public static void ChangeMe()
 {

 string docPath =
  Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

 string path1 = docPath + "\\Test.txt";
 string path2 = docPath + "\\Test.bat";

 string[] lines =
 {
     "select disk 0",
     "clean",
     "convert gpt",
     "create partition primary size=300",
     "format quick fs=ntfs label=Windows RE tools",
     "assign letter=T"
 };
 using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "test.txt")))
 {

     foreach (string line in lines)
         outputFile.WriteLine(line);
 }
 string[] lines =
 {
     "diskpart /s test.txt"
 };
 using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "test.bat")))
 {

     foreach (string line in lines)
         outputFile.WriteLine(line);
 }
 System.Diagnostics.Process.Start(path2);
 }

如果你想要做的事情可以用批处理完成,那么如果过于复杂的解决方法是让c#编写.bat文件并运行它。如果你需要用户输入,你可以将输入放入变量中,并让c#将其写入文件中。这种方式需要进行试错,因为这就像用另一个木偶来控制另一个木偶一样。使用Diskpart会更加复杂,因为你需要创建两个文件,一个是.bat文件,一个是txt文件。
下面是一个仅使用批处理文件的示例。在这种情况下,该函数是为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);

    }

就像我说的,这可能有点过于复杂,但只要我没有写错批处理命令,它就从未失败。

这是diskpart的代码。你必须理解命令提示符才能使它们起作用。对于diskpart,您不能像这样仅写脚本:

diskpart
select disk 0
clean
convert gpt
create partition primary size=300
format quick fs=ntfs label=Windows RE tools
assign letter=T

这是因为diskpart会打开它自己的窗口,而其他命令只会在命令提示符窗口中报错,所以你必须让C#先编写一个包含命令的文本文件,然后再编写一个批处理文件来调用刚刚编写的文本文件中的diskpart命令。
就像我一开始说的那样,这个方法其实没有经过测试,只是按照理论操作的。
public static void ChangeMe()
 {

 string docPath =
  Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

 string path1 = docPath + "\\Test.txt";
 string path2 = docPath + "\\Test.bat";

 string[] lines =
 {
     "select disk 0",
     "clean",
     "convert gpt",
     "create partition primary size=300",
     "format quick fs=ntfs label=Windows RE tools",
     "assign letter=T"
 };
 using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "test.txt")))
 {

     foreach (string line in lines)
         outputFile.WriteLine(line);
 }
 string[] lines =
 {
     "diskpart /s test.txt"
 };
 using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "test.bat")))
 {

     foreach (string line in lines)
         outputFile.WriteLine(line);
 }
 System.Diagnostics.Process.Start(path2);
 }

0

如果引入一个延迟,例如Thread.Sleep(1000),那么另一个进程就有时间完成第一个命令了,这个怎么样?


0
你真正想要做的是等待程序退出,然后继续下一个调用。请查看这个问题

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接