Skip to content

Instantly share code, notes, and snippets.

@tugberkugurlu
Created December 13, 2016 11:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tugberkugurlu/61a2055b4907c8f9103804a5454b9144 to your computer and use it in GitHub Desktop.
Save tugberkugurlu/61a2055b4907c8f9103804a5454b9144 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp6
{
// see: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363852(v=vs.85).aspx
class Program
{
private static string destinationFilePath = @"D:\images\copies\ubuntu-14.04.2-desktop-amd64.iso";
static void Main(string[] args)
{
int IsCancelled = 0;
var source = @"D:\images\ubuntu-14.04.2-desktop-amd64.iso";
bool result = CopyFileEx(source, destinationFilePath, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref IsCancelled, CopyFileFlags.COPY_FILE_OPEN_SOURCE_FOR_WRITE | CopyFileFlags.COPY_FILE_ALLOW_DECRYPTED_DESTINATION);
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());
}
}
private static void OnProgressChanged(double percentage)
{
Console.WriteLine($"Percentage: {percentage}");
}
private static void OnCompleted()
{
Console.WriteLine("Completed!");
}
private static 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 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();
}
return CopyProgressResult.PROGRESS_CONTINUE;
}
[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
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment