none
Como cancelar um processo de cópia de arquivos em c#?

    Question

  • Pessoal, bom dia. Gostaria de saber se vocês poderiam me ajudar, eu estou salvando os

    caminhos acessados anteriormente pelo usuário através do settings do programa. Só que eu

    preciso cancelar a operação de cópia que meu programa faz em um btnCancelar quando eu utilizo

    o  //Process.GetCurrentProcess().Kill(); da certo, porém os caminhos não ficam armazenados, pois

    o Kill(); finaliza todos os processos da application. Acredito que se eu cancelasse somente o

    File.CopyTo daria certo... alguém poderia me dizer eu poderia fazer isso?

    Agradeço desde já.


    Th3W4rl0ck

    Monday, November 19, 2012 2:02 PM

All replies

  • Não é tão simples.

    /// <summary>
    /// PInvoke wrapper for CopyEx
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363852.aspx
    /// </summary>
    public class XCopy
    {
        public static void Copy(string source, string destination, bool overwrite, bool nobuffering)
        {
             new XCopy().CopyInternal(source, destination, overwrite, nobuffering, null);            
        }
    
        public static void Copy(string source, string destination, bool overwrite, bool nobuffering, EventHandler<ProgressChangedEventArgs> handler)
        {            
             new XCopy().CopyInternal(source, destination, overwrite, nobuffering, handler);            
        }
    
        private event EventHandler Completed;
        private event EventHandler<ProgressChangedEventArgs> ProgressChanged;
    
        private int IsCancelled;
        private int FilePercentCompleted;
        private string Source;
        private string Destination;        
    
        private XCopy()
        {
            IsCancelled = 0;
        }
    
        private void CopyInternal(string source, string destination, bool overwrite, bool nobuffering, EventHandler<ProgressChangedEventArgs> handler)
        {
            try
            {
                CopyFileFlags copyFileFlags = CopyFileFlags.COPY_FILE_RESTARTABLE;
                if (!overwrite)
                    copyFileFlags |= CopyFileFlags.COPY_FILE_FAIL_IF_EXISTS;
    
                if (nobuffering)
                    copyFileFlags |= CopyFileFlags.COPY_FILE_NO_BUFFERING;
    
                Source = source;
                Destination = destination;
    
                if (handler != null)
                    ProgressChanged += handler;
    
                bool result = CopyFileEx(Source, Destination, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, copyFileFlags);
                if (!result)
                    throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            catch (Exception)
            {
                if (handler != null)
                    ProgressChanged -= handler;
    
                throw;
            }
        }
    
        private void OnProgressChanged(double percent)
        {
            // only raise an event when progress has changed
            if ((int)percent > FilePercentCompleted)
            {
                FilePercentCompleted = (int)percent;
    
                var handler = ProgressChanged;
                if (handler != null)
                    handler(this, new ProgressChangedEventArgs((int)FilePercentCompleted, null));
            }
        }
    
        private void OnCompleted()
        {
            var handler = Completed;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    
        #region PInvoke
    
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel, CopyFileFlags dwCopyFlags);
    
        private delegate CopyProgressResult CopyProgressRoutine(long TotalFileSize, long TotalBytesTransferred, long StreamSize, long StreamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason,
                                                        IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData);
    
        private enum CopyProgressResult : uint
        {
            PROGRESS_CONTINUE = 0,
            PROGRESS_CANCEL = 1,
            PROGRESS_STOP = 2,
            PROGRESS_QUIET = 3
        }
    
        private enum CopyProgressCallbackReason : uint
        {
            CALLBACK_CHUNK_FINISHED = 0x00000000,
            CALLBACK_STREAM_SWITCH = 0x00000001
        }
    
        [Flags]
        private enum CopyFileFlags : uint
        {
            COPY_FILE_FAIL_IF_EXISTS = 0x00000001,
            COPY_FILE_NO_BUFFERING = 0x00001000,
            COPY_FILE_RESTARTABLE = 0x00000002,
            COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004,
            COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008
        }
    
        private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long streamByteTrans, uint dwStreamNumber,
                                                       CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData)
        {
            if (reason == CopyProgressCallbackReason.CALLBACK_CHUNK_FINISHED)
                OnProgressChanged((transferred / (double)total) * 100.0);
    
            if (transferred >= total)
                OnCompleted();
    
            return CopyProgressResult.PROGRESS_CONTINUE;
        }
    
        #endregion
    
    }

    Usa-se assim:

    XCopy.Copy(networkFile.FullPath, temporaryFilename, true, true, (o, pce) => 
    {
        worker.ReportProgress(pce.ProgressPercentage, networkFile);
    });

    Bom, espero que ajude, aqui está a referência: http://stackoverflow.com/questions/187768/can-i-show-file-copy-progress-using-fileinfo-copyto-in-net


    Take a look at WPF FlashMessage
    About.me

    Tuesday, November 20, 2012 7:29 PM
  • Cara, desculpa sou iniciante em programação, mais esse código está em Asp ou é impressão minha ?

    Eu não consegui entender muito esse código...

    Acredito se eu parar o método ProcessaXML() também da certo. Só que como?

    Mesmo assim Obrigado

    Abraços...


    Th3W4rl0ck


    Wednesday, November 21, 2012 1:58 AM
  • Asp? Não... é c#

    Não precisa entender o código, é só copiar e colar.


    Take a look at WPF FlashMessage
    About.me

    Wednesday, November 21, 2012 10:06 AM
  • Ok, criei a classe Xcopy, e chamei o códigoabaixo no btnCancelar.

    XCopy.Copy(networkFile.FullPath, temporaryFilename, true, true, (o, pce) => 
    {
        worker.ReportProgress(pce.ProgressPercentage, networkFile);
    });

    Porém esta dando uns erros, tirei um print. Dá uma olhada...

    Não reconhece o "ProgressChangedEventArgs" e o "DllImport"


    Th3W4rl0ck

    Wednesday, November 21, 2012 1:29 PM
  • Adicione:

    using System.Runtime.InteropServices;

    []'s


    Se a minha postagem ajudou, marque-a como resposta ou vote como útil.

    Wednesday, November 21, 2012 1:43 PM
  • ué cara, você tem que importar o namespace.

    using System.Runtime.InteropServices;


    Take a look at WPF FlashMessage
    About.me

    Wednesday, November 21, 2012 1:44 PM
  • Pessoal só pra finalizar, ele não esta encontrando o

    networkFile

    no código abaixo. Não encotrei nenhuma referencia dele, o que pode ser ?

    XCopy.Copy(networkFile.FullPath, temporaryFilename, true, true, (o, pce) => 
    {
        worker.ReportProgress(pce.ProgressPercentage, networkFile);
    });


    Th3W4rl0ck

    Wednesday, November 21, 2012 2:05 PM
  • Boa tarde.
    Cara, ai você passa os parametros dos arquivos de cópia.

    Ex:

    string  _file = @"C:\teste.txt";
    string _to = @"C:\teste2.txt";
    XCopy.Copy(_file,_to,true,true, (o, pce) => 
    {
        worker.ReportProgress(pce.ProgressPercentage, _file);
    });

    Creio que seja assim que seja feito a utilização. O Joba Diniz pode te dar mais informações.

    []'s


    Se a minha postagem ajudou, marque-a como resposta ou vote como útil.



    • Edited by Rafael P Wednesday, November 21, 2012 3:05 PM
    Wednesday, November 21, 2012 3:02 PM
  • Rafael desse modo da erro de reference, mesmo assim muito obrigado...

    Th3W4rl0ck

    Wednesday, November 21, 2012 3:24 PM
  • Rafael desse modo da erro de reference, mesmo assim muito obrigado...

    Th3W4rl0ck

    Em qual linha da erro ?
    Você adicionou um BackgroundWorker ?
    Adicione: using System.ComponentModel;

    BackgroundWorker worker = new BackgroundWorker();
    string  _file = @"C:\teste.txt";
    string _to = @"C:\teste2.txt";
    XCopy.Copy(_file,_to,true,true, (o, pce) => 
    {
    	worker.ReportProgress(pce.ProgressPercentage, _file);
    });


    []'s


    Se a minha postagem ajudou, marque-a como resposta ou vote como útil.

    Wednesday, November 21, 2012 3:49 PM
  • Qual erro está dando depois da modificação que o Rafael passou?

    Lembrando que o código:

    XCopy.Copy(_file,_to,true,true, (o, pce) => 
    {
        //COLOQUE SEU CÓDIGO AQUI
    });

    é um EXEMPLO de como se usa a classe. No caso, o cara criou um "BackgroundWorker" chamado "worker" e foi reportando o processo da cópia... Você coloca o código que quiser.

    Agora, estudando melhor o código, não sei se é possível cancelar o evento.. talvez tenha que modificar alguma coisa, pois parece que ele só reporta o processo de cópia (quanto copiou)


    Take a look at WPF FlashMessage
    About.me

    Wednesday, November 21, 2012 3:52 PM
  • Pessoal ta dando erro no  

    XCopy.Copy(_file,_to,true,true, (o, pce) => 

    "No overload for method 'Copy', takes 6 arguments"

    att


    Th3W4rl0ck

    Wednesday, November 21, 2012 4:02 PM