2020年10月15日 星期四

C# 登入網路磁碟機且輸入帳號密碼(with .net core 2024 update)

Can you explain why DirectoryInfo.GetFiles produces this IOException?
以下程式碼來源如參考網站
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Company.Security
{
    public class ImpersonateUser : IDisposable
    {
        [DllImport("advapi32.dll", SetLastError=true)]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

        [DllImport( "kernel32", SetLastError = true )]
        private static extern bool CloseHandle(IntPtr hObject);

        private IntPtr userHandle = IntPtr.Zero;
        private WindowsImpersonationContext impersonationContext;

        public ImpersonateUser( string user, string domain, string password )
        {
            if ( ! string.IsNullOrEmpty( user ) )
            {
                // Call LogonUser to get a token for the user
                bool loggedOn = LogonUser( user, domain, password,
                    9 /*(int)LogonType.LOGON32_LOGON_NEW_CREDENTIALS*/,
                    3 /*(int)LogonProvider.LOGON32_PROVIDER_WINNT50*/,
                    out userHandle );
                if ( !loggedOn )
                    throw new Win32Exception( Marshal.GetLastWin32Error() );

                // Begin impersonating the user
                impersonationContext = WindowsIdentity.Impersonate( userHandle );
            }
        }

        public void Dispose()
        {
            if ( userHandle != IntPtr.Zero )
                CloseHandle( userHandle );
            if ( impersonationContext != null )
                impersonationContext.Undo();
        }
    }
}
使用方法
using ( new ImpersonateUser( "UserID", "Domain", "Password" ) )
{
    // Any IO code within this block will be able to access the remote server.
}
.net Core(20240219更新) Only windows server
 [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);

 const int LOGON32_PROVIDER_DEFAULT = 0;
 //This parameter causes LogonUser to create a primary token. 
 const int LOGON32_LOGON_INTERACTIVE = 2;
 // Call LogonUser to obtain a handle to an access token. 
 SafeAccessTokenHandle safeAccessTokenHandle;
 public IActionResult X()
 {
            try
            {
               
                bool returnValue = LogonUser("test", "mydomain", "test123", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeAccessTokenHandle);
                if (!returnValue)
                    throw new Exception("登入unc路徑錯誤!!");

 
                WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>
                {
                    var basepath = @"\\192.168.0.1\testFiles";

                    if (!Directory.Exists(basepath))
                    {
                        throw new Exception("無資料夾-" + basepath);
                    }

                    DirectoryInfo root = new DirectoryInfo(basepath);
                    FileInfo[] files = root.GetFiles();
                    foreach (var item in files)
                    {
                        try
                        {
                            
                           // item.Delete();
                                

                        }
                        catch (Exception ex)
                        {
                            throw new Exception( ex.Message);
                        }
                    }
                });
 

            }
            catch (Exception ex)
            {
                sb.Append($"error:{ex.Message}");
            }
 
 }
參考來源
Can you explain why DirectoryInfo.GetFiles produces this IOException?
How to pass unc credential in .net corev