/// <summary> /// Impersonates the specified user. /// </summary> /// <param name="domainUser">The domain user.</param> /// <param name="processFilter">Predicate to find the process suitable for impersonation. If it's <see langword="null"/>, the first <paramref name="domainUser"/>'s process will be used.</param> /// <returns> /// Impersonated context. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="domainUser"/> is <see langword="null"/> or empty.</exception> /// <exception cref="ArgumentException"><paramref name="domainUser"/> is not in the <c>DOMAIN\username</c> format.</exception> /// <exception cref="InvalidOperationException"> /// No processes are running for the <paramref name="domainUser"/>. /// <para>-or-</para> /// Process handle cannot be duplicated. /// </exception> /// <remarks> /// This method looks for the existing <paramref name="domainUser"/> process running in the system, obtains and duplicates /// its token, and uses it to impersonate the caller. So it won't work, if the user is logged out or has no processes running. /// </remarks> public static WindowsImpersonationContext Impersonate(string domainUser, Predicate <Process> processFilter) { if (string.IsNullOrEmpty(domainUser)) { throw new ArgumentNullException(nameof(domainUser)); } // Process returned by the ProcessHelper.FindUserProcesses may already be closed, so we want to retry. return(RetryHelper.Retry( () => { using (Process process = ProcessHelper.FindUserProcesses(domainUser).FirstOrDefault(p => processFilter == null || processFilter(p))) { if (process == null) { throw new InvalidOperationException("No suitable user processes found."); } return WindowsIdentity.Impersonate(Impersonator.DuplicateProcessHandle(process)); } }, Impersonator.DefaultRetryCount, Impersonator.DefaultRetryDelay, new[] { typeof(InvalidOperationException) })); }
/// <summary> /// Impersonates the currently logged on user in the current thread context. /// </summary> /// <returns>Impersonation context.</returns> public static WindowsImpersonationContext ImpersonateCurrentUser() { try { return(Impersonator.Impersonate(UserHelper.LoggedOnUser)); } catch { // Exception might occur, if we have outdated username information. // Maybe, that user has logged out. So, try to find a new username. string previousUserName = UserHelper.LoggedOnUser; string newUserName = UserHelper.GetCurrentUser(); // If username is the same, don't retry. if (string.Equals(previousUserName, newUserName, StringComparison.OrdinalIgnoreCase)) { throw; } UserHelper.LoggedOnUser = newUserName; } return(Impersonator.Impersonate(UserHelper.LoggedOnUser)); }
/// <summary> /// Impersonates the specified user within the <c>Explorer</c> process context.<br/> /// <c>Explorer</c> process is vital for the system and should always be there, if the user is logged in. /// </summary> /// <param name="domainUser">The domain user.</param> /// <returns> /// Impersonated context. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="domainUser"/> is <see langword="null"/> or empty.</exception> /// <exception cref="ArgumentException"><paramref name="domainUser"/> is not in the <c>DOMAIN\username</c> format.</exception> /// <exception cref="InvalidOperationException"> /// No processes are running for the <paramref name="domainUser"/>. /// <para>-or-</para> /// Process handle cannot be duplicated. /// </exception> /// <seealso cref="Impersonate(string,Predicate{Process})"/> public static WindowsImpersonationContext Impersonate(string domainUser) { return(Impersonator.Impersonate(domainUser, p => p.ProcessName.Equals("explorer", StringComparison.OrdinalIgnoreCase))); }