1

I am building a script to remotely install the PSWindowsUpdate PowerShell module, open the correct firewall ports, and then run a command to install waiting updates. In order to install the PSWindowsUpdate module, I need to install an MSI on some of my machines to enable the "Install-Module" commandlet.

If I run the following code manually, in an admin PowerShell session on my local machine, it works fine:

$RemoteMachine = "DCSvrRDS16"
write-host "Server Name is: $RemoteMachine"

#Copy the MSI Local to the computer
Write-Host "Copying MSI locally"
Copy "\\dcsvrstorage2\software\microsoft\powershell\PackageManagement_x64.msi" \\$RemoteMachine\c$\

#Run the MSI remotely
Write-Host "Running MSI"
Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { c:\windows\system32\msiexec /i c:\PackageManagement_x64.msi /quiet /lvx* c:\PackageManagement.log } 4>&1

But if I run THIS full script IN THE EXACT SAME ALREADY OPEN PowerShell SESSION, the MSI does not install and the log file is not created:

Import-Module PSWindowsUpdate
$domaincredentials = Get-Credential


Function ProcessMachine($RemoteMachine) {

    write-host "Server Name is: $RemoteMachine"

    #Copy the MSI Local to the computer
    Write-Host "Copying MSI locally"
    Copy "\\dcsvrstorage2\software\microsoft\powershell\PackageManagement_x64.msi" \\$RemoteMachine\c$\

    #Run the MSI remotely
    Write-Host "Running MSI"
    Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { c:\windows\system32\msiexec /i c:\PackageManagement_x64.msi /quiet /lvx* c:\PackageManagement.log } 4>&1

    #Install the module
    Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { Install-Module PSWindowsUpdate -Force }

    #Turn on the firewall rules
    Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { Set-NetFirewallRule -DisplayName "COM+ Network Access (DCOM-In)" -Enabled True }
    Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { Set-NetFirewallRule -DisplayName "COM+ Remote Administration (DCOM-In)" -Enabled True }
    Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { Remove-NetFirewallRule -DisplayName "Remote WSUS Install" }
    Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { New-NetFirewallRule -DisplayName "Remote WSUS Install" -Profile Domain -Enabled True -Direction Inbound -Action Allow -Protocol TCP -LocalPort RPC }

    #Try the update
    Install-WindowsUpdate -ComputerName $RemoteMachine -AcceptAll
}

foreach ($machine in (Get-Content NeedsWSUS.txt)) {

    ProcessMachine $machine

}

It is driving me crazy. I have run ProcessMonitor on the remote machine, and I can see msiexec start and then stop without ever accessing the MSI in the root of the C: drive or trying to open the log file for write.

Has anyone seen anything similar? Client machine is Windows 7 pro, Powershell 4, and the destination machine is Windows 2012 R2 and also PowerShell 4.

Thanks in advance.

  • Is it actually copying the file? You may want to include a test-path command in the -scriptblock. – Davidw Oct 21 '18 at 2:31
  • Yes it is. And I have even done some testing to see if manually copying the file changes anything. – Glenn Sullivan Oct 21 '18 at 2:38
  • Then I did another test, where I just pasted the script into the powershell window, thinking it might be a problem with where or how I saved it, and no change... if I run the full script, either as a saved .ps1 file or pasted into the PowerShell window directly, it fails. – Glenn Sullivan Oct 21 '18 at 2:40
  • I wonder if it's not seeing the credentials? – Davidw Oct 21 '18 at 4:35
  • 2
    Have you tried using invoke-command with the start-process -wait option to ensure it has completed before returning for script execution? Along the lines of Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock {start-process c:\windows\system32\msiexec /i c:\PackageManagement_x64.msi /quiet /lvx* c:\PackageManagement.log -wait } 4>&1 – Enigman Oct 21 '18 at 5:06
2

This issue can occur when attempting to run script blocks or commands that take some time to execute (especially with installation activities). The script is returning before the command in the script block has completed it's activity. Using Start-Process with the -wait parameter has the script wait until the command being run has completed and returned back to the script. I've noticed this before when installing on remote machines whereas running locally without Start-Process appeared to work fine.

The proper command change as you have noted is:

Invoke-Command -ComputerName $RemoteMachine -Credential $domaincredentials -ScriptBlock { Start-Process msiexec "/i c:\PackageManagement_x64.msi /quiet /lvx* c:\PackageManagement.log" -wait }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.