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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top