比较来自世界各地的卖家的域名和 IT 服务价格

我可以显示使用复制文件的进度吗? FileInfo.CopyTo// 在 .NET?

我创建了一个副本实用程序 c# /.NET 2.0 Framework/, 哪些副本文件,目录和递归子目录等。程序具有 GUI, 显示当前复制的文件,当前文件编号 /顺序/, 要复制的文件总数和已完成的复制操作的百分比。 还有一个基于当前文件的执行指示符。 / 文件总数。

我的问题与复制大文件复制有关。 我找不到一种方法来指定复制大文件的一般过程 /使用我当前的类结构使用该方法 FileInfo.CopyTo/. 作为解决方法,我划分文件复制和显示操作。 GUI 在自己的流中并设置视觉信号以显示工作是执行的。 至少用户知道程序未冻结并且仍然复制文件。

更好的是要基于总字节总数显示进度或者有一些事件的能力,或者有一些工作的事件 FileInfo.CopyTo, 指示从当前文件复制的字节总数。

我知道这个物业 FileInfo.Length, 所以我相信有办法 MacGuyver 我自己的事件,这是基于这一点,并且侧面有一个处理程序 GUI 阅读更新的东西 /也许基于验证属性 FileInfo.Length 有一些计时器的目标对象?/.

有谁知道我想念的方式? 如果我能避免这种情况,我宁愿不要重写你的类来通过流复制字节并以这种方式跟踪它 /虽然我想我可以陷入这条路线/.

先感谢您

PS - 目前我陷入了框架 .NET 2.0, 因此,任何需要函数的解决方案仅可用 >= 3.0, 它不适合我。

PPS-I以任何语言开放解决方案 .NET, 不仅 c#.
已邀请:

詹大官人

赞同来自:

fileinfo.copyto主要包裹 Win32 API 称呼 "CopyFile" 在 kernel32.dll. 此方法不支持进度的回调。

但是,方法 CopyFileEx 是吗,你可以写自己的shell .NET 在几分钟内,如下所述:
http://www.pinvoke.net/default ... ileEx

八刀丁二

赞同来自:

我也使用了所提供的实施

. 但是,然后我创建了一个包装,以确保更普美的™ API 用来 .NET.

使用

:


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


销售量


/// <summary>
/// PInvoke wrapper for CopyEx
/// [url=http://msdn.microsoft.com/en-us/library/windows/desktop/aa363852.aspx]http://msdn.microsoft.com/en-u ... .aspx[/url]
/// </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 &gt; 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 &gt;= total/
OnCompleted//;

return CopyProgressResult.PROGRESS_CONTINUE;
}

#endregion

}


</progresschangedeventargs></progresschangedeventargs></progresschangedeventargs>

三叔

赞同来自:

我知道一个派对有点迟到,但我造成了包装
CopyFileEx

, 哪个退货
Task

并接受
CancellationToken


IProgress<double>

. 不幸的是,他不会在框架里工作 .NET 2.0, 但对于那些使用的人 4.5, 这允许您使用关键字
await

.


public static class FileEx
{
public static Task CopyAsync/string sourceFileName, string destFileName/
{
return CopyAsync/sourceFileName, destFileName, CancellationToken.None/;
}

public static Task CopyAsync/string sourceFileName, string destFileName, CancellationToken token/
{
return CopyAsync/sourceFileName, destFileName, token, null/;
}

public static Task CopyAsync/string sourceFileName, string destFileName, IProgress<double> progress/
{
return CopyAsync/sourceFileName, destFileName, CancellationToken.None, progress/;
}

public static Task CopyAsync/string sourceFileName, string destFileName, CancellationToken token, IProgress<double> progress/
{
int pbCancel = 0;
CopyProgressRoutine copyProgressHandler;
if /progress != null/
{
copyProgressHandler = /total, transferred, streamSize, streamByteTrans, dwStreamNumber, reason, hSourceFile, hDestinationFile, lpData/ =&gt;
{
progress.Report//double/transferred / total * 100/;
return CopyProgressResult.PROGRESS_CONTINUE;
};
}
else
{
copyProgressHandler = EmptyCopyProgressHandler;
}
token.ThrowIfCancellationRequested//;
var ctr = token.Register/// =&gt; pbCancel = 1/;
var copyTask = Task.Run/// =&gt;
{
try
{
CopyFileEx/sourceFileName, destFileName, copyProgressHandler, IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE/;
token.ThrowIfCancellationRequested//;
}
finally
{
ctr.Dispose//;
}
}, token/;
return copyTask;
}

private static CopyProgressResult EmptyCopyProgressHandler/long total, long transferred, long streamSize, long streamByteTrans, uint dwStreamNumber, CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData/
{
return CopyProgressResult.PROGRESS_CONTINUE;
}

#region DLL Import

[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/;

delegate CopyProgressResult CopyProgressRoutine/
long totalFileSize,
long totalBytesTransferred,
long streamSize,
long streamBytesTransferred,
uint dwStreamNumber,
CopyProgressCallbackReason dwCallbackReason,
IntPtr hSourceFile,
IntPtr hDestinationFile,
IntPtr lpData/;

enum CopyProgressResult : uint
{
PROGRESS_CONTINUE = 0,
PROGRESS_CANCEL = 1,
PROGRESS_STOP = 2,
PROGRESS_QUIET = 3
}

enum CopyProgressCallbackReason : uint
{
CALLBACK_CHUNK_FINISHED = 0x00000000,
CALLBACK_STREAM_SWITCH = 0x00000001
}

[Flags]
enum CopyFileFlags : uint
{
COPY_FILE_FAIL_IF_EXISTS = 0x00000001,
COPY_FILE_RESTARTABLE = 0x00000002,
COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004,
COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008
}

#endregion
}


</double></double></double>

涵秋

赞同来自:

为所有圣徒的缘故,不要使用Streams创建自己的文件副本! 称呼 Win32 CopyFile API, 关于哪个提到的喘气可能会利用例如, DMA, 虽然我会把美元放在甜甜圈上,所以代码将不够 "smart" 为了这。

CopyFileEx 将正确与您相关联,或者您可以实施 BackgroundWorker, 这会监视目标文件的越来越大小并使用此信息更新执行指示符。 最后一个方法为您节省了 PInvoke, 但第一个可能在长期奔跑中有点清洁。

窦买办

赞同来自:

对于这样的事情,我回来了 Shell32 /或者那个 ShellUI? 我不知道/. 它为您提供了自己的对话 Windows, 哪些用户用于查看复制操作。 我假设它将替换您已经存在的对话,因此您可能是错误的答案,但您可以记住这些方案是有用的 "in a pinch".


Microsoft.VisualBasic.FileIO.FileSystem.CopyFile/
srcPath,
dstPath,
Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,
Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException
/;


是的,你必须参考 Microsoft.VisualBasic assembly. 一世
http://www.deploymentzone.com/ ... asic/
这是 assembly.

奔跑吧少年

赞同来自:

谢 @Gasper 和 @Dennis 有关说明 CopyFileEx.
我使用中断的副本扩展了丹尼斯的答案


/// <summary>
/// Type indicates how the copy gets completed.
/// </summary>
internal enum CopyCompletedType
{
Succeeded,
Aborted,
Exception
}

/// <summary>
/// Event arguments for file copy
/// </summary>
internal class FileCopyEventArgs : EventArgs
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="type"/>type of the copy completed type enum
/// <param name="exception"/>exception if any
public FileCopyEventArgs/CopyCompletedType type, Exception exception/
{
Type = type;
Exception = exception;
}

/// <summary>
/// Type of the copy completed type
/// </summary>
public CopyCompletedType Type
{
get;
private set;

}

/// <summary>
/// Exception if any happend during copy.
/// </summary>
public Exception Exception
{
get;
private set;
}

}

/// <summary>
/// PInvoke wrapper for CopyEx
/// [url=http://msdn.microsoft.com/en-us/library/windows/desktop/aa363852.aspx]http://msdn.microsoft.com/en-u ... .aspx[/url]
/// </summary>
internal class XCopy
{

private int IsCancelled;
private int FilePercentCompleted;

public XCopy//
{
IsCancelled = 0;
}

/// <summary>
/// Copies the file asynchronously
/// </summary>
/// <param name="source"/>the source path
/// <param name="destination"/>the destination path
/// <param name="nobuffering"/>Bufferig status
/// <param name="handler"/>Event handler to do file copy.
public void CopyAsync/string source, string destination, bool nobuffering/
{
try
{
//since we needed an async copy ..
Action action = new Action/
// => CopyInternal/source, destination, nobuffering/
/;
Task task = new Task/action/;
task.Start//;
}
catch /AggregateException ex/
{
//handle the inner exception since exception thrown from task are wrapped in
//aggreate exception.
OnCompleted/CopyCompletedType.Exception, ex.InnerException/;
}
catch /Exception ex/
{
OnCompleted/CopyCompletedType.Exception, ex/;
}
}

/// <summary>
/// Event which will notify the subscribers if the copy gets completed
/// There are three scenarios in which completed event will be thrown when
/// 1.Copy succeeded
/// 2.Copy aborted.
/// 3.Any exception occured.
/// These information can be obtained from the Event args.
/// </summary>
public event EventHandler<filecopyeventargs> Completed;
/// <summary>
/// Event which will notify the subscribers if there is any progress change while copying.
/// This will indicate the progress percentage in its event args.
/// </summary>
public event EventHandler<progresschangedeventargs> ProgressChanged;

/// <summary>
/// Aborts the copy asynchronously and throws Completed event when done.
/// User may not want to wait for completed event in case of Abort since
/// the event will tell that copy has been aborted.
/// </summary>
public void AbortCopyAsync//
{
Trace.WriteLine/"Aborting the copy"/;
//setting this will cancel an operation since we pass the
//reference to copyfileex and it will periodically check for this.
//otherwise also We can check for iscancelled on onprogresschanged and return
//Progress_cancelled .
IsCancelled = 1;

Action completedEvent = new Action/// =&gt;
{
//wait for some time because we ll not know when IsCancelled is set , at what time windows stops copying.
//so after sometime this may become valid .
Thread.Sleep/500/;
//do we need to wait for some time and send completed event.
OnCompleted/CopyCompletedType.Aborted/;
//reset the value , otherwise if we try to copy again since value is 1 ,
//it thinks that its aborted and wont allow to copy.
IsCancelled = 0;
}/;

Task completedTask = new Task/completedEvent/;
completedTask.Start//;
}


/// <summary>
/// Copies the file using asynchronos task
/// </summary>
/// <param name="source"/>the source path
/// <param name="destination"/>the destination path
/// <param name="nobuffering"/>Buffering status
/// <param name="handler"/>Delegate to handle Progress changed
private void CopyInternal/string source, string destination, bool nobuffering/
{
CopyFileFlags copyFileFlags = CopyFileFlags.COPY_FILE_RESTARTABLE;

if /nobuffering/
{
copyFileFlags |= CopyFileFlags.COPY_FILE_NO_BUFFERING;
}

try
{
Trace.WriteLine/"File copy started with Source: " + source + " and destination: " + destination/;
//call win32 api.
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///;
}
}
catch /Exception ex/
{
//the mesage will contain the requested operation was aborted when the file copy
//was cancelled. so we explicitly check for that and do a graceful exit
if /ex.Message.Contains/"aborted"//
{
Trace.WriteLine/"Copy aborted."/;
}
else
{
OnCompleted/CopyCompletedType.Exception, ex.InnerException/;
}
}
}

private void OnProgressChanged/double percent/
{
// only raise an event when progress has changed
if //int/percent &gt; FilePercentCompleted/
{
FilePercentCompleted = /int/percent;

var handler = ProgressChanged;
if /handler != null/
{
handler/this, new ProgressChangedEventArgs//int/FilePercentCompleted, null//;
}
}
}

private void OnCompleted/CopyCompletedType type, Exception exception = null/
{
var handler = Completed;
if /handler != null/
{
handler/this, new FileCopyEventArgs/type, exception//;
}
}

#region PInvoke

/// <summary>
/// Delegate which will be called by Win32 API for progress change
/// </summary>
/// <param name="total"/>the total size
/// <param name="transferred"/>the transferrred size
/// <param name="streamSize"/>size of the stream
/// <param name="streamByteTrans"/>
/// <param name="dwStreamNumber"/>stream number
/// <param name="reason"/>reason for callback
/// <param name="hSourceFile"/>the source file handle
/// <param name="hDestinationFile"/>the destination file handle
/// <param name="lpData"/>data passed by users
/// <returns>indicating whether to continue or do somthing else.</returns>
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 &gt;= total/
{
if /CloseHandle/hDestinationFile//
{
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
}

#endregion

}


客户可以创建一个类对象 XCopy 并调用方法 copy/abort.
</progresschangedeventargs></filecopyeventargs>

小姐请别说爱

赞同来自:

如果有人仍然陷入此问题 /10 多年后!/, 像我一样,我在功能周围创建了一个贝壳 CopyFileEx 和 MoveFileWithProgress /作为这里的一些答案/ 有一些额外的有用功能 /如异步,检查访问权限,字节格式,复制目录.../

在这里检查一下 -
https://github.com/martinchrza ... nager

https://www.nuget.org/packages ... ager/

要回复问题请先登录注册