How to copy big file 5g with task and within impersonation

Dani_S 2,886 Reputation points
2024-04-18T08:06:36.18+00:00

Hi,

How to copy big file 5G from source to destination using

impersonation:

WindowsIdentity.RunImpersonated(

ImpersonationHelper.Token

Thanks,

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,458 questions
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
2,971 questions
{count} votes

Accepted answer
  1. Jiale Xue - MSFT 36,391 Reputation points Microsoft Vendor
    2024-04-23T06:06:21.48+00:00

    Hi @דני שטרית , Welcome to Microsoft Q&A,

    Updated:

    The problem solved. The code is good.the problematic USB was not of NTFS type. Ntfs allow to copy more than 4 Giga.


    Regarding the copying of large files, since large files cannot be completely loaded into memory, you cannot use the File pointer to operate it.

    In c#, you can use FileStream to accomplish this requirement, because FileStream allows reading and writing files in chunks, that is, splitting large files into small chunks and writing them into new files in segments.

    You can refer to the following code. After testing, this code takes about 28 seconds to copy a 6G file.

    public static class FileCopyHelper
        {
            public static void CopyBigFile(string sSource, string sTarget)
            {
                using (FileStream fsRead = new FileStream(sSource, FileMode.Open, FileAccess.Read))
                {
                    using (FileStream fsWrite = new FileStream(sTarget, FileMode.Create, FileAccess.Write))
                    {
                        //define buffer If the buffer is too large, the memory usage will be too high and the computer will freeze.
                        byte[] bteData = new byte[12 * 1024 * 1024];
                        int r = fsRead.Read(bteData, 0, bteData.Length);
                        while (r > 0)
                        {
                            fsWrite.Write(bteData, 0, r);
                            double d = 100 * (fsWrite.Position / (double)fsRead.Length);
                            Console.WriteLine("{0}%", d);
                            r = fsRead.Read(bteData, 0, bteData.Length);
                        }
                        Console.WriteLine("Copying the large file successfully");
                    }
                }
            }
        }
    

    Best Regards,

    Jiale


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". 

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

3 additional answers

Sort by: Most helpful
  1. Khaled El-Sayed Mohamed 1,160 Reputation points
    2024-04-18T09:57:10.8333333+00:00

    Hi, Below is an equivalent .NET MAUI code snippet for copying a large file (5GB) from a source to a destination using impersonation:

    C#

    using System;
    using System.IO;
    using System.Security.Principal;
    using Microsoft.Maui.Essentials;
    
    namespace FileCopyApp
    {
        public class FileCopyService
        {
            public async Task CopyFileAsync(string sourceFilePath, string destinationFilePath)
            {
                try
                {
                    // Impersonate a user (e.g., service account) for the file copy operation
                    await ImpersonateUserAsync(async () =>
                    {
                        // Perform the file copy
                        await File.CopyAsync(sourceFilePath, destinationFilePath);
                        Console.WriteLine("File copied successfully!");
                    });
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error copying file: {ex.Message}");
                }
            }
    
            private async Task ImpersonateUserAsync(Func<Task> action)
            {
                // Replace ImpersonationHelper.Token with the actual token or credentials for impersonation
                // Ensure that the account used has appropriate permissions to read from the source and write to the destination
    
                // Example: Impersonate using a service account token
                var impersonationResult = await ImpersonateHelper.ImpersonateAsync(ImpersonationHelper.Token);
    
                if (impersonationResult.Success)
                {
                    try
                    {
                        await action.Invoke();
                    }
                    finally
                    {
                        // Revert impersonation
                        await ImpersonateHelper.RevertImpersonationAsync();
                    }
                }
                else
                {
                    Console.WriteLine($"Impersonation failed: {impersonationResult.ErrorMessage}");
                }
            }
        }
    }
    
    

    In this .NET MAUI code:

    Replace sourceFilePath and destinationFilePath with the actual paths of your source and destination files. The ImpersonateUserAsync method handles impersonation using the ImpersonateHelper class (similar to the previous example). Ensure that the account used for impersonation has the necessary permissions to read from the source location and write to the destination location. Remember to adjust the code according to your specific requirements and security considerations when integrating it into your .NET MAUI app.


  2. Bruce (SqlWork.com) 57,886 Reputation points
    2024-04-18T21:53:18.57+00:00

    to impersonate a user, you need to create a user token handle. this is typically done via LogonUser (advapi32.dll) to get the handle (you need user name, domain and password).

    depending on the source, often the token handle will not have impersonation permission. You use DuplicateTokenEx (advapi32.dll) to add the permission to the new handle. be sure to close the handles.

    see:

    https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.runimpersonated?view=net-8.0


  3. Bruce (SqlWork.com) 57,886 Reputation points
    2024-04-22T17:17:34.1233333+00:00

    sample impersonation code (windows only - requires full trust). also user running the app requires impersonate user permission.

        public class RunAs
        {
            private string _domain;
            private string _username;
            private string _password;
    
            [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
                                                int dwLogonType, int dwLogonProvider, 
                                                out SafeAccessTokenHandle phToken);
    
            public RunAs(string domain, string username, string password)
            {
                _domain = domain;
                _username = username;
                _password = password;
            }
    
            private SafeAccessTokenHandle GetTokenHandle()
            {
                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;
                SafeAccessTokenHandle tokenHandle;
    
                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(_username, _domain, _password,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    out tokenHandle);
    
                return returnValue ? tokenHandle : throw new Exception("Unable to impersonate user");
            }
    
            public void Execute(Action callback)
            {
                WindowsIdentity.RunImpersonated(GetTokenHandle(), callback);
            }
            public Task ExecuteAsync(Func<Task> callback)
            {
                return WindowsIdentity.RunImpersonated(GetTokenHandle(), async () => await callback.Invoke());
            }
    
        }
    

    note: using SafeAccessTokenHandle closes handle.

    0 comments No comments