Get-ThreadToken.ps1

function Get-ThreadToken
{
    param (
        [Parameter(Position=0, Mandatory=$true)]
        [UInt32]
        $ThreadId
    )

    $TokenPrivs = $Win32Constants.TOKEN_ALL_ACCESS

    $RetStruct = New-Object PSObject
    [IntPtr]$hThreadToken = [IntPtr]::Zero

    $hThread = $OpenThread.Invoke($Win32Constants.THREAD_ALL_ACCESS, $false, $ThreadId)
    if ($hThread -eq [IntPtr]::Zero)
    {
        $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
        if ($ErrorCode -ne $Win32Constants.ERROR_INVALID_PARAMETER) #The thread probably no longer exists
        {
            Write-Warning "Failed to open thread handle for ThreadId: $ThreadId. Error code: $ErrorCode"
        }
    }
    else
    {
        $Success = $OpenThreadToken.Invoke($hThread, $TokenPrivs, $false, [Ref]$hThreadToken)
        if (-not $Success)
        {
            $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
            if (($ErrorCode -ne $Win32Constants.ERROR_NO_TOKEN) -and  #This error is returned when the thread isn't impersonated
             ($ErrorCode -ne $Win32Constants.ERROR_INVALID_PARAMETER)) #Probably means the thread was closed
            {
                Write-Warning "Failed to call OpenThreadToken for ThreadId: $ThreadId. Error code: $ErrorCode"
            }
        }
        else
        {
            Write-Verbose "Successfully queried thread token"
        }

        #Close the handle to hThread (the thread handle)
        if (-not $CloseHandle.Invoke($hThread))
        {
            $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
            Write-Warning "Failed to close thread handle, this is unexpected. ErrorCode: $ErrorCode"
        }
        $hThread = [IntPtr]::Zero
    }

    $RetStruct | Add-Member -MemberType NoteProperty -Name hThreadToken -Value $hThreadToken
    return $RetStruct
}