PowerCLI PowerShell Jobs does not finish - powershell

I have the problem that a simple PowerShell Job does not complete. It will always be running.
I am trying the following:
$Job = Start-Job -Name "TestJob" -ScriptBlock {param($vcenter,$session) Connect-VIServer -Server $vcenter -Session $session; Get-VM -Name "VMName"} -ArgumentList $global:DefaultVIServer.Name,$global:DefaultVIServer.SessionSecret;
Hopefully some of you have an idea what I am doing wrong.
Thanks in advance.

Found the solution. I cannot explain it but if you write the return of Get-VM in a variable the job will finish normally.
$Job = Start-Job -Name "TestJob" -ScriptBlock {param($vcenter,$session) Connect-VIServer -Server $vcenter -Session $session; $t = Get-VM -Name "VMName"} -ArgumentList $global:DefaultVIServer.Name,$global:DefaultVIServer.SessionSecret;
Best regards

Related

input objects in powershell jobs

I'm trying to implement a job in PowerShell that would look something like this:
$cred = Get-Credential
$job1 = Start-Job -InputObject $cred -ScriptBlock {
Get-ADUser -Credential $cred -Filter *
}
$res1 = Wait-Job -Job $job1 | Receive-Job
But I am receiving an error message:
"Wait-Job : The Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction. Process interactive job output by using the Receive-Job cmdlet, and then try again.
....
Deadlock detected: (System.Manageme...n.PSRemotingJob:PSRemotingJob) [Wait-J
ob],
....
"
But if I create this seemingly identical job like this:
$job2 = Start-Job -ScriptBlock {
$pass = ConvertTo-SecureString "pass" -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "usr",$pass
Get-ADUser -Credential $cred -Filter *
}
$res2 = Wait-Job -Job $job2 | Receive-Job
Everything works perfectly.
Can you please help me understand why?
Thanks!
To pass arguments to the script block, you need to use the -ArgumentList parameter, not -InputObject. Try this:
$cred = Get-Credential
$job1 = Start-Job -ScriptBlock {PARAM($cred)
Get-ADUser -Credential $cred -Filter *
} -ArgumentList $cred
Note that -ArgumentList has to be the last parameter in the Start-Job command.
Well, this would probably be evident if you had but read the Help for Start-Job. If you use the -InputObject argument you then reference it from within the scriptblock with the automatic variable $Input. Since you reference $Cred out of scope like that it's trying to get credentials again. Here's the Help text for that parameter.
-InputObject <PSObject>
Specifies input to the command. Enter a variable that contains the objects, or type a command or expression that generates the objects.
In the value of the ScriptBlock parameter, use the $input automatic variable to represent the input objects.
You could alter your script to look like this and it should work fine:
$cred = Get-Credential
$job1 = Start-Job -InputObject $cred -ScriptBlock {
Get-ADUser -Credential $Input -Filter *
}
$res1 = Wait-Job -Job $job1 | Receive-Job

Running Batch Script on remote Server via PowerShell

I need to connect to some remote servers from a client (same domain as the servers) once connected, I need to run a batch file:
I've done so with this code:
$Username = 'USER'
$Password = 'PASSWORD'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
try {
Invoke-Command -ComputerName "SERVER1" -Credential $Cred -ScriptBlock -ErrorAction Stop {
Start-Process "C:\Users\nithi.sundar\Desktop\Test.bat"
}
} catch {
Write-Host "error"
}
This script does not give any errors, but it doesn't seem to be executing the batch script.
any input on this would be greatly appreciated.
Try replacing
invoke-command -computername "SERVER1" -credential $Cred -ScriptBlock -ErrorAction stop { Start-Process "C:\Users\nithi.sundar\Desktop\Test.bat" }
with
Invoke-Command -ComputerName "Server1" -credential $cred -ErrorAction Stop -ScriptBlock {Invoke-Expression -Command:"cmd.exe /c 'C:\Users\nithi.sund
ar\Desktop\Test.bat'"}
It's not possible that the code you posted ran without errors, because you messed up the order of the argument to Invoke-Command. This:
Invoke-Command ... -ScriptBlock -ErrorAction Stop { ... }
should actually look like this:
Invoke-Command ... -ErrorAction Stop -ScriptBlock { ... }
Also, DO NOT use Invoke-Expression for this. It's practically always the wrong tool for whatever you need to accomplish. You also don't need Start-Process since PowerShell can run batch scripts directly:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
C:\Users\nithi.sundar\Desktop\Test.bat
} -Credential $Cred -ErrorAction Stop
If the command is a string rather than a bare word you need to use the call operator, though:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
& "C:\Users\nithi.sundar\Desktop\Test.bat"
} -Credential $Cred -ErrorAction Stop
You could also invoke the batch file with cmd.exe:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
cmd /c "C:\Users\nithi.sundar\Desktop\Test.bat"
} -Credential $Cred -ErrorAction Stop
If for some reason you must use Start-Process you should add the parameters -NoNewWindow and -Wait.
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
Start-Process 'C:\Users\nithi.sundar\Desktop\Test.bat' -NoNewWindow -Wait
} -Credential $Cred -ErrorAction Stop
By default Start-Process runs the invoked process asynchronously (i.e. the call returns immediately) and in a separate window. That is most likely the reason why your code didn't work as intended.

Restart a service in the background using Powershell

I'm trying to restart a service in the background, then monitor the if the service has been restarted. If the service has not started as a while, then the service is to be restarted.
I'm having issues with restarting the service in the background the start-job command does run so thats where i'm most probably going wrong. the restart-service and do command work correctly, just cant get it to run in the background.
$a = "Restart-Service -InputObject $(get-service -ComputerName $Server -Name Service)"
start-job -scriptblock {$a}
do {
($Check = (Get-Service -ComputerName $RadSvr -Name IAS).status -eq "Running") }
Until ($check -eq $true)
After playing around, I noticed the script ran in the background if i didnt use variables in the Start-Job. so if i changed the start-job to include the IP address of a server
start-job -scriptblock { Restart-Service -InputObject $(get-service -ComputerName 10.10.10.10 -Name Service) }
anyone know how to make variable work?
Use Wait-Job to wait for the job to complete.
$a = "Restart-Service -InputObject $(get-service -ComputerName $Server -Name Service)"
$job = start-job -scriptblock {$a}
Wait-Job $job
Maybe you can simplify your code a little bit by using process functions
$service = Get-Service -Name $servicename -ComputerName $targetcomputer
$service.Stop();
$maxTimeout = "00:03:00"
$service.WaitForStatus('Stopped', $maxTimeout);
# check again the status and eventually perform another action
I got the script working. I needed to add param and -argumentlist in the start-job
start-job -scriptblock {param($Server) Restart-Service -InputObject $(get-service -ComputerName $Server -Name Service)} -Argumentlist $Server

invoke-expression inside scriptblock of invoke-command not working

I've got the following script
$name = (Invoke-Command -ComputerName "STW111" -Credential $cred -ScriptBlock { Invoke-Expression "C:\PSS\User Tool\UserTool.exe"} -AsJob).Name
Wait-Job -Name $name
This not working, however, if I move the usertool to c:\pss\, it works fine.
$name = (Invoke-Command -ComputerName "STW111" -Credential $cred -ScriptBlock { Invoke-Expression "C:\PSS\UserTool.exe"} -AsJob).Name
Wait-Job -Name $name
I really need to get to grips with escaping in Powershell.
Any ideas?
TIA
try this:
Invoke-Expression "& 'C:\PSS\User Tool\UserTool.exe'"

Start-Job script block-- how to call cmdlets with arguments?

I'm new to the Start-Job cmdlet and am having trouble calling a script block with cmdlets in it that take arguments. Here's what I have so far:
Start-Job -ScriptBlock {
$ServiceObj = Get-Service -Name $ServiceName -ComputerName $Computer -ErrorAction Stop
Stop-Service -InputObj $ServiceObj -erroraction stop
}
I'm seeing errors when I run receive-job that the -ComputerName argument is null or empty, and the -InputObj argument is null or empty. In neither case is that so. The snippet above is being called from inside two foreach loops:
foreach($Computer in $ComputerNames) {
foreach($ServiceName in $ServiceNames) {
#..call snippet above
}
}
I've tried using the -ArgumentList when calling my script block but no luck there either. I'm sure I'm missing something?
You do need to use ArgumentList (unless you're on PowerShell V3) e.g.:
Start-Job -ScriptBlock {param($ComputerName)
$ServiceObj = Get-Service -Name $ServiceName -CN $ComputerName -ErrorAction Stop
Stop-Service -InputObj $ServiceObj -erroraction stop
} -ArgumentList $Computer
If you're using PowerShell V3, you can use the using variable qualifier e.g.:
Start-Job -ScriptBlock {
$ServiceObj = Get-Service -Name $ServiceName -CN $using:Computer -ErrorAction Stop
Stop-Service -InputObj $ServiceObj -erroraction stop
}