Олицетворение Windows решает эту проблему, используя данные для входа в систему для получения токена пользователя. Затем этот токен можно использовать для получения идентификатора WindowsIdentity, который затем используется для создания контекста олицетворения. В рамках этого контекста вы можете получить доступ к файловой системе как под именем пользователя.
Конечно, вам нужно будет сохранить имя пользователя и пароль, чтобы этот подход работал.
Сначала определите API-интерфейсы Windows, необходимые для получения токена пользователя из Windows:
internal class WindowsAPI
{
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_LOGON_INTERACTIVE = 2;
[DllImport( "advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
public static extern bool LogonUser( String lpszUsername,
String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken
);
[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
public extern static bool CloseHandle( IntPtr handle );
}
Затем используйте эти API для получения идентификатора Windows:
private WindowsIdentity GetIdentity( string userName, string password )
{
_userToken = IntPtr.Zero;
if ( !WindowsAPI.LogonUser(
userName,
AbbGrainDomain,
password,
WindowsAPI.LOGON32_LOGON_INTERACTIVE, WindowsAPI.LOGON32_PROVIDER_DEFAULT,
ref _userToken
) )
{
int errorCode = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception( errorCode );
}
return new WindowsIdentity( _userToken );
}
И, наконец, используйте эту идентичность для создания контекста олицетворения:
public List<string> GetDirectories( string searchPath )
{
using ( WindowsImpersonationContext wic = GetIdentity().Impersonate() )
{
var directories = new List<string>();
var di = new DirectoryInfo( searchPath );
directories.AddRange( di.GetDirectories().Select( d => d.FullName ) );
return directories;
}
}
Наконец, важно очистить дескриптор окна, используя шаблон IDisposable, используя сохраненный _userToken:
if ( _userToken != IntPtr.Zero )
WindowsAPI.CloseHandle( _userToken );