I scripted in a pre-check to see if a device has not rebooted for two days before they can install:
## checks if device has not rebooted within two working days. Will show reboot prompt if this time has exceeded.
$lastbootuptime = (Get-ADTPendingReboot).LastBootUpTime
$rebootpending = (Get-ADTPendingReboot).IsSystemRebootPending
## if statement to see if user is logged off/away and system is logged on
if($rebootpending -eq $true -and (Get-ADTLoggedOnUser).UserName -eq "system"){
Write-ADTLogEntry "User is logged off. Silent install"}
## tests if device is pending a reboot and not rebooted in the past two days with the user logged on.
if($rebootpending -eq $true -and $lastbootuptime -lt (Get-Date).AddDays(-2) -and (Get-ADTLoggedOnUser).UserName -notlike "system")
{
if ((Show-ADTInstallationPrompt -Message "An install of $($ADTsession.InstallTitle) is about to take place but is unable to proceed because your device has a reboot pending. `nPlease can you save any work and reboot so the install can begin." `
-ButtonRightText 'Reboot Now' -ButtonLeftText 'Reboot Later' -Subtitle "Action Required") -eq 'Reboot Now')
{
Restart-Computer -force}
else
{
Close-ADTSession -ExitCode 1602}
}
This worked fine on previous v4 versions and the only change I have done is the new exit code 1602 rather than 60012.
When i check the logs, i see the below error:
[Pre-Install] :: Exception calling "InitCloseAppsDialog" with "1" argument(s): "Pipe is broken."
Error Record:
-------------
Message : Exception calling "InitCloseAppsDialog" with "1" argument(s): "Pipe is broken."
InnerException : System.IO.IOException: Pipe is broken.
at System.IO.Pipes.PipeStream.WinIOError(Int32 errorCode)
at System.IO.Pipes.PipeStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.BinaryWriter.Write7BitEncodedInt(Int32 value)
at System.IO.BinaryWriter.Write(String value)
at PSADT.ClientServer.ServerInstance.Invoke[T](String command) in C:\Repos\PSAppDeployToolkit\src\PSADT\PSADT.ClientServer.Server\ServerInstance.cs:line 541
at PSADT.ClientServer.ServerInstance.InitCloseAppsDialog(ReadOnlyCollection`1 closeProcesses) in C:\Repos\PSAppDeployToolkit\src\PSADT\PSADT.ClientServer.Server\ServerInstance.cs:line 193
at CallSite.Target(Closure , CallSite , Object , Object )
FullyQualifiedErrorId : IOException,Show-ADTInstallationWelcome
ScriptStackTrace : at Private:Invoke-ADTClientServerOperation, C:\WINDOWS\IMECache\32fd5921-2276-4006-aaf6-2ac9eebf9118_1\PSAppDeployToolkit\PSAppDeployToolkit.psm1: line 1251
at Show-ADTWelcomePrompt, C:\WINDOWS\IMECache\32fd5921-2276-4006-aaf6-2ac9eebf9118_1\PSAppDeployToolkit\PSAppDeployToolkit.psm1: line 19110
at Show-ADTInstallationWelcome<Process>, C:\WINDOWS\IMECache\32fd5921-2276-4006-aaf6-2ac9eebf9118_1\PSAppDeployToolkit\PSAppDeployToolkit.psm1: line 19413
at Install-ADTDeployment, C:\WINDOWS\IMECache\32fd5921-2276-4006-aaf6-2ac9eebf9118_1\Invoke-AppDeployToolkit.ps1: line 164
at <ScriptBlock>, C:\WINDOWS\IMECache\32fd5921-2276-4006-aaf6-2ac9eebf9118_1\Invoke-AppDeployToolkit.ps1: line 405
at <ScriptBlock>, <No file>: line 1
PositionMessage : At C:\WINDOWS\IMECache\32fd5921-2276-4006-aaf6-2ac9eebf9118_1\Invoke-AppDeployToolkit.ps1:164 char:5
+ Show-ADTInstallationWelcome @saiwParams `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Not sure why this is happening.
Further investigation, this happens when the user hits "reboot now" so they don't actually see any errors. Still doesn't look nice in intune reports though.
I reformatted your code as it was quite hard to follow. I'd recommend trying to use a consistent set of bracing for readability.
## checks if device has not rebooted within two working days. Will show reboot prompt if this time has exceeded.
$lastbootuptime = (Get-ADTPendingReboot).LastBootUpTime
$rebootpending = (Get-ADTPendingReboot).IsSystemRebootPending
## if statement to see if user is logged off/away and system is logged on
if ($rebootpending -eq $true -and (Get-ADTLoggedOnUser).UserName -eq "system")
{
Write-ADTLogEntry "User is logged off. Silent install"
}
## tests if device is pending a reboot and not rebooted in the past two days with the user logged on.
if ($rebootpending -eq $true -and $lastbootuptime -lt (Get-Date).AddDays(-2) -and (Get-ADTLoggedOnUser).UserName -notlike "system")
{
if ((Show-ADTInstallationPrompt -Message "An install of $($ADTsession.InstallTitle) is about to take place but is unable to proceed because your device has a reboot pending.`nPlease can you save any work and reboot so the install can begin." -ButtonRightText 'Reboot Now' -ButtonLeftText 'Reboot Later' -Subtitle "Action Required") -eq 'Reboot Now')
{
Restart-Computer -force
}
else
{
Close-ADTSession -ExitCode 1602
}
}
Now that all this is said and done, why aren't you using Show-ADTInstallationRestartPrompt? It has custom message support now and will properly show an asynchronous dialog, or if running silently, will trigger a reboot during the Close-ADTSession process as final closing action before exiting.
Where is this code located in your script as well? For it to be triggering the exception you're demonstrating to us, it'd have to be prior to the Show-ADTInstallationWelcome line because what's happening is that Restart-Computer has started to do its thing, but you're not exiting the script at all. There's nothing in Restart-Computer that's going to halt execution, so it's quite possible to get 1-2 more commands fired off before the restart actually happens, by which point PSADT.ClientServer.Client.exe could have already been terminated.
Yeah I was just thinking should I have a custom exit code when the users do hit restart.
The Show-ADTInstallationRestartPrompt does not have custom button params so our users have the option to restart now or later. We do not want to force a restart on them or countdown as they maybe busy/on a call.
We also do not want to force a restart if logged off as this may impact apps if left open in the back ground i.e. Theyre on a break etc.
You can do Show-ADTInstallationRestartPrompt -NoCountdown, that way it just sits there onscreen until they press the Restart Now button. This is effectively giving you almost the same outcome with the added bonus that they can't infinitely delay the reboot.
If you're not amenable to that, change your code to something like this:
## checks if device has not rebooted within two working days. Will show reboot prompt if this time has exceeded.
$lastbootuptime = (Get-ADTPendingReboot).LastBootUpTime
$rebootpending = (Get-ADTPendingReboot).IsSystemRebootPending
## if statement to see if user is logged off/away and system is logged on
if ($rebootpending -eq $true -and (Get-ADTLoggedOnUser).UserName -eq "system")
{
Write-ADTLogEntry "User is logged off. Silent install"
}
## tests if device is pending a reboot and not rebooted in the past two days with the user logged on.
if ($rebootpending -eq $true -and $lastbootuptime -lt (Get-Date).AddDays(-2) -and (Get-ADTLoggedOnUser).UserName -notlike "system")
{
if ((Show-ADTInstallationPrompt -Message "An install of $($ADTsession.InstallTitle) is about to take place but is unable to proceed because your device has a reboot pending.`nPlease can you save any work and reboot so the install can begin." -ButtonRightText 'Reboot Now' -ButtonLeftText 'Reboot Later' -Subtitle "Action Required") -eq 'Reboot Now')
{
Start-Process -FilePath powershell.exe -ArgumentList '-NonInteractive -NoProfile -Command Start-Sleep -Seconds 10; Restart-Computer -Force'
}
Close-ADTSession -ExitCode 1602
}
By doing the restart in a separate process and giving it a 10 second nap beforehand, you're giving the actual PSADT script a chance to call Close-ADTSession and shut down gracefully without pulling the carpet out from underneath everything.
You know, thinking about it further. You could even just do this:
## checks if device has not rebooted within two working days. Will show reboot prompt if this time has exceeded.
$lastbootuptime = (Get-ADTPendingReboot).LastBootUpTime
$rebootpending = (Get-ADTPendingReboot).IsSystemRebootPending
## if statement to see if user is logged off/away and system is logged on
if ($rebootpending -eq $true -and (Get-ADTLoggedOnUser).UserName -eq "system")
{
Write-ADTLogEntry "User is logged off. Silent install"
}
## tests if device is pending a reboot and not rebooted in the past two days with the user logged on.
if ($rebootpending -eq $true -and $lastbootuptime -lt (Get-Date).AddDays(-2) -and (Get-ADTLoggedOnUser).UserName -notlike "system")
{
if ((Show-ADTInstallationPrompt -Message "An install of $($ADTsession.InstallTitle) is about to take place but is unable to proceed because your device has a reboot pending.`nPlease can you save any work and reboot so the install can begin." -ButtonRightText 'Reboot Now' -ButtonLeftText 'Reboot Later' -Subtitle "Action Required") -eq 'Reboot Now')
{
Close-ADTSession -ExitCode 1641
}
else
{
Close-ADTSession -ExitCode 1602
}
}
By default (at least for Intune), by using Close-ADTSession -ExitCode 1641, the exit code of 1641 is considered a "hard reboot" code, which will trigger an immediate restart. I think that'd be the best approach here.
weirdly, this is exactly what i was thinking. Thank you.
Great minds think alike 
. If you have any further dramas, keep posting and I'll keep helping. Hopefully you're enjoying 4.1 as well!
Yeah 4.1 is great. Wasn't too taxing at all adjusting my templates from 4.0.6.