none
How can you run a command with elevated rights on a remote server with invoke-command ? RRS feed

  • Question

  • I am trying to run a script on a remote server with invoke-command.  The script is starting and is running fine, but the problem is that it should be running with elevated rights on the remote server.  On the server where I start the invoke-command, my account has the necessary rights.

    The server were I launch the invoke-command is a W2K8 R2.  The remote box is a W2K3 with powershell v2.0 installed.

    When I launch the script on the remote-box from the command line, I don't get the access denied's.

    Is there a way to do this ?

     

    Thanks in advance

    Friday, April 16, 2010 10:06 AM

Answers

  • Well I found a round about way to get the updates to install, but with this method, the only way you could get any status is to output the script to a text file

    I set the task scheduler to run a powershell script as a Job.  It ran it under the local settings but I was able to start the Job Remotely

    It's probably not the best way but it enables you to download and install the updates remotely without having to touch the box.

    • Marked as answer by Mervyn Zhang Wednesday, July 21, 2010 2:45 AM
    Tuesday, June 15, 2010 5:42 PM
  • I was working on this for a long time too. Microsoft have a requirement that to use the update COM object you require an interactive logon (but it throws Access is denied at you).

    Only way around it I found was either to use the task scheduler approach or PSEXEC as system then monitor status by creating text files. I don't know if WinRM will solve it for Powershell though (one may have to deploy WinRM first though). I orginally worked with the COM objects for windows scripting host but is now porting it to powershell.

    • Marked as answer by CarlaVM Friday, April 12, 2013 12:46 PM
    Wednesday, July 28, 2010 9:00 AM

All replies

  • Are these part of the same domain?  Have you tried using Invoke-Command with the -Credential parameter?
    Friday, April 16, 2010 12:12 PM
    Moderator
  • Running remote commands requires access to the PowerShell session configuration on the remote machines. ONLY members of local administrators group on remote machine or domain administrators have that access. So, if you are not a member of local admins or domain admins, you will have to pass the admin equivalent credentials using -Credential

    HTH


    Ravikanth
    http://www.ravichaganti.com/blog
    Twitter: @ravikanth
    PowerShell 2.0 remoting - eBook
    Saturday, April 17, 2010 11:56 AM
  • Both machines are part of the same domain. 

    I am using a domain account which has local administrator rights on both servers.

    Saturday, April 17, 2010 7:22 PM
  • Can we see part or all of the script?  If not, what exactly is it trying to accomplish/do?
    Saturday, April 17, 2010 8:41 PM
    Moderator
  • Hi,

    Windows 2003 doesn’t have UAC. Please let us know the detailed problem. Is there any symptom of this issue? Any error message?

    If not, please let us know what would you like to do and your script if possible so that we can try to reproduce your problem.

    Thanks.


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, April 19, 2010 6:50 AM
  • The script that I want to run is to install the windows updates.  I get an access denied on the download of the updates.

    When I execute the script on an W2K8 box, (not remotely) and I run it with non-elevated rights, I get the same error.

    The script is running fine when it is launched on W2K3 box locally with a domain account that has local admin rights, or on a W2K8 R2 server with a domain account that has local admin rights, but with elevated rights.

    Thanks in advance for your help.

     

    #=== start script ====

    param($installOption="TESTINSTALL",$rebootOption="NOREBOOT")
    
    
    
    Function Show-Help
    {
    
      Write-Host ""
      Write-Host "SCRIPT: $scriptName <installOption> <RebootOption>"
      Write-Host ""
      Write-Host "DESCRIPTION: Installatie van WSUS updates op de lokale server"
      Write-Host ""
      Write-Host "PARAMETERS"
      Write-Host " -installOption <[INSTALL|TESTINSTALL]>"
      Write-Host " -rebootOption <[REBOOT|NOREBOOT|REBOOT_IF_UPDATED]>"
      Write-Host ""
      Write-Host "EXAMPLE:"
      Write-Host "$ScriptName -installOption INSTALL -rebootOption REBOOT_IF_UPDATED"
      Write-Host "$ScriptNAme INSTALL NOREBOOT"
      Write-Host ""
      Write-Host "Indien beide parameter weggelaten worden zijn de defaultwaarden :"
      Write-Host "                 installOption=TESTINSTALL "
      Write-Host "                 RebootOption=NOREBOOT"
    
      Write-Host ""
     Exit
    }
    
    
    #Include alle globale variablen
    $CEIF_WIN_PATH = (get-content env:CEIF_WIN_PATH)
    $includeFile=$CEIF_WIN_PATH + "\Scripts\include_win.ps1"
    . $includeFile
    
    
    #initialiseer error count
    $errcnt=0 
    $scriptName=$MyInvocation.MyCommand.Name
    
    
    #argumenten controleren
    $arrInstallOption= "TESTINSTALL", "INSTALL" # Mandatory variable with predefined values
    If (!($arrInstallOption –contains $installOption)){ Show-Help }
    $arrRebootOption = "REBOOT", "NOREBOOT","REBOOT_IF_UPDATED" # Mandatory variable with predefined values
    If (!($arrRebootOption –contains $rebootOption)){ Show-Help }
    
    
    #Logfile opbouwen
    $logfile = get-logfileName($MyInvocation.MyCommand.Name)
    
    Log-scriptStart $MyInvocation.MyCommand.Name $logfile
    
    function Get-WIAStatusValue($value)
    {
      switch -exact ($value)
      {
       0  {"NotStarted"}
       1  {"InProgress"}
       2  {"Succeeded"}
       3  {"SucceededWithErrors"}
       4  {"Failed"}
       5  {"Aborted"}
      } 
    }
    
    function boot-server()
    {
      if ($installOption -eq "TESTINSTALL")
      {
        logger "TESTINSTALL : - Reboot local Server" $logfile
      }
      else
      {
        logger " - Reboot local Server" $logfile
    	  $thisServer = gwmi win32_operatingsystem 
    	  $thisServer.psbase.Scope.Options.EnablePrivileges = $true
    	  $thisServer.Reboot()
      }
    	 
    }
    
    $logmsg="Install option = " + $installOption + ", RebootOption = $rebootOption"
    logger "$logmsg" $logfile
    
    logger "" $logfile
    logger " - Creating WU COM object" $logfile
    $UpdateSession = New-Object -ComObject Microsoft.Update.Session 
    $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
    
    logger " - Searching for Updates" $logfile
    $SearchResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0")
    
    logger " - Found [$($SearchResult.Updates.count)] Updates to Download and install" $logfile
    $Updates=$($SearchResult.Updates.count)
    
    
    logger "" $logfile
    foreach($Update in $SearchResult.Updates)
    {
      if ($Update.EulaAccepted -eq 0) 
      {
        $Update.AcceptEula()
      } 
    
    
      # Add Update to Collection
      $UpdatesCollection = New-Object -ComObject Microsoft.Update.UpdateColl
      $UpdatesCollection.Add($Update) | out-null
    
      if ($installOption -eq "TESTINSTALL")
      {
      
      }
      else
      {
        # Download
        logger " + Downloading Update $($Update.Title)" $logfile
        $UpdatesDownloader = $UpdateSession.CreateUpdateDownloader()
        $UpdatesDownloader.Updates = $UpdatesCollection
        $DownloadResult = $UpdatesDownloader.Download()
        $Message = "  - Download {0}" -f (Get-WIAStatusValue $DownloadResult.ResultCode)
        if ($DownloadResult.ResultCode -eq 4 )  
    	    { $errcnt = 1 }
    
        logger $message   $logfile
    
        # Install
        logger "  - Installing Update" $logfile
        $UpdatesInstaller = $UpdateSession.CreateUpdateInstaller()
        $UpdatesInstaller.Updates = $UpdatesCollection
        $InstallResult = $UpdatesInstaller.Install()
        $Message = "  - Install {0}" -f (Get-WIAStatusValue $InstallResult.ResultCode)
        if ($InstallResult.ResultCode -eq 4 )
    	    { $errcnt = 1 }
        logger $message $logfile
        logger "" $logfile
      }
    
    }
    
    
    #Indien er een fout gebeurde tijdens download/installatie -> stuur mail naar windowsteam
    if ( $errcnt -gt 0 )
    {
      logger " - Fout tijdens de uitvoering van script -> send mail" $logfile
    	$mailSubject=$MyInvocation.MyCommand.Name
    	$msg = new-object Net.Mail.MailMessage
    	$att = new-object Net.Mail.Attachment($logfile)
    	$smtp = new-object Net.Mail.SmtpClient($smtpServer) 
    	$msg.From = $mailFrom
    	$msg.To.Add($mailTo)
    	$msg.Subject = $mailSubject
    	$msg.Body = “Meer details in attachement”
    	$msg.Attachments.Add($att) 
    	$smtp.Send($msg)
    }
    
    
    #Moet de server herstart worden ?
    if ($rebootOption -eq "REBOOT_IF_UPDATED" )
    {
      if ($Updates -gt 0)
      {
    	  #Reboot the server when updates are installed
    	  boot-server
      }
    }
    elseif ($rebootOption -eq "REBOOT")
    {
      #reboot the server always
      boot-server
    }
    else
    {
      #Do not reboot the server 
      logger "Do not reboot the server" $logfile
    }
    
    
    Log-scriptEnd $MyInvocation.MyCommand.Name $logfile
    
    exit 0
    Monday, April 19, 2010 9:33 AM
  • You've got a good one here.  Elevated privileges are not normally needed.  You can test this by doing invoke-command with {md HKLM:\Software\toenuff}.  Running that with invoke-command works without elevating privs even though elevated privs are required when running it locally.

    I tested your code with -authentication credssp with the hopes that there was some double-hop-type problem, but that did not do the trick.

    If it helps I've trimmed down your code to the essentials to duplicate the problem:

    $script = {
      $UpdateSession = New-Object -ComObject Microsoft.Update.Session 
      $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
      $SearchResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0")
      $Updates=$($SearchResult.Updates.count)
      foreach($Update in $SearchResult.Updates)
      {
       if ($Update.EulaAccepted -eq 0) 
       {
        $Update.AcceptEula()
       } 
       $UpdatesCollection = New-Object -ComObject Microsoft.Update.UpdateColl
       $UpdatesCollection.Add($Update) | out-null
      }
      $UpdatesDownloader = $UpdateSession.CreateUpdateDownloader()
      $UpdatesDownloader.Updates = $UpdatesCollection
      $DownloadResult = $UpdatesDownloader.Download()
    }
    Invoke-Command -ComputerName remotecomputer -ScriptBlock $script

    Monday, April 19, 2010 3:20 PM
  • This has been really bugging me.  I was playing with it again.... I noticed that the error is not the same remotely as it is when doing it locally without elevated privs.  When you do it locally it errors on the download() method.  When you do it remotely it errors on createupdatedownloader().  I'm not sure if that's a clue to anyone to help us figure out what exactly is the problem.

     

    I also found that you get the same error when running invoke-command locally with the -computername parameter.... However, if you leave the computername parameter off locally it works without error.

    Also... the exact error is:

    Exception calling "CreateUpdateDownloader" with "0" argument(s): "Access is denied. (Exception from HR

    ESULT: 0x80070005 (E_ACCESSDENIED))"

        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

        + FullyQualifiedErrorId : ComMethodTargetInvocation

     

     

    Wednesday, April 21, 2010 3:56 PM
  • Poked around a little more today.  If you run the following locally, and inspect the webproxy property you see that it has a valid webproxy com object.

    $UpdateSession = New-Object -ComObject Microsoft.Update.Session 

    If you do the above after doing enter-psession you see that webproxy is blank.  I see the property has a {set} so I imagine if we can find a way to manually create this we can set it.  Once that's done we can probably create a valid createupdatedownloader.  Since the webproxy is where the credentials are stored I'm assuming that's where the access denied message is coming from.

    I have to go work on other things so I thought I would post what I found in case anyone else wants to continue stabbing at it.

    Thursday, April 22, 2010 4:48 PM
  • Okay.... looks like my plan failed....

    $webproxy = New-Object -ComObject Microsoft.Update.Webproxy

    $UpdateSession = New-Object -ComObject Microsoft.Update.Session

    $updateSession.webproxy = $webproxy

    Exception setting "WebProxy": "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
    At line:1 char:16
    + $UpdateSession. <<<< WebProxy = $webproxy
      + CategoryInfo     : InvalidOperation: (:) [], RuntimeException
      + FullyQualifiedErrorId : PropertyAssignmentException

    Thursday, April 22, 2010 8:20 PM
  • Hi!

    I ran into the same problem when poking around with James O`Neill`s PowerShell functions for Windows Update:
    http://blogs.technet.com/b/jamesone/archive/2009/01/27/managing-windows-update-with-powershell.aspx

    Did you manage to solve the issue or are you still troubleshooting?


    Jan Egil Ring

    Blog: http://blog.powershell.no
    Twitter: http://twitter.com/janegilring
    Tuesday, June 15, 2010 11:53 AM
  • Jan,

    I have come across the problem still. I tried using the Add-WindowsUpdate function and still getting the error.

    I'm trying to see if there is an issue with Windows Updates itself then try and run the updates again.

     

     

    I've also tried invoking the commands and still get the same error, also use the -cred parameter, doesn't seem to change it.  I can do it on my local machine with no problems, and I'm sure if I ran it on the remote machine locally it would work fine.

    in the Link that was given, i tried using  the Add-windowsupdate function

    Function Add-WindowsUpdate

    { param ($Criteria="IsInstalled=0 and Type='Software'" , [switch]$AutoRestart, [Switch]$ShutdownAfterUpdate)
     
    $resultcode= @{0="Not Started"; 1="In Progress"; 2="Succeeded"; 3="Succeeded With Errors"; 4="Failed" ; 5="Aborted" }

    $updateSession = new-object -com "Microsoft.Update.Session"

    write-progress -Activity "Updating" -Status "Checking available updates"
     
    $updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates

    if ($Updates.Count -eq 0) { "There are no applicable updates."}
     
    else {
     
    $downloader = $updateSession.CreateUpdateDownloader()

    $downloader.Updates = $Updates

    write-progress -Activity 'Updating' -Status "Downloading $($downloader.Updates.count) updates"
     
    $Result= $downloader.Download()

    if (($Result.Hresult -eq 0) –and (($result.resultCode –eq 2) -or ($result.resultCode –eq 3)) ) {

    $updatesToInstall = New-object -com "Microsoft.Update.UpdateColl"

    $Updates | where {$_.isdownloaded} | foreach-Object {$updatesToInstall.Add($_) | out-null }
     
    $installer = $updateSession.CreateUpdateInstaller()
     
    $installer.Updates = $updatesToInstall

    write-progress -Activity 'Updating' -Status "Installing $($Installer.Updates.count) updates"

    $installationResult = $installer.Install()

    $Global:counter=-1
    $installer.updates | Format-Table -autosize -property Title,EulaAccepted,@{label='Result';expression={$ResultCode[$installationResult.GetUpdateResult($Global:Counter++).resultCode ] }}

    if ($autoRestart -and $installationResult.rebootRequired) { Write-Host "A Reboot Is required for updates to take effect" }

    if ($ShutdownAfterUpdate) { Write-Host "A Reboot is required for Updates to take effect" } } }

    }

    I went down the function and the problem seems to start at

    $downloader = $updateSession.CreateUpdateDownloader()

    Then just stops from there

     

    Tuesday, June 15, 2010 4:07 PM
  • Well I found a round about way to get the updates to install, but with this method, the only way you could get any status is to output the script to a text file

    I set the task scheduler to run a powershell script as a Job.  It ran it under the local settings but I was able to start the Job Remotely

    It's probably not the best way but it enables you to download and install the updates remotely without having to touch the box.

    • Marked as answer by Mervyn Zhang Wednesday, July 21, 2010 2:45 AM
    Tuesday, June 15, 2010 5:42 PM
  • I was working on this for a long time too. Microsoft have a requirement that to use the update COM object you require an interactive logon (but it throws Access is denied at you).

    Only way around it I found was either to use the task scheduler approach or PSEXEC as system then monitor status by creating text files. I don't know if WinRM will solve it for Powershell though (one may have to deploy WinRM first though). I orginally worked with the COM objects for windows scripting host but is now porting it to powershell.

    • Marked as answer by CarlaVM Friday, April 12, 2013 12:46 PM
    Wednesday, July 28, 2010 9:00 AM
  • Hello,
     
    Are you guys saying this is a general problem with all remote scenarios
    with all types of object, or are you saying it's a problem specific to
    Windows Update (WUA API)?
     
    If this whole thread is just about WUA, I think you'll find this
    limitation exists regardless of PowerShell and Elevated Rights.
     
    As far as I know, client/server remoting of the WUA download and install
    objects will always fail. Microsoft have deliberately restricted remote
    access to these interfaces.
     
    There's some information here
     
     
    Jonnw wrote:
    > I was working on this for a long time too. Microsoft have a requirement that to
    > use the update COM object you require an interactive logon (but it throws Access
    > is denied at you).
    >
    > Only way around it I found was either to use the task scheduler approach or
    > PSEXEC as system then monitor status by creating text files. I don't know if
    > WinRM will solve it for Powershell though (one may have to deploy WinRM first
    > though). I orginally worked with the COM objects for windows scripting host but
    > is now porting it to powershell.
    >
     
     
    Friday, July 30, 2010 7:47 PM
  • I ran ISE in elevated mode and started the script via it. Worked like a charm.
    Friday, January 24, 2014 9:46 AM
  • I have managed to install the updates remotely using psexec as follows:

    psexec \\<remote> -s powershell -File <InstallUpdates.ps1>

    where my InstallUpdates.ps1 just contains:
    Import-Module PSWindowsUpdate
    Get-WUInstall -WindowsUpdate -AcceptAll -Verbose

    The trick is to use the -s flag to connect as system account (-h did not work).
    I suppose that the same process will also work for other scripts that require elevation, but for some it may not make sense to run as system account (it does in my case).

    The <remote> machine is Hyper-V (Server 2012) and my machine Windows 8.1. Both systems have sysinternals tools installed (using chocolatey), and the remote uses the PSWindowsUpdate from https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc.
    [I had also done "set-item WSMan:\localhost\Client\TrustedHosts * " in my local machine, but I am not sure whether this is important.] 

    Friday, November 21, 2014 3:59 PM