I need to modify the below script to execute the Windows Update so it downloads and updates the remote server:
Invoke-RemoteExecution($computername){
$cred = get-credential
invoke-command -computername $computername -Credential $cred -scriptblock {
Function Search-Updates
{
$Criteria = "IsInstalled=0 and Type='Software'"
#Search for relevant updates.
$Searcher = New-Object -ComObject Microsoft.Update.Searcher
$SearchResult = $Searcher.Search($Criteria).Updates
return [System.MarshalByRefObject]$SearchResult
}
Function Download-Updates
{
Param ($SearchResult)
$Session = New-Object -ComObject Microsoft.Update.Session
$Downloader = $Session.CreateUpdateDownloader()
$Downloader.Updates = $SearchResult
$Downloader.Download()
}
[System.MarshalByRefObject]$SearchResult = Search-Updates
Download-Updates -SearchResult $SearchResult
}
}
Invoke-RemoteExecution -computername yourcomputername
The error I am facing is like the below:
Invoke-RemoteExecution -computername PRD-SVR01-VM
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
+ CategoryInfo : OperationStopped: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException
+ PSComputerName : PRD-SVR01-VM
The property 'Updates' cannot be found on this object. Verify that the property exists and can be set.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
+ PSComputerName : PRD-SVR01-VM
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : PRD-SVR01-VM
I have tried to use the remoting but it is still failed as above.
I've faced up with a problem to execute powershell class methods inside a scriptblock passed to invoke-command.
Let's start with some examples
FooClass.psm1
class Foo {
static [string]Func() {
return "bar"
}
}
FooToScriptblock.ps1
using module .\FooClass.psm1
Function FooToScriptBlock {
$m = [Foo]::new()
write-host "from func:" $m.Func()
$sb1 = {$m = [Foo]::new(); $m.Func()}
$sb2 = {param($foo)$foo.Func()}
$sb3 = [scriptblock]::Create('$m.Foo()')
$s = New-PSSession -ComputerName "computer" -Credential "someuser"
$r1 = Invoke-Command -Session $s -ScriptBlock $sb1
write-host $r1
$r2 = Invoke-Command -Session $s -ScriptBlock $sb2 -ArgumentList $m
write-host $r2
$r3 = Invoke-Command -Session $s -ScriptBlock $sb3
write-host $r3
}
FooToScriptBlock
After executing I'm getting output like this
PS <scripts> $> .\FooToScriptblock.ps1
from func: bar
Unable to find type [Foo].
+ CategoryInfo : InvalidOperation: (Foo:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
+ PSComputerName :
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName :
Method invocation failed because [Deserialized.Foo] does not contain a method named 'Func'.
+ CategoryInfo : InvalidOperation: (Func:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
+ PSComputerName :
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName :
So now the question. Is it possible to execute PowerShell classes inside a script block on another computer?
The easiest solution is to specify the 'Using' statement in the PSSession by adding something like the following.
$sb = {using module UNC_Path_to_Module\FooClass.psm1}
$r = Invoke-Command -Session $s -ScriptBlock $sb
It should be noted that since PSSessions do not pass credentials to remote session by default and will not allow access to network resources requiring authentication. In order to authenticate to network resources you will need to specify the authentication method as CredSSP. This carries a security risk if the remote system is compromised.
New-PSSession -Authentication CredSSP
This is my PowerShell script where I am loading the assembly and invoking a function from one of the assemblies.
$dllpath1 = "D:\Adhoc_Testing\AdhocDataServices\AdhocDataServices\bin\AdhocDataServices.dll"
$dllpath2 = "D:\Adhoc_Testing\QueryExpressDataServices\QueryExpressDataServices\bin\Microsoft.IdentityModel.Tokens.dll"
$dllpath3 = "D:\Adhoc_Testing\QueryExpressDataServices\QueryExpressDataServices\bin\System.IdentityModel.Tokens.Jwt.dll"
$lib3 = [Reflection.Assembly]::LoadFile("$dllpath3")
$lib2 = [Reflection.Assembly]::LoadFile("$dllpath2")
$lib1 = [Reflection.Assembly]::LoadFile("$dllpath1")
$obj = New-Object "AdhocDataServices.Controllers.TokenController"
$result = $obj.Fact()
Write-Host $result
Read-Host -Prompt “Press Enter to exit”
I'm getting below error.
New-Object : Cannot find type
[AdhocDataServices.Controllers.TokenController]: verify that the
assembly containing this type is loaded. At line:1 char:8 + $obj =
New-Object AdhocDataServices.Controllers.TokenController +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException +
FullyQualifiedErrorId :
TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
We migrated one Windows Server 2008 to Server 2016.
Now I'm getting an error at this script:
cls
$key = (2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43,6,6,6,6,6,6,31,33,60,23)
$pass = Read-Host -AsSecureString
$securepass = $pass | ConvertFrom-SecureString -Key $key
$bytes = [byte[]][char[]]$securepass
$csp = New-Object System.Security.Cryptography.CspParameters
$csp.KeyContainerName = "SuperSecretProcessOnMachine"
$csp.Flags = $csp.Flags -bor [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore
$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider -ArgumentList 5120,$csp
$rsa.PersistKeyInCsp = $true
$encrypted = $rsa.Encrypt($bytes,$true)
$encrypted | Export-Clixml 'C:\Temp\encrypted_ysastaginpro_PRE.txt' -Force
Error Code:
New-Object : Exception calling ".ctor" with "2" argument(s): "Object already
exists."
At C:\Program Files\Staging\MESDI\Create_PSW_File_Poly.ps1:13 char:10
+ ... $rsa = New-Object System.Security.Cryptography.RSACryptoServiceP ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Exception calling "Encrypt" with "2" argument(s): "Bad Length."
At C:\Program Files\Staging\MESDI\Create_PSW_File_Poly.ps1:18 char:3
+ $encrypted = $rsa.Encrypt($bytes,$true)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CryptographicException
I found the the solution.
Run the PS Script as adminstrator.
KB2956128 is causing headache for users in my network. I do not run WSUS in this environment so I was going to employ PS script to take care of uninstallation.
By all means the script below should work
$comp = 'PC03'
$scrblock =
{
$TitlePattern = 'KB2956128'
$Session = New-Object -ComObject Microsoft.Update.Session
$Collection = New-Object -ComObject Microsoft.Update.UpdateColl
$Installer = $Session.CreateUpdateInstaller()
$Searcher = $Session.CreateUpdateSearcher()
$Searcher.QueryHistory(0, $Searcher.GetTotalHistoryCount()) |
Where-Object { $_.Title -match $TitlePattern } |
ForEach-Object {
Write-Verbose "Found update history entry $($_.Title)"
$SearchResult = $Searcher.Search("UpdateID='$($_.UpdateIdentity.UpdateID)' and RevisionNumber=$($_.UpdateIdentity.RevisionNumber)")
Write-Verbose "Found $($SearchResult.Updates.Count) update entries"
if ($SearchResult.Updates.Count -gt 0) {
$Installer.Updates = $SearchResult.Updates
$Installer.Uninstall()
$Installer | Select-Object -Property ResultCode, RebootRequired, Exception
# result codes: http://technet.microsoft.com/en-us/library/cc720442(WS.10).aspx
}
}
}
Invoke-Command -ComputerName $comp -ScriptBlock $scrblock -Credential 'myDomain\administrator'
Instead I get this error
Exception calling "CreateUpdateInstaller" with "0" argument(s): "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
+ PSComputerName : PC03
Exception calling "QueryHistory" with "2" argument(s): "Exception from HRESULT: 0x80240007"
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
+ PSComputerName : PC03
I don't quite understand why the access is denied. Any ideas?
Short answer is that the ComObject does not allow the CreateUpdateInstaller to be called remotely. You can only do this locally, not over sessions or any other remoting. You can however use psexec to remotely execute your script as system.