With more and more organizations moving to Modern Management approach to manage their endpoints; there is an increase in adapting and leveraging Endpoint Manager and Autopilot where devices can be shipped directly from manufacturers (OEMs) to users. Typically, the OEM would go about Pre-provisioning (AKA White-Glove) those devices where all essential apps are installed and ready to be used by users when they receive and enroll their device (upon first logon) into Intune (Azure AD joined only)
However, many of Microsoft customers out there still use Endpoint Configuration Manager (MECM or SCCM) on-prem and are yet to be 100% cloud based, and if we add the fact that Intune have a lot to catch up on compared to SCCM, many administrators may well prefer to get the best of both worlds (i.e. manage devices via Intune and SCCM simultaneously).
While we can preload devices with most apps during pre-provisioning; The SCCM client installation presents few challenges:
- Enrolling devices into SCCM requires CMG (Cloud Management Gateway) which adds to the cost of your Azure Tenant.
- Without CMG, the alternative would be to connect devices to on-prem Configuration Manager via a VPN, however, at the point of pre-provisioning, no access to corporate network is available.
- Most VPN Solutions require an active user to login before establishing a VPN connection to the corporate network so we can only trigger the installation when a device has successfully passed security checks and connected to the corporate network.
To go about this scenario, I have broken the deployment into three steps:
- Package the SCCM client for Intune (convert to Intunewin package).
- Download SCCM client to endpoints as part of pre-provisioning (white Glove) – or as a user-driven installed app
- Trigger the installation upon user login via a scheduled task and a PowerShell script when a set of conditions are met.
Contents
Step 1: Package the SCCM client for Intune
To package SCCM in an format that Intune can understand, download the Microsoft Win32 Content Prep Tool. This tool allows you to create Win32 packages that can be uploaded to Intune. Click on “Code” and choose “Download ZIP”
Extract the contents – they will look similar to this
We will come back to this later, for now let’s get the installation script ready
The script will do several checks before triggering an installation:-
- Is SCCM Client already installed? if yes, exit.
- Is SCCM package (MSI) downloaded on the endpoint? if not, exit.
- Has the device connected to VPN and is SCCM server on-prem ping-able? if not, exit, otherwise trigger the installation.
What you will need to have in hand to customize the script?
- SMSMP: The FQDN of your SCCM server
- SMSSITECODE: Your SCCM site code
- FSP: Fallback Status Point (If applicable)
The script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
<#PSScriptInfo .VERSION 1.0 .GUID 8e7f03b3-2efc-4bdf-8fb1-091a71f68d26 .AUTHOR Amir Joseph Sayes - Twitter: @amirjsa .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Script to install SCCM client if it doesn't exist already when a VPN is connected and on-prem sccm server is pingable on Autopiloted devices (Azure AD joined only) #> # Start of Settings [string]$tmpDatePreifx = $(get-date -format "yyyy-MM-dd-HH-mm-ss") # End of Settings #Gettting the location of the script if ($myInvocation.MyCommand.Path -ne $null) { $ScriptPath = Split-Path $myInvocation.MyCommand.Path } else { $scriptPath = (Get-Location).Path} #If the script isn't saved, use the current location #Function to create a log file for the installation function LogFile([string]$strData) { # Get logfile name/path [string]$LogFileName = "$ScriptPath`\SCCMInstallationLog.log" # Create date/time prefix for log [string]$tmpDatePreifx = $(get-date -format "yyyy-MM-dd HH:mm:ss") #Actually log data Add-Content -Path $LogFileName -Value "$tmpDatePreifx - $strData" Write-Host "$tmpDatePreifx $strData" -ForegroundColor Cyan } LogFile "Check if SCCM is already installed, exit the script" #Check if SCCM is already installed, exit the script if ((Test-Path "C:\Windows\CCM\CcmExec.exe") -eq $true) { LogFile "SCCM is already installed, exit the script" break } LogFile "SCCM Client is not installed. Proceeding to the next check" LogFile "Check if VPN has connected and do not proceed otherwise" #Check if VPN has connected and do not proceed otherwise do { Write-Host "Waiting for VPN to connect" Start-Sleep -Seconds 5 } until (Test-Connection <Replace with your SCCM server FQDN> -Quiet -Count 10) LogFile "VPN is connected and SCCM server is pingable. Proceeding to installation" #Check if SCCM package files are already copied on the device if ((Test-Path "C:\Temp\SCCMPackage\ccmsetup.exe") -eq $false) { LogFile "SCCM package is not found on this machine under C:\Temp\SCCMPackage\ccmsetup.exe. Exiting." Break } Logfile "Triggering the SCCM Client installation..." $res = Start-Process -FilePath "C:\Temp\SCCMPackage\ccmsetup.exe" -ArgumentList "SMSMP=<Replace as required> SMSSITECODE=<Replace as required> FSP=<Replace as required> SMSCACHESIZE=10240 /nocrlcheck /AllowMetered" -Wait -PassThru Logfile "Exit time: $($res.ExitTime). Exit Code:$($res.Exitcode)" Logfile "SCCM Client installation has completed" |
Replace the variables in the code to suite your environment (lines 78 and 89).
Save this code as “InstallSCCMClient.ps1” and place it to your SCCM package contents
Prepare and convert the SCCM package to Intunewin format
As explained earlier, the Intune Win 32 App will only copy down the package and will not install it. In order to do that we need a simple .cmd or .bat file that has a copy action. In this example, I am instructing Intune to copy the package to C:\temp\SCCMpackage on the endpoint
Using Notepad, paste the following line and save the file as CopySCCMpackage.cmd
1 2 3 |
xcopy SCCMPackage C:\Temp\SCCMPackage /E /H /C /I |
Move CopySCCMpackage.cmd and place it at the root level with your SCCMPackage folder
Now you are ready to convert the package into Intunewin format. Open up PowerShell as Admin and navigate to the location where you extracted the Microsoft Win32 Content Prep Tool. Call the tool.
As you can see the tool will prompt you for 4 variables:
- Please specify the source folder: The parent folder where your SCCMPackage folder and CopySCCMPackage.cmd reside.
- Please specify the setup file: The path to CopySCCMPackage.cmd
- Please specify the output folder: where the intunewin package will be saved
- Do you want to specify catalog folder (Y/N)? choose N
When you hit enter, the tool will create and place the Intunewin package into the destination you specified
Step 2: Upload the SCCM package into Intune
Navigate to endpoint.microsoft.com as an Intune Admin and go to Apps – All Apps – Add
Select the Intunewin file
Add a description and publisher information as needed.
Next, in the Program tab, add CopySCCMPackage.cmd as install and uninstall command
Leave the “Requirements” tab as is. In the “Detection Rule” tab, add a detection rule to determine whether the application has successfully installed.
Assign the app as appropriate, and save your package. Upon the next sync, your Endpoints will have the package copied to C:\temp\SCCMPackage. Intune will create the temp folder for you if it doesn’t exist.
Step 3: Create a scheduled task to trigger the installation
Now, it’s time to create a scheduled task that would trigger the installation via InstallSCCMClient.ps1 (which should be by now located in C:\temp\SCCMPackage\ folder on the Endpoint
The script is straightforward – The scheduled task will run as System and upon logon:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<#PSScriptInfo .VERSION 1.0 .GUID 051a464a-c06f-4b52-9a46-dc94d0dc7ece .AUTHOR Amir Joseph Sayes - Twitter: @amirjsa .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Script to create a scheduled task that would install SCCM agent if it doesn't exist already when VPN connects #> #Creating a scheduled task #1- Creating the scheduled task action $taskAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -File C:\Temp\SCCMPackage\InstallSCCMClient.ps1' $taskTrigger = New-ScheduledTaskTrigger -AtLogOn $taskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries # Register the new PowerShell scheduled task # The name of your scheduled task. $taskName = "Install SCCM Client" # Describe the scheduled task. $description = "Install SCCM client on Azure AD joined devices when VPN has successfully connected to the network" # Register the scheduled task Register-ScheduledTask -TaskName $taskName -Action $taskAction -Trigger $taskTrigger -Settings $taskSettings -Description $description -User "System" -Force #End |
Save the above script somewhere and move to Endpoint Manager portal (Intune) to upload it.
Go Devices – Scripts – Add – Windows 10 or later
Name the script and add description. In Script settings, upload your script and leave the other options to “No”
Assign the script to your devices. Review and Save the script. Upon the next sync, verify that the Scheduled Task was created by running “Scheduled Tasks” as admin on the Endpoint.
The next time a user logs in, the task will trigger the logic of InstallSCCMClient.ps1. If all conditions are met, the installation will be triggered!
Happy scripting!
wow Amir,its very useful and informative, i read your all blogs over the weekend and it found very useful…Thanks for sharing keep it up and share more information …Thank you.
That’s great to hear! Cheers