Search code examples
powershellparametersscopecredentialsgroup-policy

PowerShell run Command as different User when Credential Parameter is missing


I need to run a common PowerShell command to trigger a Group Policy Update "gpupdate" on a remote computer out of a workflow. The workflow runs in a system user context, which do not have the local admin permissions on the clients to force a remote "gpupdate". For that reason, I import a PowerShell credential secure string with "Import-CliXml" to run that statement in scope of a user which is local admin on the clients.

But, the command I want to use, don't support the native credential parameter. And I need to use a parameter for the remote client. Invoke-GPUpdate -Computer $client -RandomDelayInMinutes 0

I tried many approches from the internet, but it won't work for me:

Start-Process powershell.exe -Credential $credentials -ArgumentList $ProcessCommand -WorkingDirectory $env:windir -NoNewWindow -PassThru

Start-Process powershell.exe -wait -Credential $credentials -ArgumentList "-command &{Start-Process Powershell.exe -argumentlist '$($cmnd)' -verb runas -wait}"

If I test to send the remote gpupdate out of a PowerShell console started with a user which is local admin on the remote client, it works.

Did anyone has a solution for this problem? Many thanks!


Solution

  • When I connect to remote computers using PowerShell to execute commands on those computers I normally run the following. I've left an example of my code for you to use to execute Invoke-GPUpdate

    #Local Host Computer 
    #$RequestingServer = $env:COMPUTERNAME
    
    #Server List From Text File
    #$ServerList = Get-Content 'C:\temp\servicetest\servers.txt'
    
    #Server List In Script 
    $ServerList = 'Computer1','Computer2','Computer3','Computer4'
    
    #Domain Admin Account 
    [STRING]$DomainAccountName = (whoami)
    [STRING]$DomainAccountName = $DomainAccountName.Split("\")[1]
    [STRING]$DomainAccountPassword = "Password01" #Obviously Change Password    
    $DomainAccountSecurePassword = $DomainAccountPassword | ConvertTo-SecureString -AsPlainText -Force
    $DomainCredentials = New-Object System.Management.Automation.PSCredential -ArgumentList $DomainAccountName, $DomainAccountSecurePassword
                    
    #Local Server Admin Account
    [STRING] $LocalUser = "Administrator" #Obviously Change Account
    [STRING] $LocalPassword = "Password01" #Obviously Change Password
    $LocalSecurePassword = $LocalPassword | ConvertTo-SecureString -AsPlainText -Force
    $LocalCredentials = New-Object System.Management.Automation.PSCredential -ArgumentList $LocalUser, $LocalSecurePassword
    
    #If running on multiple computers / servers etc. - - See Lines 5 and 8
    ForEach($ComputerName in $ServerList) {
    
        #Update Windows Something Locally - See Line 2
        #$DomainSession = New-PSSession -Computername $RequestingServer -Credential $DomainCredentials
        
        #Update Windows Something Remotely - See Lines 5 and 8
        $DomainSession = New-PSSession -Computername $ComputerName -Credential $DomainCredentials
            Invoke-Command -Session $DomainSession -ScriptBlock {   
            
            #Some commands need the computername currently using localhost...
            $GPUpdateServer = $Using:ComputerName
            #$GPUpdateServer = $Using:RequestingServer
            
            # enter code of what you plan to do... 
            Invoke-GPUpdate -Computer $GPUpdateServer -RandomDelayInMinutes 0
            }
    } End of ForEach Statement
    
    #If running on multiple computers / servers etc. - - See Lines 5 and 8
    ForEach($ComputerName in $ServerList) {
        
        #Update Windows Something Locally - See Line 2
        #$LocalSession = New-PSSession -Computername $RequestingServer -Credential $LocalCredentials
        
        #Update Windows Something Remotely - See Lines 5 and 8
        $LocalSession = New-PSSession -Computername $ComputerName -Credential $LocalCredentials
            Invoke-Command -Session $LocalSession -ScriptBlock {
            
            #Some commands need the computername currently using localhost...
            $GPUpdateServer = $Using:ComputerName
            #$GPUpdateServer = $Using:RequestingServer
            
            # enter code of what you plan to do... 
            Invoke-GPUpdate -Computer $GPUpdateServer -RandomDelayInMinutes 0
            }
            
    } End of ForEach Statement