Functions/New-ImpersonateUser.ps1
function New-ImpersonateUser { [cmdletbinding()] Param( [Parameter(ParameterSetName="ClearText", Mandatory=$true)][string]$Username, [Parameter(ParameterSetName="ClearText", Mandatory=$true)][string]$Domain, [Parameter(ParameterSetName="ClearText", Mandatory=$true)][string]$Password, [Parameter(ParameterSetName="Credential", Mandatory=$true, Position=0)][PSCredential]$Credential, [Parameter()][Switch]$Quiet ) #Import the LogonUser Function from advapi32.dll and the CloseHandle Function from kernel32.dll if (-not ([System.Management.Automation.PSTypeName]'Import.Win32').Type) { Add-Type -Namespace Import -Name Win32 -MemberDefinition @' [DllImport("advapi32.dll", SetLastError = true)] public static extern bool LogonUser(string user, string domain, string password, int logonType, int logonProvider, out IntPtr token); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CloseHandle(IntPtr handle); '@ -ErrorAction SilentlyContinue } #Set Global variable to hold the Impersonation after it is created so it may be ended after script run $Global:ImpersonatedUser = @{} #Initialize handle variable so that it exists to be referenced in the LogonUser method $tokenHandle = 0 #Pass the PSCredentials to the variables to be sent to the LogonUser method if ($Credential) { Get-Variable Username, Domain, Password | ForEach-Object { Set-Variable $_.Name -Value $Credential.GetNetworkCredential().$($_.Name)} } #Call LogonUser and store its success. [ref]$tokenHandle is used to store the token "out IntPtr token" from LogonUser. $returnValue = [Import.Win32]::LogonUser($Username, $Domain, $Password, 2, 0, [ref]$tokenHandle) #If it fails, throw the verbose with the error code if (!$returnValue) { $errCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error(); Write-Host "Impersonate-User failed a call to LogonUser with error code: $errCode" throw [System.ComponentModel.Win32Exception]$errCode } #Successful token stored in $tokenHandle else { #Call the Impersonate method with the returned token. An ImpersonationContext is returned and stored in the #Global variable so that it may be used after script run. $Global:ImpersonatedUser.ImpersonationContext = [System.Security.Principal.WindowsIdentity]::Impersonate($tokenHandle) #Close the handle to the token. Voided to mask the Boolean return value. [void][Import.Win32]::CloseHandle($tokenHandle) #Write the current user to ensure Impersonation worked and to remind user to revert back when finished. if (!$Quiet) { Write-Host "You are now impersonating user $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)" Write-Host "It is very important that you call Remove-ImpersonateUser when finished to revert back to your user." } } Function Global:Remove-ImpersonateUser { <# .SYNOPSIS Used to revert back to the orginal user after New-ImpersonateUser is called. You can only call this function once; it is deleted after it runs. .INPUTS None. You cannot pipe objects to Remove-ImpersonateUser .OUTPUTS None. Remove-ImpersonateUser does not generate any output. #> #Calling the Undo method reverts back to the original user. $ImpersonatedUser.ImpersonationContext.Undo() #Clean up the Global variable and the function itself. Remove-Variable ImpersonatedUser -Scope Global Remove-Item Function:\Remove-ImpersonateUser } } Export-ModuleMember -Function New-ImpersonateUser |