Have you ever been working on an issue, rebooted the computer, and forgot to remote back in to finish the problem? Wouldn’t it be nice if your computer just magically reminded you?
But why stop at a little reminder, why not have your computer automatically launch a remote session to that computer! PowerShell can do all of this and when embedded in Active Directory Users and Computers, you get instant access to it. Don’t let the length of this script discourage you; setting this process up won’t take more than 10 minutes!
The Restart Monitor and Automatic Remote In Script
First, I want to thank Sitaram Pamarthi for most of this script. You can find his original script here. If you are looking to populate your PowerShell Script store, his blog would make a good resource. Go ahead and copy the script below. Save it to a network location. I will meet up with you in 100 lines!
Param ( [Parameter(ValueFromPipeline=$False,Mandatory=$False)] [int]$timeout=5 ) $MAX_PINGTIME = $timeout * 600 $max_iterations = $MAX_PINGTIME/5 $Notification_timeout = 10 # in seconds function Show-notification { param($type,$text,$title) #load Windows Forms and drawing assemblies. Thanks to George for catching this. [Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”) | Out-Null [Reflection.Assembly]::LoadWithPartialName(“System.Drawing”) | Out-Null #define an icon image pulled from PowerShell.exe $icon=[system.drawing.icon]::ExtractAssociatedIcon((join-path $pshome powershell.exe)) $notify = new-object system.windows.forms.notifyicon $notify.icon = $icon $notify.visible = $True #define the tool tip icon based on the message type switch ($messagetype) { "Error" { $messageIcon=[system.windows.forms.tooltipicon]::Error} "Info" {$messageIcon=[system.windows.forms.tooltipicon]::Info} "Warning" {$messageIcon=[system.windows.forms.tooltipicon]::Warning} Default {$messageIcon=[system.windows.forms.tooltipicon]::None} } #display the balloon tipe $notify.showballoontip($Notification_timeout,$title,$text,$type) } function ping-host { param($pc) $status = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$pc'" if( $status.statuscode -eq 0) { return 1 } else { return 0 } } Function Remote-host { while ((Test-Connection -Quiet -ComputerName $Computer) -eq $False) {Test-Connection -Quiet -ComputerName $Computer} if ((Test-Connection -Quiet -ComputerName $Computer) -eq $True) { & 'C:\Program Files (x86)\NetSupport\NetSupport Manager\PCICTLUI.EXE' /C"$Computer" /vw /e } } $Computer = Read-Host "What is the Computer Name?" if(ping-host -pc $computer) { Write-Host "$computer is online; Waiting for it to go offline" Restart-Computer -ComputerName $computer -Force $status = "online" for ($i=0; $i -le $max_iterations; $i++) { if (!(ping-host -pc $computer )) { break } Start-Sleep -Seconds 5 if($i -eq $max_iterations) { Write-Host "$computer never went down in last $timeout minutes" Write-Host "Check that reboot is initiated properly" show-notification -type "error" -text "$computer is still ONLINE; Check that reboot is initiated properly" -title "Computer is not rebooting" exit } } Write-Host "$computer is offline now; monitoring for online status" } else { Write-Host "$computer is offline; Monitoring for online status" $status = "offline" } for ($i=0; $i -le $max_iterations; $i++) { if ((ping-host -pc $computer )) { break } Start-Sleep -Seconds 5 if($i -eq $max_iterations) { Write-Host "Your computer never came back online in last $MAX_PINGTIME seconds" Write-Host "Check that nothing is preventing starup" show-notification -type "error" -text "$Computer is NOT coming online; Something is preventing its startup" -title "Computer failed to start" exit } } Write-Host "Your computer is Online Now; Task done; exiting" show-notification -type "info" -text "$Computer is online" -title "$Computer successfully restarted" Remote-host
Choose Your Remote Tool
So you made it, great! To enable automatic connections to a client, you will need a remote tool that supports command line options. In our environment, we use a product called NetSupport which works pretty well for this. You should also be able to use Remote Assistance, Remote Desktop, or Concurrent Remote Desktop.
In your saved script, search for this line: & ‘C:\Program Files (x86)\NetSupport\NetSupport Manager\PCICTLUI.EXE’ /C”$Computer” /vw /e . Replace the program path (‘C:\….\PCICTLUI.EXE’) with your remote support tool. After the last ‘ mark, add in any silent connection options that you need. Be sure to specify $Computer as the client name/connection name.
If you are using Remote Desktop or Remote Assistance, you can use the commands below:
- Remote Desktop: mstsc /V:$Computer
- Remote Assistance: msra.exe /offerra $Computer
Adding the Script to Active Directory
The easiest way to access this script is to embed it within your Active Directory Users and Computers MMC. We’ve covered adding scripts to your ADUC MMC a few times. If you have a custom ADUC MMC, create a new task in your Taskpad. If you aren’t using a custom ADUC MMC yet, here are the short steps to creating one.
- Launch a new blank MMC (start – run – mmc.exe). Select File – Add/Remove Snap-ins. Load the Active Directory Users and Computer Snapin.
- Expand ADUC until you are looking at an OU. At the top of the MMC, select Action and then New Taskpad View.
- Continue through the wizard until it ends. Save your MMC to a network location and create Start Menu/Screen shortcuts to it. Here is a detailed article covering this process.
You should now be at the New Task Wizard. Press Next and select Shell Command. Below is the information that you will need for this task. Be sure to include all quote marks.
Command: c:\windows\System32\WindowsPowerShell\v1.0\powershell.exe
Parameters: -command “”&” ‘”\\SERVER\SHARE\restart-monitor.ps1′””
Continue through the wizard by naming your task and selection an icon. When you want to reboot a machine and automatically reconnect to it, select your new task and type in your computer name. The computer will reboot and your remote control agent will launch when the machine is active again!
Is this parameter correct?
Parameters: -command “”&” ‘”\\SERVER\SHARE\restart-monitor.ps1′””
-command “”&” ‘”\\SERVER\SHARE\restart-monitor.ps1′””
It looks like it. I copied mine for you incase I am off by a ‘ mark or something.
PS C:\> -command “”&” ‘”\\172.16.20.40\AppV_Client_Remote$\restart-monitor.ps1’””
At line:1 char:11
+ command “”&” ‘”\\172.16.20.40\AppV_Client_Remote$\restart-monitor.ps1’””
+ ~
Ampersand not allowed. The & operator is reserved for future use; use “&” to pass ampersand as a string
At line:1 char:70
+ command “”&” ‘”\\172.16.20.40\AppV_Client_Remote$\restart-monitor.ps1’””
+ ~~~
The string is missing the terminator: ‘.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : AmpersandNotAllowed
Thank you dear Joseph,
I am using POS version 3.0 using AD 2012.
What could be the problem?
Regards,
Thank you dear Joseph for the script,
Please note that I am facing the following error when I run the PowerShell:
I am using Remote Desktop to connect:
PS C:\AppV_Client_Remote> .\restart-monitor.ps1
What is the Computer Name?: App-v-5
App-v-5 is online; Waiting for it to go offline
App-v-5 is offline now; monitoring for online status
Your computer is Online Now; Task done; exiting
Unable to find type [system.drawing.icon]: make sure that the assembly containing this type is loaded.
At C:\AppV_Client_Remote\restart-monitor.ps1:17 char:5
+ $icon=[system.drawing.icon]::ExtractAssociatedIcon((join-path $pshome powers …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (system.drawing.icon:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
new-object : Cannot find type [system.windows.forms.notifyicon]: make sure the assembly containing this type is load
At C:\AppV_Client_Remote\restart-monitor.ps1:18 char:15
+ $notify = new-object system.windows.forms.notifyicon
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
Property ‘icon’ cannot be found on this object; make sure it exists and is settable.
At C:\AppV_Client_Remote\restart-monitor.ps1:19 char:5
+ $notify.icon = $icon
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Property ‘visible’ cannot be found on this object; make sure it exists and is settable.
At C:\AppV_Client_Remote\restart-monitor.ps1:20 char:5
+ $notify.visible = $True
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Unable to find type [system.windows.forms.tooltipicon]: make sure that the assembly containing this type is loaded.
At C:\AppV_Client_Remote\restart-monitor.ps1:26 char:14
+ Default {$messageIcon=[system.windows.forms.tooltipicon]::None}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (system.windows.forms.tooltipicon:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
You cannot call a method on a null-valued expression.
At C:\AppV_Client_Remote\restart-monitor.ps1:30 char:5
+ $notify.showballoontip($Notification_timeout,$title,$text,$type)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
& : The term ‘amp’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\AppV_Client_Remote\restart-monitor.ps1:48 char:6
+ & ‘C:\mstsc /V:$Computer’
+ ~~~
+ CategoryInfo : ObjectNotFound: (amp:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
C:\mstsc /V:$Computer
PS C:\AppV_Client_Remote>
——————————————————————————————
The Script below:
Param (
[Parameter(ValueFromPipeline=$False,Mandatory=$False)]
[int]$timeout=5
)
$MAX_PINGTIME = $timeout * 600
$max_iterations = $MAX_PINGTIME/5
$Notification_timeout = 10 # in seconds
function Show-notification {
param($type,$text,$title)
#load Windows Forms and drawing assemblies
#define an icon image pulled from PowerShell.exe
$icon=[system.drawing.icon]::ExtractAssociatedIcon((join-path $pshome powershell.exe))
$notify = new-object system.windows.forms.notifyicon
$notify.icon = $icon
$notify.visible = $True
#define the tool tip icon based on the message type
switch ($messagetype) {
“Error” { $messageIcon=[system.windows.forms.tooltipicon]::Error}
“Info” {$messageIcon=[system.windows.forms.tooltipicon]::Info}
“Warning” {$messageIcon=[system.windows.forms.tooltipicon]::Warning}
Default {$messageIcon=[system.windows.forms.tooltipicon]::None}
}
#display the balloon tipe
$notify.showballoontip($Notification_timeout,$title,$text,$type)
}
function ping-host {
param($pc)
$status = Get-WmiObject -Class Win32_PingStatus -Filter “Address=’$pc'”
if( $status.statuscode -eq 0) {
return 1
} else {
return 0
}
}
Function Remote-host
{
while ((Test-Connection -Quiet -ComputerName $Computer) -eq $False) {Test-Connection -Quiet -ComputerName $Computer}
if ((Test-Connection -Quiet -ComputerName $Computer) -eq $True) {
& mstsc /V:$Computer
}
}
$Computer = Read-Host “What is the Computer Name?”
if(ping-host -pc $computer) {
Write-Host “$computer is online; Waiting for it to go offline”
Restart-Computer -ComputerName $computer -Force
$status = “online”
for ($i=0; $i -le $max_iterations; $i++) {
if (!(ping-host -pc $computer )) {
break
}
Start-Sleep -Seconds 5
if($i -eq $max_iterations) {
Write-Host “$computer never went down in last $timeout minutes”
Write-Host “Check that reboot is initiated properly”
show-notification -type “error” -text “$computer is still ONLINE; Check that reboot is initiated properly” -title “Computer is not rebooting”
exit
}
}
Write-Host “$computer is offline now; monitoring for online status”
} else {
Write-Host “$computer is offline; Monitoring for online status”
$status = “offline”
}
for ($i=0; $i -le $max_iterations; $i++) {
if ((ping-host -pc $computer )) {
break
}
Start-Sleep -Seconds 5
if($i -eq $max_iterations) {
Write-Host “Your computer never came back online in last $MAX_PINGTIME seconds”
Write-Host “Check that nothing is preventing starup”
show-notification -type “error” -text “$Computer is NOT coming online; Something is preventing its startup” -title “Computer failed to start”
exit
}
}
Write-Host “Your computer is Online Now; Task done; exiting”
show-notification -type “info” -text “$Computer is online” -title “$Computer successfully restarted”
Remote-host
Please advise.
Thank you.
Regards,
What version of PowerShell are you using? In PowerShell, type $PSVersiontable. See this post for more details: https://deployhappiness.com/what-version-of-powershell-should-i-use/
That’s because at line 14 there’s a comment that says to load the assemblies, but there is no code to actually load the assemblies..
Try adding these lines after that comment:
[Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”) | Out-Null
[Reflection.Assembly]::LoadWithPartialName(“System.Drawing”) | Out-Null
Thank you,
Now that part is solved, the issue is in the remote desktop now:
& : The term ‘amp’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\AppV_Client_Remote\restart-monitor.ps1:50 char:6
+ & ‘mstsc /V:$Computer’
+ ~~~
+ CategoryInfo : ObjectNotFound: (amp:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
——————————————
I replaced
‘C:\Program Files (x86)\NetSupport\NetSupport Manager\PCICTLUI.EXE’ /C”$Computer” /vw /e
with: & ‘mstsc /V:$Computer’
There is something screwy going on with my blog’s script editor. Sorry for the confusion!
If you are using remote desktop, the line should read:
& ‘mstsc.exe’ /V:$Computer
Thank you dear Jospeh, now it’s working.
What about below command and parameter?
It’s not working when I run it from MMC
Command: c:\windows\System32\WindowsPowerShell\v1.0\powershell.exe
Parameters: -command “”&” ‘”\\SERVER\SHARE\restart-monitor.ps1′””
Great!
Remove the amp; from your parameters and you should be good! I went back and removed that garbage from the post.
Thank you George!