C# CopyFileEx - ProgressRoutine:我们真的需要在进程中关闭目标文件句柄吗?
C# CopyFileEx - ProgressRoutine : do we really need to close the destination file handle while progress?
当传输的字节大小大于或等于总文件长度时,我试图关闭 ProgressRoutine
中的句柄。但是整个操作很少抛出 System.IO.IOException : The Handle is invalid.
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
}
如果有效,为什么会出错?
我们真的需要关闭 handle 还是它会被 CopyFileEx
关闭?但是如果我删除代码 CloseHandle
我永远不会得到这个异常。但是目标文件在这个副本之后被另一个操作使用,这就是我装备这个的原因。!
请帮助避免 System.IO.IOException : The handle is invalid
错误。
您不得关闭手柄。句柄归 CopyFileEx
所有,它会关闭它们。删除对 CloseHandle
的调用。
当传输的字节大小大于或等于总文件长度时,我试图关闭 ProgressRoutine
中的句柄。但是整个操作很少抛出 System.IO.IOException : The Handle is invalid.
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
}
如果有效,为什么会出错?
我们真的需要关闭 handle 还是它会被 CopyFileEx
关闭?但是如果我删除代码 CloseHandle
我永远不会得到这个异常。但是目标文件在这个副本之后被另一个操作使用,这就是我装备这个的原因。!
请帮助避免 System.IO.IOException : The handle is invalid
错误。
您不得关闭手柄。句柄归 CopyFileEx
所有,它会关闭它们。删除对 CloseHandle
的调用。