Enviar ctrl + c para um processo cmd.exe no c #
Pergunta
Atualmente estou escrevendo-me um pouco C # back-up programa. Eu estou usando um padrão do Windows formar para a interface, e estou chamando cmd.exe como um novo processo, e em seguida, usando XCOPY de dentro deste novo processo. ótimo trabalhar cada de coisa, exceto para esta última característica que eu quero adicionar no, que é a capacidade de quebrar a operação.
No prompt um comando nativo, eu posso fazer isso de forma limpa com ctrl + c, mas por mais que tentasse, não posso replicar essa funcionalidade usando as winforms e abordagem de processo. Eu tentei redirecionando o standardInput e usando isso para enviar consolespecialkeys.ControlC ao processo, eu também tentei enviar 0x03 e "/ x03", ambos os quais eu li em outros posts no fórum são código hexadecimal para ctrl + c . Nada que eu estou enviando está registrado, porém, e sair do processo mata a interface do usuário, mas deixa o xcopy.exe trabalhando em segundo plano. Matar resultados manualmente Xcopy.exe nele deixando o arquivo que estava copiando metade copiado e corrompido, não é algo que acontece com o ctrl + c em um prompt de comando.
Estou faltando alguma coisa óbvias? Eu sou novo-ish para C #, então eu vou segurar minhas mãos e admitir que este é provavelmente me ser lento ou mal-entendido como o processo está a trabalhar com cmd.exe. No entanto, desde processos suportam redirecionamento de entrada padrão, ele parece ser algo que deve funcionar ... pelo menos para mim. Eu coloquei o esquema básico de meu código abaixo, no caso, ajuda a identificar onde estou atrapalhando.
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();
Muito obrigado antecipadamente por qualquer ajuda ninguém pode oferecer.
Solução
Eu não quero ser um besserwisser, mas eu acho que você seria muito melhor fora de fazer a cópia dentro de seu programa. Usando arquivo, diretório e as outras classes no namespace System.IO, é realmente simples, e deixa-lo em controle total ao progresso relatório, cancelar as operações etc.
Outras dicas
Sim, fazendo a operação em .NET seria mais fácil. MAS, eu preciso enviar ctrl-c para um processo também, e eu não tenho essa opção.
Então será que podemos obter uma resposta a esta pergunta?
EDIT: Eu tenho que postar uma duplicata para obter uma resposta? E não, @ j0rd4n não respondeu a pergunta.
Como os outros disse, há melhores maneiras de realizar essa tarefa particular. No entanto, isso não responder à sua pergunta. Eu uso uma técnica semelhante ao que você mostrou aqui para automatizar várias tarefas e achar que é bastante útil. Às vezes as coisas vão muito mal embora e você quer que o processo para salvar antes que as coisas piorem. ; P
Aqui está o problema com o seu exemplo:
XCopyStartInfo.CreateNoWindow = true;
Set-lo para falso e ele irá processar XCopyProcess.CloseMainWindow () e XCopyProcess.Close (). Muito mais limpo do que usar Kill ().
Isso exigiria menos linhas de código para apenas loop sobre os subdiretórios e arquivos e copiá-los um por um e, em seguida, você não teria que se preocupar com controlando outro processo ...
Desculpe é em 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
Eu enviada com sucesso uma combinação CTRL-C a um processo cmd.exe criado com SW_HIDE -. Ou seja, uma janela cmd.exe escondido
A técnica consistia em usar EnumWindows para identificar o processo e fazê-lo da janela do punho (ele ainda tem um identificador para processar mensagens mesmo se não for visível).
Em seguida, eu usei PostMessage para enviar uma combinação ctrl-c para o processo. Isto teve o mesmo efeito que se um usuário tinha batido 'ctrl-c', enquanto a janela estava ativa.
Para fazer isso a partir de C #, você iria querer, provavelmente, visite http://pinvoke.net/ - um salva-vidas quando se trata de escrever Win32 protótipos de função API em C #.
Você terá que matar manualmente o processo se você quiser lidar com a cópia dessa maneira. Em seu código acima, você está chamando XCopyProcess.WaitForExit (...). Esta é uma chamada bloqueando assim o processo # pai C irá parar nesse ponto até que o processo filho terminar ou o intervalo de tempo decorrido.
O que você poderia fazer é em vez de bloqueio, você pode dormir em um loop rotineiramente verificar se o usuário tiver solicitado para matar o processo através do seu C # UI. Se você receber este evento, você mata explicitamente o processo. Caso contrário, você esperar por um outro intervalo até que o processo esteja concluído.
EDIT: eu concordo com os outros comentários, no entanto. Copiar directamente a partir do framework .NET em vez de usar xcopy.