เรียกใช้พรอมต์คำสั่ง


605

มีวิธีการเรียกใช้คำสั่งที่พร้อมรับคำสั่งจากภายในแอปพลิเคชัน C # หรือไม่? ถ้าเป็นเช่นนั้นฉันจะทำสิ่งต่อไปนี้:

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

สิ่งนี้จะรวมไฟล์ RAR ไว้ภายในรูปภาพ JPG ฉันแค่สงสัยว่ามีวิธีการทำเช่นนี้โดยอัตโนมัติใน C #


6
ทำซ้ำของstackoverflow.com/questions/181719/… (มีคำตอบที่ทำในสิ่งที่คุณต้องการ)
Matt Hamilton

stackoverflow.com/a/5367686/492มีคำตอบที่ดีกว่า
CAD bloke

คำตอบ:


917

นี่คือทั้งหมดที่คุณต้องทำเพื่อเรียกใช้คำสั่งเชลล์จาก C #

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เช่นนั้นจะไม่ทำงาน วิธีสกอตต์เฟอร์กูสันกล่าวว่า: มันว่า "ดำเนินการคำสั่งที่ระบุโดยสตริงและยุติแล้ว."


166
/ C ดำเนินการคำสั่งที่ระบุโดยสายอักขระและจากนั้นจะสิ้นสุดลง
Scott Ferguson

16
เพียงแค่จะบอก cmd ในการทำงานและยุติ (รอ Dont สำหรับการป้อนข้อมูลผู้ใช้ใด ๆ เพื่อปิดหน้าต่าง)
RameshVel

3
ขอบคุณอีกหนึ่งคำถาม มีวิธีซ่อนพรอมต์คำสั่งระหว่างนี้หรือไม่?
ผู้ใช้

9
ฉันไม่เห็นว่าฉันเป็นคนเดียวที่คิดว่านี่เป็นความคิดที่น่ากลัว ใช่มันใช้งานได้ แต่มันผิดทั้งหมด กระบวนการวางไข่ CMD เพื่อดำเนินการ IO อย่างง่ายผิดแม้ว่าจะใช้งานได้ก็ตาม อ่านเอกสารในเนมสเปซ System.IO มีฟังก์ชันการทำงานมากเกินพอที่จะทำสิ่งที่คุณต้องทำโดยไม่ต้องวางไข่กระบวนการที่ไม่จำเป็น
อินสแตนซ์ฮันเตอร์

56
FYI: ใช้ process.WaitForExit () เพื่อรอให้กระบวนการเสร็จสมบูรณ์ก่อนดำเนินการต่อและดำเนินการ ExitCode เพื่อรับรหัสทางออกของกระบวนการ
shindigo

122

พยายามแก้ปัญหา @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());

2
ดีฉันให้มันไม่มีโอกาสคิดว่าในเครื่องของฉันมีข้อ จำกัด ผู้ดูแลระบบหรือป้องกันไวรัส แต่ .. รหัสข้างต้นใช้งานได้! ขอบคุณ Ogglas
Pete Kozak

6
บรรทัดนี้: cmd.StartInfo.CreateNoWindow = true บันทึกวันของฉัน
Ganesh Kamath - 'Code Frenzy'

มีวิธีการดำเนินการหลายคำสั่งในหนึ่งเดียวcmd.StandardInput.WriteLine(@"cd C:\Test; pwd")
Zach Smith

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

2
อะไรคือ@สัญญาณใน C #?
Pacerier

6
@Pacerier มันบอกให้คอมไพเลอร์หนีตัวละครทุกตัวที่ปกติจะต้องหลบหนีในสตริงในกรณีนี้ \ ดังนั้นหากไม่มี \ รหัสของคุณจะดูเหมือนproc1.FileName = "C:\\Windows\\System32\\cmd.exe";
James Ko

1
หนึ่งควรทราบว่าproc1.Verb = "runas";ทำให้กระบวนการนี้ทำงานด้วยสิทธิ์ระดับสูง ... นี้ไม่ได้ตั้งใจเสมอ
Dinei

1
ฉันจะทำให้หน้าต่าง cmd นี้ไม่ปิดหลังจากเสร็จสิ้นได้อย่างไร
Hrvoje T

1
ฉันพบว่าการเรียก 'เส้นทางซีดี' เข้าร่วมโดย '&&' กับคำสั่งอื่น ๆ ในบรรทัดจะดำเนินการครั้งสุดท้ายแม้ว่ามันจะหายไปก่อน ของคุณ: 'proc1.WorkingDirectory = @ "C: \ Windows \ System32";' มีประโยชน์มาก! ขอบคุณ!
Nozim Turakulov

11

ไม่มีคำตอบข้างต้นที่ช่วยด้วยเหตุผลบางอย่างดูเหมือนว่าพวกเขากวาดข้อผิดพลาดภายใต้พรมปูพื้นและทำให้คำสั่งการแก้ไขปัญหาของคนยาก ดังนั้นฉันเลยไปกับอะไรแบบนี้บางทีมันอาจช่วยคนอื่นได้:

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

หากฉันต้องการรวบรวมในแอปพลิเคชันคอนโซลแบบสแตนด์อะโลนจะต้องเพิ่มรหัสอื่นเพื่อให้ใช้งานได้ (ฉันเป็น noob สำหรับเนื้อหาการเขียนโปรแกรมทั้งหมดนี้ทำสคริปต์บางอย่างเท่านั้น) ฉันใช้ csc.exe btw
script'n'code

@copyitright เนมสเปซและคลาส หากคุณเพิ่งสร้างโครงการใหม่พวกเขาจะถูกสร้างขึ้นสำหรับคุณ
coinbird

อา. ไม่เป็นไร. ถ้าคุณใช้cmd.exeแอพคุณสามารถส่งคำสั่งเป็นอาร์กิวเมนต์
Zach Smith

สำหรับลูกหลาน: ฉันต้องการให้กระบวนการรันecho Hello World!และแสดงเอาต์พุตคำสั่งในหน้าต่าง cmd ที่ปรากฏขึ้น Filename = @"echo"ดังนั้นผมจึงพยายาม: Arguments = "Hello World!", UseShellExecute = false, RedirectStandardOuput = false, CreateNoWindow = false, สิ่งนี้อนุญาตให้หน้าต่าง cmd ของแอปพลิเคชันหลักแสดง "Hello World!" (ซึ่งสมเหตุสมผลเนื่องจาก stdout ไม่ได้ถูกเปลี่ยนเส้นทางไปยังกระบวนการย่อย)
Minh Tran

10

แม้ว่าเทคนิคนี้จะไม่ตอบคำถามโดยตรง แต่ก็ตอบคำถามว่าจะทำอย่างไรในสิ่งที่โปสเตอร์ดั้งเดิมต้องการทำ: รวมไฟล์เข้าด้วยกัน หากมีสิ่งใดสิ่งนี้เป็นโพสต์เพื่อช่วยให้มือใหม่เข้าใจว่า Instance Hunter และ Konstantin กำลังพูดถึงอะไร

นี่เป็นวิธีที่ฉันใช้เพื่อรวมไฟล์ (ในกรณีนี้คือ 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);
            }
        }
    }
}

9

หากคุณต้องการเปิดหน้าต่าง cmd หรือต้องการใช้งานใน winform / wpf ให้ใช้เช่นนี้

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

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

/ K

จะเปิดหน้าต่าง cmd


ดี พบเอกสารนี้สำหรับcmdคำสั่งและพารามิเตอร์
ปิอุสที่

8

ใช่มี (ดูลิงค์ในความคิดเห็นของ Matt Hamilton) แต่จะง่ายกว่าและดีกว่าถ้าใช้คลาส IO ของ. NET คุณสามารถใช้ File.ReadAllBytes เพื่ออ่านไฟล์จากนั้น File.WriteAllBytes เพื่อเขียนเวอร์ชัน "ฝังตัว"


11
การโหลดไฟล์ทั้งไฟล์ลงในหน่วยความจำเพียงเพื่อผนวกต่อกันนั้นไม่ได้มีประสิทธิภาพมากนักโดยเฉพาะถ้าไฟล์มีขนาดใหญ่พอ
Konstantin Spirin

7
ลองมองดูวิญญาณของคำตอบ ประเด็นก็คือว่า. NET มีคลาสและฟังก์ชั่น IO มากพอที่จะทำสิ่งนี้โดยไม่ต้องเรียกใช้เชลล์ระบบปฏิบัติการ ฟังก์ชั่นเฉพาะที่ฉันกล่าวถึงอาจไม่ได้ดีที่สุด แต่ฟังก์ชั่นนั้นง่ายที่สุด มันไม่สมเหตุสมผลเลยที่จะโทรออกไปหาเชลล์เพื่อทำสิ่งนี้
อินสแตนซ์ฮันเตอร์

7

คุณสามารถทำได้โดยใช้CliWrapในหนึ่งบรรทัด:

var stdout = new Cli("cmd")
         .Execute("copy /b Image1.jpg + Archive.rar Image2.jpg")
         .StandardOutput;

ฉันลงคะแนนเสียงให้กับสิ่งนี้ ... แต่ดูเหมือนว่า repo จะหายไปในขณะนี้:Unable to find package 'CliWrap' at source
Zach Smith

1
@ZachSmith ไม่แน่ใจว่าสิ่งที่คุณหมายถึงnuget.org/packages/CliWrapดูเหมือนจะทำงานได้ดี ลิงค์เดิมด้วย
Tyrrrz

Ah.sorry .. ด้วยเหตุผลบางอย่างเมื่อฉันไม่สามารถเชื่อมต่อกับ repug nuget ของฉันผ่าน vpn ฉันไม่สามารถติดตั้งแพ็กเกจนี้ได้ นักเก็ตส่วนใหญ่ยังคงเป็นปริศนาสำหรับฉัน จะต้องตั้งค่าผิด
ซัคสมิ ธ


5

นี่คือรุ่นรหัสที่ง่ายและน้อยกว่าเล็กน้อย มันจะซ่อนหน้าต่างคอนโซลด้วย -

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

5

หากคุณต้องการเรียกใช้คำสั่งในโหมด async - และพิมพ์ผลลัพธ์ คุณเรียนชั้นนี้ได้:

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

}

2

คุณสามารถทำได้โดยใช้วิธีการดังต่อไปนี้ (ดังที่กล่าวไว้ในคำตอบอื่น ๆ ):

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

1

คุณสามารถใช้เพียงแค่เขียนรหัสในการ.batขยายรูปแบบรหัสของไฟล์แบทช์:

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

ใช้รหัส c # นี้:

Process.Start("file_name.bat")


หากคุณต้องการซ่อน cmd ในขณะที่ใช้งานคุณสามารถใช้โค้ดสคริปต์พื้นฐานแบบวิชวลแบบง่าย ๆ ในการ.vbsขยายรูปแบบรหัส:CreateObject("Wscript.Shell").Run "filename.bat",0,True
XMMR12
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.