Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 发送ctrl+;c中的cmd.exe进程#_C#_.net_Winforms_Cmd - Fatal编程技术网

C# 发送ctrl+;c中的cmd.exe进程#

C# 发送ctrl+;c中的cmd.exe进程#,c#,.net,winforms,cmd,C#,.net,Winforms,Cmd,我目前正在为自己编写一个小小的C#备份程序。我使用标准的windows窗体作为界面,并将cmd.exe作为新进程调用,然后在此新进程中使用XCOPY。除了我想添加的最后一个功能,即中断操作的能力之外,其他功能都运行得很好 在本机命令提示符下,我可以使用ctrl+c清晰地执行此操作,但尽管我可以尝试,但我无法使用winforms和process方法复制此功能。我尝试重定向标准输入,并使用它将consolespecialkeys.ControlC发送到进程,我还尝试发送0x03和“/x03”,我在其

我目前正在为自己编写一个小小的C#备份程序。我使用标准的windows窗体作为界面,并将cmd.exe作为新进程调用,然后在此新进程中使用XCOPY。除了我想添加的最后一个功能,即中断操作的能力之外,其他功能都运行得很好

在本机命令提示符下,我可以使用ctrl+c清晰地执行此操作,但尽管我可以尝试,但我无法使用winforms和process方法复制此功能。我尝试重定向标准输入,并使用它将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();

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

我不想成为一名贝塞尔维瑟,但我认为你最好在程序中进行复制。使用System.IO名称空间中的File、Directory和其他类,非常简单,让您可以完全控制报告进度,取消操作等。

只需较少的代码行就可以循环遍历子目录和文件并逐个复制它们,这样您就不必担心控制另一个进程了。

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

你可以做的不是阻塞,而是在一个循环中睡眠,定期检查用户是否通过你的C#UI请求终止进程。如果收到此事件,则显式终止进程。否则,您将等待另一个间隔,直到该过程完成


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

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

那么我们能得到这个问题的答案吗

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

很抱歉,它在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

正如其他人所说,有更好的方法来完成这项任务。然而,这并不能回答你的问题。我使用了与您在这里展示的类似的技术来自动化各种任务,并且发现它非常有用。但有时事情会变得非常糟糕,你希望在事情变得更糟之前,这个过程能得到纾困;p

下面是您的示例的问题:

XCopyStartInfo.CreateNoWindow=true


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

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

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

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


要从C#实现这一点,您可能需要访问-在C#中编写Win32 API函数原型时的救星。

非常感谢您的建议。老实说,我可能对使用XCOPY的决心有点犹豫不决。我开始使用它是为了纯粹的简单性(而不是编写递归foreach循环),但随着我开始向我的项目中添加更多的层,我认为XCOPY已经成为一种越来越不高效的处理工作的方式。我现在已经使用.Net的System.IO重新开始实际的复制引擎。我们来看看我是怎么做的。再次感谢您的投入和快速回复。正如我在上面对Tor Haugen所说的,我认为您是对的,在项目的这个阶段使用XCOPY可能有点违反直觉。不过当时似乎是个好主意。感谢您对另一种方法的输入和建议,我现在将尝试这种方法。我曾想知道waitforexit是否给我带来了问题,但在它和顽固坚持尝试将ctrl+c发送到我的流程之间,我从未真正给出您建议的解决方案。最后,根据这里的社区反馈,我想我无论如何都会放弃XCOPY,转而使用.Net的原生功能,但还是非常感谢您的建议,感谢您花时间回答。非常感谢。如果流程以“CreateNoWindow=true”开始,则这不起作用。