将ctrl + c发送到c#中的cmd.exe进程

时间:2009-05-05 13:47:56

标签: c# .net winforms cmd

我正在为自己编写一个C#备份程序。我正在为接口使用标准的Windows窗体,并将cmd.exe作为一个新进程调用,然后在此新进程中使用XCOPY。除了我想要添加的最后一个功能外,每个东西都运行良好,这是打破操作的能力。

从本机命令提示符,我可以使用ctrl + c干净利落地完成此操作,但尽可能尝试,我无法使用winforms和process方法复制此功能。我已经尝试重定向standardinput并使用它来发送consolespecialkeys.ControlC到进程,我也尝试发送0x03和“/ x03”,我在其他论坛帖子上读到的都是ctrl + c的十六进制代码。我发送的任何内容都没有注册,退出进程会终止用户界面,但会让xcopy.exe在后台运行。手动杀死xcopy.exe导致它将复制的文件保留为半复制和损坏,而不是在命令提示符下使用ctrl + c发生的事情。

我错过了一些令人目眩的明显事物吗?我是C#的新手,所以我会举起手来承认这很可能是我很慢,或误解了进程如何使用cmd.exe。但是,由于进程支持标准输入重定向,所以至少应该对我起作用。我已经在下面列出了我的代码的基本轮廓,以防它有助于确定我搞砸了。

string XCopyArguments = "\"" + dir.FullName + "\" \"" + destination + "\" /D /S /I /E";  
Process XCopyProcess = new Process();  
ProcessStartInfo XCopyStartInfo = new ProcessStartInfo(); 
XCopyStartInfo.FileName = "CMD.exe ";  
XCopyStartInfo.RedirectStandardError = true;
XCopyStartInfo.RedirectStandardOutput = true;
XCopyStartInfo.RedirectStandardInput = true;
XCopyStartInfo.UseShellExecute = false;
XCopyStartInfo.CreateNoWindow = true;
XCopyStartInfo.Arguments = " /D /c XCOPY " + XCopyArguments;
XCopyProcess.EnableRaisingEvents = true;
XCopyProcess.StartInfo = XCopyStartInfo;
XCopyProcess.Start();                
XCopyProcess.WaitForExit(15000);
int ExitCode = XCopyProcess.ExitCode;
if (ExitCode > 0 & !XCopyProcess.HasExited)
{
XCopyProcess.Kill();
}
XCopyProcess.Dispose();

非常感谢任何人提供的任何帮助。

7 个答案:

答案 0 :(得分:13)

我不想成为besserwisser,但我认为你在程序内部进行复制要好得多。使用File.IO名称空间中的文件,目录和其他类,它非常简单,让您完全控制报告进度,取消操作等。

答案 1 :(得分:3)

是的,在.NET中进行操作会更容易。但是,我还需要将ctrl-c发送到进程,我没有那个选项。

那么我们可以回答这个问题吗?

编辑:我是否必须发布重复内容才能获得答案?不,@ j0rd4n没有回答这个问题。

答案 2 :(得分:2)

与其他人一样,有更好的方法来完成这项特定任务。但是,这不能回答你的问题。我使用了类似于此处所示的技术来自动执行各种任务并发现它非常有用。有时事情会非常糟糕,你希望在事情变得更糟之前保住这个过程。 ; P

以下是您的示例的问题:

XCopyStartInfo.CreateNoWindow = true;

将其设置为false,然后它将处理XCopyProcess.CloseMainWindow()和XCopyProcess.Close()。比使用Kill()更清洁。

答案 3 :(得分:1)

只需要更少的代码行来循环遍历子目录和文件并逐个复制它们,然后您就不必担心控制另一个进程......

答案 4 :(得分:1)

抱歉,这是在VB.NET中。

Declare Function GenerateConsoleCtrlEvent Lib "kernel32" ( _
                    ByVal dwCtrlEvent As Integer, _
                    ByVal dwProcessGroupId As Integer _
                    ) As Integer

Private Const CTRL_C_EVENT As Integer = 0

Private Sub SendCtrlC()
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)

    ' send a Ctrl-C to this process
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, currentpid)

    ' send a Ctrl-C to the cmd process
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, cmdpid)
End Sub

答案 5 :(得分:1)

我已成功将CTRL-C组合发送到使用SW_HIDE创建的cmd.exe进程 - 即隐藏的cmd.exe窗口。

该技术是使用EnumWindows来识别进程并获取它的窗口句柄(它仍然有一个处理消息的句柄,即使它不可见)。

接下来,我使用PostMessage将ctrl-c组合发布到流程中。这与用户在窗口处于活动状态时点击“ctrl-c”的效果相同。

要从C#执行此操作,您可能希望访问http://pinvoke.net/ - 在C#中编写Win32 API函数原型时的救命稻草。

答案 6 :(得分:0)

如果要以这种方式处理复制,则必须手动终止进程。在上面的代码中,您正在调用XCopyProcess.WaitForExit(...)。这是一个阻塞调用,因此父C#进程将在此时停止,直到子进程完成或时间间隔已经过去。

你可以做的不是阻止,你可以定期睡觉,检查用户是否已经通过你的C#UI请求杀死进程。如果您收到此事件,则明确终止该进程。否则,等待另一个间隔,直到该过程结束。

编辑:但我同意其他评论。直接从.NET框架复制而不是使用xcopy。