PowerShell start-sleep cmdlet - powershell

Hey I am very new to PowerShell and found one of Ed Wilson's helpful scripts on his blog: http://blogs.technet.com/b/heyscriptingguy/archive/2012/11/12/force-a-domain-wide-update-of-group-policy-with-powershell.aspx.
I needed to customize it a little for my needs and just need some help getting the right code down.
I will just use his code because all I did was replace it with my credentials and AD info:
$cn = Get-ADComputer -filt *
$cred = Get-Credential iammred\administrator
$session = New-PSSession -cn $cn.name -cred $cred
icm -Session $session -ScriptBlock {gpupdate /force}
What I added was the next two lines to attempt to pause the script to allow the gpupdate to process then restart the computer(s):
Start-Sleep -s 120
Restart-Computer -ComputerName $cn.name
When I run the script all together it seems to just hang after I enter my credentials. My guess would be it doesn't like the way I present the Start-Sleep cmdlet because I can run the Restart-Computer cmdlet with success without Start-Sleep. The problem is it doesn't wait for gpupdate to finish so the policy doesn't get pushed. I do not get any errors when I run the script, it just hangs. I have left it running for about 10 minutes with no success.
I appreciate any help or suggestions to make this script work properly. Thanks in advance for any input.

There's nothing wrong with your sleep invocation but it isn't the best way to go. You can wait on the job to finish with a timeout (in case the command hangs) e.g.:
$job = icm -Session $session -ScriptBlock {gpupdate /force} -AsJob
Wait-Job $job -Timeout 120
Remove-PSSession $session
Restart-Computer $cn.name

#Keith Hill is right, sleep looks good. Another thing you can do is push the sleep/restart commands onto your target machines:
icm -Session $session -ScriptBlock {
gpupdate /force; Start-Sleep -s 120; Restart-Computer -Force}

Related

Invoke-Command executes on remote machine without having an effect

I'm trying to run a command on a VM using Invoke-Command. The command should stop a program that processes jobs after it finishes its current job. It works if I run it in the terminal using RDC.
& 'C:\Program Files\Autodesk\Vault Client 2021\Explorer\JobProcessor.exe' /stop
But if I run it from a different machine using Invoke-Command nothing seems to happen.
$session = New-PSSession -ComputerName 'hostname' -Credential (Get-Credential)
Invoke-Command -Session $session -ScriptBlock {
& 'C:\Program Files\Autodesk\Vault Client 2021\Explorer\JobProcessor.exe' /stop
}
However Process Monitor shows the command come in for both cases, but the program is still running.
I have also tried using Start-Process with the same result, i.e. it works in the terminal on the VM but not using Invoke-Command.
Start-Process -FilePath 'C:\Program Files\Autodesk\Vault Client 2021\Explorer\JobProcessor.exe' -ArgumentList '/stop'
I've been stuck for many days and I've exhausted my googlable knowledge for this problem.
Are you sure that file exists on the remote computer?
For simplicity, I rewrote your command to a known executable that is always there in Windows and returns unique info for any given computer.
C:\> & 'C:\Windows\system32\HOSTNAME.EXE'
server1
C:\> icm {& 'C:\Windows\system32\HOSTNAME.EXE'}
server1
C:\> icm {& 'C:\Windows\system32\HOSTNAME.EXE'} -ComputerName server2
server2
Here's your script with some error handling.
$session = New-PSSession -ComputerName 'hostname' -Credential (Get-Credential)
Invoke-Command -Session $session -ScriptBlock {
$exe = 'C:\Program Files\Autodesk\Vault Client 2021\Explorer\JobProcessor.exe'
$ok = Test-Path $exe
if ($ok) {& $exe /stop} else {
Write-Warning "EXE not present on $($env:COMPUTERNAME)!"
}
}
Learn how to add error handling and you'll be well on your way to solving your problems faster and getting more stuff done.

PowerShell remote session and Start-Job issue

I am trying to run following script with job but the code in the block only executes 1st command and exits. Job is displayed completed on my computer
$computers = get-adcomputer -filter * | where { ($_.DNSHostName -match 'server')}
foreach ($computer in $computers) {
$session = New-PSSession -ComputerName $computer.DNSHostName
Invoke-Command -Session $session -ScriptBlock {
Stop-Service W3SVC -Force
Remove-Item "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root" -Force -Recurse
Start-Service W3SVC
} -asjob -jobname IIS_Maintenance
Remove-PSSession -Session $session
}
If I comment out -asjob -jobname IIS_Maintenance job runs fine but it's synchronous. It takes several seconds to stop IIS but I am not sure why job is not waiting on that.
Thoughts?
Creating the session induces a lot of delay. Why did you chose to use the -Session instead of directly using -ComputerName ?
I think using the -ComputerName way will be more efficient to run with Start-Job. Either way, Since you are invoking the jobs on remote machines, your workstation would have no clue on the progress of the jobs.
If you want to track the progress of the jobs, you shouldn't be using Invoke-Command at all.
OK I figured it out... the point of confusion was:
1) I didn't know I can send block of code without Session and yes session implementation is slow
2) I also didn't know I send invoke-command to several computers are once without foreach. Thank you for that Ansgar Wiechers!

Powershell Code with No Errors not running

Invoke-Command -cn (Get-Content C:\Users\Administration\Documents\MyText.txt) -scriptblock {Start-Process -FilePath "MyProg.exe" -WorkingDirectory "C:\Program Files\ThisFolder\ThatFolder" -ArgumentList "-1", "-2", "-3"}
Obviously I'm doing something wrong, but not sure what. Anyone seeing something I'm missing?
The process is ending after your session on the remote system is closed. When i run the following test, notepad will run for 5 seconds on the remote computer, then close:
Invoke-Command -ComputerName $RemoteComputer -ScriptBlock {start-process notepad.exe;Start-Sleep -Seconds 5}
If myprog.exe closes on it's own use the -Wait switch to wait for the process to close on it's own. You could also use New-PSSession to keep a session open until you are done then use Remove-PSSession to end the session and have the remote process end.

Prevent additional windows from displaying in powershell script

The idea here is to uninstall a program silently. Unfortunately the program's msi is custom and executes a batch file during the uninstall process. What I am trying to do is prevent this window from displaying during the powershell uninstall script. I'm using wmi uninstall method because the msi that the program uses doesn't respond to quite or uninstall flags (/q, /x, /uninstall). I have attempted to run it as a background job but the window still appears. The script looks as follows:
start-job -scriptblock `
{(Get-WmiObject -class Win32_Product |? {$_Name -eq "Annoying1"}).uninstall()} `
-Name Uninstall1
$job = get-job -name Uninstall1
wait-job $job
receive-job $job
This will run mostly hidden until the uninstall job gets to the point where the batch file is executed, at which point a cmd window will appear and run. Any ideas of how to run this script without displaying extra windows?
The script is ran with -windowstyle hidden as well.
Be indulgent, I'am not proud of this, but I'am quite sure that if you try to localy run your script using remoting the window will not be seen by the user :
I just try :
$sess = New-PSSession -ComputerName localhost
Invoke-Command -Session $sess -ScriptBlock {calc.exe}
get-process "calc"
In your case try :
$sess = New-PSSession -ComputerName localhost
$job = Invoke-Command -Session $sess -ScriptBlock {(Get-WmiObject -class Win32_Product |? {$_Name -eq "Annoying1"}).uninstall()} -asjob -Name Uninstall1
wait-job $job
receive-job $job

New-PSSession in Job blocks Job

I need to start PSSession in job. But I can't use Invoke-Command -AsJob due product architecure.
I tried something like:
$block {
"Job started"
$session = New-PSSession -computername "host-name"
"Session started"
}
$job = Start-Job -ScriptBlock $block
Wait-Job -Job $job -Timeout 10 | Out-Null
Receive-Job -Job $job
(I don't have PS on system I post this question, so I could make mistake in syntax, skip it, please)
But, instead of creating remote session job became blocked forever on New-PSSession line.
Wait-Job will exit by timeout, and Recieve-Job will return only "Job started".
I tried:
I ensure that remoting in main thread is working well, and Invoke-Command -AsJob is working too.
Invoke-Command and other PSSession-based cmdlets have same behavior — blocks job execution.
Create PSSession in main thread and then transfer session object or object.Id as -InputArguments for job
Result: PSSession created in main thread can't be used in child Job, no matter, was it transfered or found inside job`s scriptblock by Get-PSSession
Thanks in advance!