Domanda

Attualmente sto scrivendo un piccolo programma di backup in C #. Sto utilizzando un modulo di Windows standard per l'interfaccia e sto chiamando cmd.exe come nuovo processo, quindi utilizzo XCOPY da questo nuovo processo. Tutto funziona alla grande, ad eccezione di quest'ultima funzione che voglio aggiungere, che è la possibilità di interrompere l'operazione.

Da un prompt dei comandi nativo, posso farlo in modo pulito con ctrl + c, ma provando come potrei, non riesco a replicare questa funzionalità usando l'approccio winforms e process. Ho provato a reindirizzare l'input standard e ad usarlo per inviare consolespecialkeys.ControlC al processo, ho anche provato a inviare 0x03 e " / x03 " ;, entrambi i quali ho letto su altri post del forum sono codice esadecimale per ctrl + c. Tuttavia, nulla di ciò che sto inviando è registrato e l'uscita dal processo uccide l'interfaccia utente, ma lascia xcopy.exe funzionante in background. L'uccisione di xcopy.exe provoca la sua uscita manuale dal file che stava copiando e copiato per metà, non qualcosa che accade usando ctrl + c in un prompt dei comandi.

Mi sto perdendo qualcosa di palesemente ovvio? Sono new-ish in C #, quindi terrò le mani in alto e ammetto che è molto probabile che io sia lento o che fraintenda il funzionamento del processo con cmd.exe. Tuttavia, poiché i processi supportano il reindirizzamento dell'input standard, sembra qualcosa che dovrebbe funzionare ... almeno per me. Ho messo di seguito lo schema di base del mio codice, nel caso in cui aiuti a identificare dove sto sbagliando.

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

Molte grazie in anticipo per qualsiasi aiuto chiunque possa offrire.

È stato utile?

Soluzione

Non voglio essere un besserwisser, ma penso che faresti molto meglio a fare la copia all'interno del tuo programma. Utilizzando File, Directory e le altre classi nello spazio dei nomi System.IO, è davvero semplice e ti lascia il pieno controllo per segnalare progressi, annullare operazioni ecc.

Altri suggerimenti

Sì, l'operazione in .NET sarebbe più semplice. MA, devo anche inviare ctrl-c a un processo e non ho questa opzione.

Quindi possiamo per favore ottenere una risposta a questa domanda?

MODIFICA: Devo pubblicare un duplicato per ottenere una risposta? E no, @ j0rd4n non ha risposto alla domanda.

Come hanno detto gli altri, ci sono modi migliori per svolgere quel particolare compito. Tuttavia, ciò non risponde alla tua domanda. Uso una tecnica simile a quella che hai mostrato qui per automatizzare varie attività e la trovo abbastanza utile. A volte le cose vanno molto male e vuoi che il processo venga salvato prima che le cose peggiorino. ; P

Ecco il problema con il tuo esempio:

XCopyStartInfo.CreateNoWindow = true;

Impostalo su false e quindi elaborerà XCopyProcess.CloseMainWindow () e XCopyProcess.Close (). Molto più pulito rispetto all'utilizzo di Kill ().

Richiederebbe un numero inferiore di righe di codice per passare in loop sopra le sottodirectory e i file e copiarli uno per uno, quindi non dovresti preoccuparti di controllare un altro processo ...

Mi dispiace è in 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

Ho inviato correttamente una combinazione CTRL-C a un processo cmd.exe creato con SW_HIDE, ovvero una finestra nascosta cmd.exe.

La tecnica consisteva nell'utilizzare EnumWindows per identificare il processo e ottenere l'handle della finestra (ha ancora un handle per elaborare i messaggi anche se non è visibile).

Successivamente, ho usato PostMessage per pubblicare una combinazione ctrl-c nel processo. Ciò ha avuto lo stesso effetto che se un utente avesse premuto 'ctrl-c' mentre la finestra era attiva.

Per fare questo da C #, probabilmente vorrai visitare http://pinvoke.net/ - un vero toccasana quando si tratta di scrivere prototipi di funzioni API Win32 in C #.

Dovrai terminare manualmente il processo se vuoi gestire la copia in questo modo. Nel tuo codice sopra, stai chiamando XCopyProcess.WaitForExit (...). Questa è una chiamata di blocco in modo che il processo C # genitore si fermerà a quel punto fino a quando il processo figlio non sarà terminato o non sarà trascorso l'intervallo di tempo.

Quello che potresti fare è invece di bloccare, puoi dormire in un ciclo controllando regolarmente se l'utente ha richiesto di interrompere il processo tramite l'interfaccia utente di C #. Se ricevi questo evento, uccidi esplicitamente il processo. Altrimenti, aspetti un altro intervallo fino al termine del processo.

MODIFICA: sono d'accordo con gli altri commenti. Copia direttamente da .NET framework invece di utilizzare xcopy.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top