2015-01-29 7 views
0

전송 된 바이트 크기가 전체 파일 길이보다 크거나 같을 때 ProgressRoutine 핸들을 닫으려고했습니다. 그러나 전체 작업이 거의 System.IO.IOException : The Handle is invalid.C# CopyFileEx - ProgressRoutine : 진행 중에 대상 파일 핸들을 닫아야합니까?

bool result = CopyFileEx(source, destination, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, copyFileFlags); 
if (!result) 
{ 
    //when ever we get the result as false it means some error occured so get the last win 32 error. 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 
} 

여기가 발생하지 않는 CopyProgressHandler 방법

private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long streamByteTrans, uint dwStreamNumber, 
               CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData) 
{ 
    //when a chunk is finished call the progress changed. 
    if (reason == CopyProgressCallbackReason.CALLBACK_CHUNK_FINISHED) 
    { 
     OnProgressChanged((transferred/(double)total) * 100.0); 
    } 

    //transfer completed 
    if (transferred >= total) 
    { 
     if (CloseHandle(hDestinationFile)) // here is that valid!! ? 
     { 
      //if file is read only, remove read-only attribute(case to handle CD drive import) 
      FileAttributes attr = File.GetAttributes(destinationFilePath); 
      if ((attr & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) 
      { 
       attr = attr & ~FileAttributes.ReadOnly; 
       File.SetAttributes(destinationFilePath, attr); 
      } 

      OnCompleted(CopyCompletedType.Succeeded, null); 
     } 
     else 
     { 
      OnCompleted(CopyCompletedType.Exception, 
       new System.IO.IOException("Unable to close the file handle")); 
     } 
    } 

    return CopyProgressResult.PROGRESS_CONTINUE; 
} 
[System.Runtime.InteropServices.DllImport("Kernel32")] 
private extern static Boolean CloseHandle(IntPtr handle); 

[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 
} 

그 유효한지, 왜 오류가? 핸들을 닫아야하나요 아니면 CopyFileEx으로 닫습니까? 하지만 코드를 제거한 경우 CloseHandle이 예외는 결코 발생하지 않습니다. 그러나 대상 파일은이 사본 이후 다른 작업에서 사용됩니다.

System.IO.IOException : The handle is invalid 오류를 피하십시오.

+0

CopyProgressRoutine MSDN 항목에서는 파일 핸들을 닫아야 함을 언급하지 않았습니다. 핸들을 닫지 않고 몇 가지 문제가 있습니까? –

+0

예 @AlexFarber '다른 프로세스에서 파일을 사용했습니다.'다른 작업을 통해 파일을 다시 열려고 시도했습니다. 이것을 피하기 위해서'CloseHandle'을 넣었습니다. –

답변

1

핸들을 닫지 마십시오. 핸들은 CopyFileEx에 의해 소유되고 닫힙니다. CloseHandle로 전화를 제거하십시오.

+0

복사가 끝나면 즉시'CopyFileEx'가 그 핸들들을 닫을 것인가? 시간이 좀 걸리나요? –

+1

핸들은'CopyFileEx'가 리턴 할 때까지 닫힙니다. 이제 귀하의 안티 바이러스 소프트웨어가 방해가 될 수 있습니다. 아니면 다른 일이있을 수 있습니다. 그러나 일반적으로 달리 언급하지 않는 한, 사용자가 만든 핸들 만 닫습니다. 당신은 이것들을 만들지 않았고, 당신이 닫을 책임이 없습니다. –

+0

예 동의합니다 .. 고맙습니다 .. :) –