Trigger Machine Restart, Controlled by CM, via PowerShell

Update 2021.06.09 – Based on a comment, I’ve moved over to using some code provided on sccmf12twice.com which I talk about in the post.

Function Restart-ComputerCMClient {
    $time = [DateTimeOffset]::Now.ToUnixTimeSeconds()
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'RebootBy' -Value $time -PropertyType QWord -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'RebootValueInUTC' -Value 1 -PropertyType DWord -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'NotifyUI' -Value 1 -PropertyType DWord -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'HardReboot' -Value 0 -PropertyType DWord -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'OverrideRebootWindowTime' -Value 0 -PropertyType QWord -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'OverrideRebootWindow' -Value 0 -PropertyType DWord -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'PreferredRebootWindowTypes' -Value @("4") -PropertyType MultiString -Force -ea SilentlyContinue
    New-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData' -Name 'GraceSeconds' -Value 0 -PropertyType DWord -Force -ea SilentlyContinue
    $CcmRestart = Start-Process -FilePath c:\windows\ccm\CcmRestart.exe -PassThru -Wait -WindowStyle Hidden
    }

You can grab the function along with the updated version of my test app on GitHub

Original Post Starts Here: Ok, if the title didn’t make sense, let me explain.

  • Goal 1: Trigger a Restart of a computer, which will use the Configuration Manager Dialogs Boxes and so the CM Client is aware of the Restart and not start any jobs.
  • Goal 2: Trigger via PowerShell from the local client without reaching back to the Server (Completely offline)

Basically to replicate this experience, but locally via PowerShell:

Moments after I choose “Restart” on PC 06, I see:

I want to be able to trigger the CM Native Restart Dialog following the Restart Rules setup in the Client Settings.

Stops along the way:

Community: This got me really close: SCCM Reboot DECODED:: How to make a PC Cancel, Start, Extend or Change mandatory reboot to non-mandatory on the fly. The problem was that it required a restart of the CM Service, which you can’t really do during an Application Install… and I don’t like the idea of restarting the CM Service, what if it’s actually doing something when you restart it. So while that post was really helpful to understand how the CM Reboot works, it didn’t get me to the solution.

User Voice Items:

Ideal Solution: CM team adds this functionality: https://configurationmanager.uservoice.com/forums/300492-ideas/suggestions/40159861-ability-to-trigger-reboots-through-the-client-wmi

Another UV that would help with the main reason I need this ability: https://configurationmanager.uservoice.com/forums/300492-ideas/suggestions/38915797-allow-immediate-restart-after-user-initiated-insta

Failed Attempts:

So if you exit an application with Exit Code 3010, it will tell the client a reboot is needed, but on an available deployment will never actually reboot, it just creates the popups. My plan was to create a deadline in the local policy. This actually sorta works. I am able to create a deadline in the past, so as soon as the application is done, it prompts for restart… BUT… the count down doesn’t start until AFTER a Application Policy Evaluation. The Trick her was that you have to make it evaluate the USER deployed applications, not just the Machine. Every thing I did would only trigger machine, unless you ran it from the Control Panel.. See this Twitter Thread

Process:

  • Install App, in Script create a Deadline on the App you’re installing (basically flipping it from Available to Required with a deadline in the past)
    • $Deadline = “20190528024500.000000+***”
    • $AppDeployment.EnforcementDeadline = $deadline
    • $AppDeployment.Put()
    • If you want to figure out how I got $AppDeployment, see HERE
  • Exit App Script with 3010 to tell the system a reboot is needed
  • Trigger App Eval

This actually works, if you go to Control Panel, ConfigMgr Actions and trigger the App Eval. But I couldn’t find a way to do that via PowerShell. (yes, there are ways to trigger App Evals, but it only evals MACHINE policies)

Normal App Install, when deployed as Available and exit code 3010:

You can see that you get prompted to restart, but there is no “Deadline” on the restart, you can snooze forever if you want. This is why we created the 2nd UV above

So unless I could figure out a way to trigger an App Eval which also evals the User apps, I couldn’t get this idea to work either.

Presented Solution:

  • CM Package “Restart Computer”
    • Program “Exit Force Restart”
      • General: Command line: cmd.exe /c
      • General: Run: Hidden
      • General: After running: Configuration Manager restarts computer
      • Environment: Program can run: Whether or not a user is logged on
      • Environment: Run mode: Run with Admin Rights
    • Deployment
      • Collection: All Workstations
      • Purpose: Required
      • Scheduling: Start Time (Available Time): ASAP
      • Scheduling: Deadline 10 years in the Future (Assignment Schedule)
      • Scheduling: Rerun behavior: Never rerun deployed program
      • User Experience: Outside MW: Software install True, System Restart True

With this Package / Program, having it deployed to all machines set it up in the policy on the machine, which then allows you to trigger it via PowerShell.
Program Image:

How? Using the trigger schedule method. ([wmiclass]’ROOT\ccm:SMS_Client’).TriggerSchedule($Schedule)

https://gist.github.com/gwblok/ad56603bef9a6845e4401c40187cc941

So now that we can programmatically reboot the machine, lets add this into an Application Install

Tying it together

I’ve created an Application for Testing things like this: FakeApp – Available on GitHub
Note, remember you have to have already created the Package and deployed it to the workstations you plan to call the Restart. If you don’t it won’t be able to trigger the restart.

I use this script to test additional items, but basically it sets a registry key to True or False. Everything else in the script is for testing processes.

Running the App on End Point results in triggering the Restart Program and popping up the Dialog.
I’ve also set the Application itself to exit with 3010, which lets the machine know the App itself needs the machine to restart.

Image

When you run the App, in AppEnforce & ExecMgr, you can see the FakeApp Script calling the Exit Force Restart Program. (Function in the FakeApp Installer Script)

Image

The script is available on GitHub, and you’ll see how the App calls the Restart Package:

The Actual Install part of the script is very short, and then calls the Restart function below:

This function finds the policy for the Restart Computer Package, then triggers the “install” of the Package which tells the system to restart.

Now, this is NOT the solution I’d like, but it’s the only thing I could make work. I would really like the ConfigMgr team to do those uservoice options, to allow better control around Application Installs, and give us a way to add a ConfigMgr restart into our own Scripts for our reasons.

Take a look at the full code on GitHub, if you have Qs, hit me up.

Gary Blok – GARYTOWN.COM

10 thoughts on “Trigger Machine Restart, Controlled by CM, via PowerShell”

  1. Hi,
    I’m interested in using this but can you give more information on how you create your CM Package “Restart Computer” because I don’t understand where this General: After running: Configuration Manager restarts computer option is.
    Thanks

    Reply
    • On the Package, you create a Program. “General” = Tab of the Program, “After Running” = The Option in the program. “CM restarts computer” is the selection for that option.
      Hope that helps, I’ve also added an image into the post.

      Reply
  2. I had success triggering the CM reboot prompt by running the registry script from SCCM Reboot DECODED:: How to make a PC Cancel, Start, Extend or Change mandatory reboot to non-mandatory on the fly site and then running CcmRestart.exe. There wasn’t a need to restart the service.

    Reply
    • Unsure, never tried.
      Why not use the built in restart step?

      I don’t think you’d want to use this, it would add a long reboot count down during OSD, assuming it worked.

      Reply
      • It is not for OSD, I am using this with a script to install Symantec DLP in a task sequence, but want the native software center restart prompt to show with snooze button and timer from client settings. the task sequence checks for previous versions uninstalls them and installs the new app with .bat file. i tried it and it worked, the prompt shows but there is probably a better way. you think if i add exit code 3010 to bat it will prompt? or is there variable i can use to prompt. i have another task sequence with the restart step, using SMSREBOOTMESSAGE and SMSREBOOTIMEOUT but no snooze button, just static restart window

        Reply
  3. Hi,

    Similar to Alan, I have been looking for the ability to do a more traditional CM reboot at the end of a task sequence – something more than the 2hr 45min TS reboot step offers with normal user experience from patching, etc.

    I’m simply running the PS script within my app deployment task sequence having pre-deployed the package/program for Exit Force Restart to the collection per Gary’s guidance.

    The problem I’m running into is this works about 80% of the time. The other 20% of the time in my testing/piloting, my clients are getting XML errors when running the script and trying to parse the PRG_Requirements piece. Has anyone seen something like this in your usage of this solution? Here is output:

    Cannot convert value “System.Object[]” to type “System.Xml.XmlDocument”. Error: “Unexpected XML
    declaration. The XML declaration must be the first node in the document, and no white space
    characters are allowed to appear before it. Line 30, position 3.”
    At XXXXXXX.ps1:6 char:1
    + [XML]$XML = $RestartProgram.PRG_Requirements
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

    Cannot convert value
    “ROOT\ccm\policy\machine\actualconfig:CCM_SoftwareDistribution.ADV_AdvertisementID=’XXXXXXXX
    XXXXXXXX’,PKG_PackageID=’XXXXXXXX XXXXXXXX’,PRG_ProgramID=’Exit Force Restart Exit Force Restart'”
    to type “System.Management.ManagementObject”. Error: “Not found ”
    At XXXXXXX.ps1:9 char:191
    + … startProgramPackageID)’,PRG_ProgramID=’$($RestartProgramProgramID)'”)

    Comparing a working and non-working client, the first piece of the PRG_Requirements in WMI looks the same:

    Any insight into this is greatly appreciated. Thank you.

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.