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

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

April 16th, 2010 1:06pm

Are these part of the same domain?  Have you tried using Invoke-Command with the -Credential parameter?
Free Windows Admin Tool Kit Click here and download it now
April 16th, 2010 3:12pm

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

April 17th, 2010 2:56pm

Both machines are part of the same domain. 

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

Free Windows Admin Tool Kit Click here and download it now
April 17th, 2010 10:22pm

Can we see part or all of the script?  If not, what exactly is it trying to accomplish/do?
April 17th, 2010 11:41pm

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.

Free Windows Admin Tool Kit Click here and download it now
April 19th, 2010 9:50am

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
April 19th, 2010 12:33pm

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

Free Windows Admin Tool Kit Click here and download it now
April 19th, 2010 6:20pm

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

 

 

April 21st, 2010 6:56pm

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.

Free Windows Admin Tool Kit Click here and download it now
April 22nd, 2010 7:48pm

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

April 22nd, 2010 11:20pm

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?

Free Windows Admin Tool Kit Click here and download it now
June 15th, 2010 2:53pm

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

 

June 15th, 2010 7:07pm

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.

Free Windows Admin Tool Kit Click here and download it now
June 15th, 2010 8:42pm

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
July 28th, 2010 12:00pm

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   http://msdn.microsoft.com/en-us/library/aa387288(v=VS.85).aspx   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. >    
Free Windows Admin Tool Kit Click here and download it now
July 30th, 2010 10:47pm

I ran ISE in elevated mode and started the script via it. Worked like a charm.
January 24th, 2014 4:49am

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics