MSEndpointMgr

Zero-Touch Microsoft Connected Cache with Intune

What is Microsoft Connected Cache (or MCC)?

Microsoft Connected Cache, or DOINC (Delivery Optimization In-Network Cache) was first released with Configuration Manager Technical Preview 1903 and was created with the intent of replacing distribution points for cloud native devices (aka Entra joined aka AADJ). The solution went through various iterations for the last 5 years, but its General Availability is finally here. MCC acts as a centralized cache node for Delivery Optimization on a network segment. When an Intune managed device is checking for Windows, Updates, Win32Apps and many other download types (for a complete list check Types of download content supported by Delivery Optimization) you can configure it to look or a cache node, and if one is available and does not have the contents you are looking for, it will download it, service to your device and keep it in cache for when other devices need it, reducing internet bandwidth and improving efficiency since content is always available. Peer to Peer Delivery Optimization is great, but if the first computer to download an update on the network goes offline, the next one will have to download it again. When you use MCC the server is most likely always available to service requests.

This guide intention is to automatically deploy an MCC node on Windows 11 25H2 using the local user account option. This implementation will leverage Intune Autopilot with Self-Deployment mode to create a Zero Touch deployment. This idea came from a requirment that many organisations have, where remote offices, which might benefit hugely from a caching solution not always have a dedicated IT team onsite, making it harder to troubleshoot or re-deploy this solution otherwise.

How to create an MCC instance and a node

To get started with MCC, you need an Azure subscription and access to create resources in it.

Once you have that you can navigate to Create a resource, choose Microsoft Connected Cache for Enterprise and then click Create

Choose a Subscription, Resource group, a Location and name.
These are the currently supported locations:

Once the resource is created, you can navigate to it and start creating nodes in the Cache Nodes blade.

You’ll notice you can create nodes on Windows and Linux operating systems.

This guide will cover only Windows deployments. Once you created a new node, go to Configuration and define a size for the cache drive (for this guide 150 will be the value set) and click save.

After that navigate to Deployment, choose Using Local User account and copy all the information for the cache node provisioning (this will be utilised later with the MCC Bootstrap App) and click Download deployment package

Prerequisites of MCC node

Entra Groups

To be able to target our apps, configuration profiles, autopilot and enrollment status page we will need a dynamic group plus one group per physical connected cache node.

Dynamic Group

This group is based on a query for Autopilot Tags and will add any devices imported to Autopilot with the Group tag of MCC. This group will be assigned to the Autopilot Profile, the Enrollment Status Page Profile and the Configuration Profiles

This is the dynamic query for the group.

(device.devicePhysicalIds -any (_ -eq "[OrderId]:MCC"))

Assigned Group(s)

This group(s) will be used to assign each MCC Bootstrap App. In case you have more than one cache node, you will require a unique copy of this app pointing to each node ID and Registration key. Each node corresponding device entra object should be statically assigned to each group. Those should then be assigned to its corresponding Win32App. To illustrate that example below is two Win32apps with their assignments

Win32Apps

1 Enable Windows optional features

VirtualMachinePlatform‘ and ‘Microsoft-Hyper-V-All‘ Windows optional features are required to install and enable MCC. We are going to create a Win32App to deploy those features as per below.

Installation script (Install.ps1)
Param (
    [Parameter(Mandatory = $true)]
    [ValidateSet("Install", "Uninstall")]
    [String]$Mode
)

#region Config
$Features = @("VirtualMachinePlatform", "Microsoft-Hyper-V-All")
$Client = "MCC"
$LogPath = "$env:ProgramData\$Client\logs"
$LogFile = "$LogPath\FeatureManagement.log"
#endregion

# Ensure log directory exists
if (!(Test-Path -Path $LogPath)) {
    New-Item -Path $LogPath -ItemType Directory -Force | Out-Null
}

$RestartNeeded = $false

foreach ($Feature in $Features) {
    switch ($Mode) {
        "Install" {
            Write-Output "Installing $Feature..." | Tee-Object -FilePath $LogFile -Append
            $result = Enable-WindowsOptionalFeature -Online -FeatureName $Feature -All -NoRestart -ErrorAction SilentlyContinue
        }
        "Uninstall" {
            Write-Output "Uninstalling $Feature..." | Tee-Object -FilePath $LogFile -Append
            $result = Disable-WindowsOptionalFeature -Online -FeatureName $Feature -NoRestart -ErrorAction SilentlyContinue
        }
    }

    if ($result.RestartNeeded) {
        $RestartNeeded = $true
    }

    Write-Output "$Feature - RestartNeeded: $($result.RestartNeeded)" | Tee-Object -FilePath $LogFile -Append
}

Write-Output "Overall RestartNeeded: $RestartNeeded" | Tee-Object -FilePath $LogFile -Append
# Exit code 1641 indicates restart required
if ($RestartNeeded) {
    [System.Environment]::Exit(1641)
} else {
    [System.Environment]::Exit(0)
}
Detection script (detect.ps1 )
$vmPlatform = Get-WmiObject -Class Win32_OptionalFeature | Where-Object { $_.Name -eq "VirtualMachinePlatform" -and $_.InstallState -eq 1 }
$hyperV = Get-WmiObject -Class Win32_OptionalFeature | Where-Object { $_.Name -eq "Microsoft-Hyper-V-All" -and $_.InstallState -eq 1 }
if ($vmPlatform -and $hyperV) {$True}
Intune App

Install command: powershell.exe -ExecutionPolicy Bypass -Command “& { ./Install.ps1 -Mode Install; exit $LASTEXITCODE }”

Uninstall command: powershell.exe -ExecutionPolicy Bypass -Command “& { ./Install.ps1 -Mode Uninstall; exit $LASTEXITCODE }”

2 WSL

Windows Subsystem for Linux can also be enabled as a Windows optional feature, but we will be using the latest release from Microsoft available on GitHub. This will also be packaged as a Win32App

Intune App

Install command: msiexec /i wsl.2.6.1.0.x64.msi /qn /l*v C:\ProgramData\MCC\Logs\wsl_2_6_1_0_Install.log

Uninstall command: msiexec /x “{8705254B-3AE0-4CFA-93D5-F71DCDE9ED2B}” /qn

  • Note that the Device restart behavior is set to “Intune will force a mandatory device restart”

3 MCC Deployment Package

The deployment package is a Msixbundle app and as we need to create a dependency chain between our apps, it needs to be re-packaged as a Win32App.

These are the instructions for the current version:

Download the deployment package (msixbundle) and add the following script to a source folder (to later create the .intunewin file


Installation script (Install.ps1)

Param (
    [Parameter(Mandatory = $true)]
    [ValidateSet("Install", "Uninstall")]
    [String[]]$Mode
)

# ----------------------------------------
# Read file info: locate the MSIX bundle
# ----------------------------------------
$MSIX = (Get-ChildItem -Recurse -Path ".\*.msixbundle").FullName

# ----------------------------------------
# Retrieve MSIX properties
# ----------------------------------------

# Load .NET assembly to work with ZIP files
Add-Type -AssemblyName System.IO.Compression.FileSystem

# Open the .msixbundle as a ZIP archive
$zip = [System.IO.Compression.ZipFile]::OpenRead($MSIX)

# Create an empty array to store package info
$packageInfoList = @()

# Find all embedded .msix or .appx packages inside the bundle
$packages = $zip.Entries | Where-Object { $_.FullName -like "*.msix" -or $_.FullName -like "*.appx" }

# Loop through each embedded package
foreach ($pkg in $packages) {
    # Open the embedded package stream
    $pkgStream = $pkg.Open()

    # Treat the embedded package as a ZIP archive
    $pkgZip = New-Object System.IO.Compression.ZipArchive($pkgStream, [System.IO.Compression.ZipArchiveMode]::Read)

    # Locate the AppxManifest.xml file inside the embedded package
    $manifestEntry = $pkgZip.Entries | Where-Object { $_.FullName -eq "AppxManifest.xml" }

    if ($manifestEntry) {
        # Read and parse the manifest XML
        $reader = New-Object System.IO.StreamReader($manifestEntry.Open())
        [xml]$manifest = $reader.ReadToEnd()
        $reader.Close()

        # Create a custom object with Name, Version, and Publisher
        $packageInfo = [PSCustomObject]@{
            Name      = $manifest.Package.Identity.Name
            Version   = $manifest.Package.Identity.Version
            Publisher = $manifest.Package.Identity.Publisher
        }

        # Add the object to the array
        $packageInfoList += $packageInfo
    }

    # Dispose of the embedded package ZIP archive
    $pkgZip.Dispose()
}

# Dispose of the main .msixbundle ZIP archive
$zip.Dispose()

# ----------------------------------------
# Initialize ExitCode
# ----------------------------------------
$ExitCode = 0

# ----------------------------------------
# Main logic based on mode
# ----------------------------------------
switch ($Mode) {
    "Install" {
		if ($MSIX)
			{	
				# Install MSIX from local source
				Add-AppProvisionedPackage -Online -PackagePath $MSIX -SkipLicense
			}
		else 
			{
				# Install MSIX from online binaries
				Add-AppProvisionedPackage -Online -PackagePath "https://aka.ms/do-mcc-ent-windows-x64" -SkipLicense
			}
    }

    "Uninstall" {
        # Uninstall MSIX
        Get-AppxPackage -AllUsers -Name $packageInfoList.name | Remove-AppPackage -AllUsers
    }
}

# ----------------------------------------
# Exit with appropriate code
# ----------------------------------------
[System.Environment]::Exit($ExitCode)
Detection script (detect.ps1 )
IF (Get-AppxPackage -AllUsers | Where-Object { $_.Name -eq "microsoft.deliveryoptimization"})
{$True}
Intune App

Install command: powershell.exe -executionPolicy bypass -file “./Install.ps1” -Mode Install

Uninstall command: powershell.exe -executionPolicy bypass -file “./Install.ps1” -Mode Uninstall

4 MCC Bootstrap

This is the app that will hold all the logic to install the Connected Cache server adjusting all the requisites that would otherwise fail if trying to deploy by only calling the original mcc installer (deploymcconwsl.ps1) directly. Keep in mind, that while the prerequisites (apps 1-3) can be re-used across all connected cache nodes, the MCC Bootstrap app needs to have a separate instance to each node (due to unique parameters to the cache node bring present in the install command).

Installation script (Install.ps1)

<#
.SYNOPSIS
    Script that initiates MCC Self Deployng on Intune
 
.NOTES
    Author: Jose Schenardie
    Contact: @schenardie
    Website: https://www.msendpointmgr.com
#>


param(
	[Parameter(Mandatory = $true)][string]$installationFolder,
	[Parameter(Mandatory = $true)][string]$cacheDrives,
	[Parameter(Mandatory = $true)][string]$customerId,
	[Parameter(Mandatory = $true)][string]$cacheNodeId,
	[Parameter(Mandatory = $true)][string]$customerKey,
	[Parameter(Mandatory = $true)][string]$registrationKey,
	[Parameter(Mandatory = $false)][pscredential]$mccLocalAccountCredential,
	[Parameter(Mandatory = $false)][int]$mccPublicPort = 80,
	[Parameter(Mandatory = $false)][string]$mccLocalAccountUser,
	[Parameter(Mandatory = $false)][string]$mccLocalAccountPassword
)

# Helper function for timestamped logging
function Log-Message {
	param([string]$Message)
	$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
	Write-Host "[$timestamp] $Message"
}

#Logging Function
    $Pname = "MicrosoftConnectedCacheBootstrap"
    $Pversion = "1.0"
    $client = "MCC"
    $logPath = "$env:ProgramData\$client\logs"
    $logFile = "$logPath\$PName" + "_" + "$Pversion" + "_Install.log"
#endregion
    if (!(Test-Path -Path $logPath)) {
        New-Item -Path $logPath -ItemType Directory -Force | Out-Null
    }

    Start-Transcript -Path $logFile -Force 
#Create credential object for local account
$User = "$env:COMPUTERNAME\$mccLocalAccountUser"

#Add account to local administrators group if not yet
if (-not (net localgroup Administrators | Select-String -Pattern $mccLocalAccountUser)) { 
	Log-Message "Adding $($mccLocalAccountUser) to local admins" 
	net localgroup Administrators $mccLocalAccountUser /add 
}
else { 
	Log-Message "$($mccLocalAccountUser) is already member of local admins"
}

#Define Working directory for scheduled Task
$WorkingDir = (Get-ChildItem "C:\program files\WindowsApps" -directory | Where-Object {$_.Name -like "Microsoft.DeliveryOptimization*"} | select-Object -First 1).Fullname + "\deliveryoptimization-cli\"

# Create action for scheduled Task
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -NoProfile -Command `" & '.\deploymcconwsl.ps1' -installationFolder $installationFolder -customerid $customerId -cachenodeid $cacheNodeId -customerkey $customerKey -registrationkey $registrationKey -cacheDrives '$($cacheDrives)' -mccRunTimeAccount $User -mccLocalAccountCredential (New-Object System.Management.Automation.PSCredential('$($User)', (ConvertTo-SecureString '$($mccLocalAccountPassword)' -AsPlainText -Force)))`"" -WorkingDirectory $WorkingDir

# Create principal for scheduled Task
$Principal = New-ScheduledTaskPrincipal -userID $User -LogonType Password -RunLevel Highest

# Create task for scheduled Task
$Task = New-ScheduledTask -Action $Action -Principal $Principal

# Create a task name for the scheduled Task
$DeployWSLTaskName = "MCC_DeployWSL"

# Register scheduled task
Log-Message "Registering scheduled task $DeployWSLTaskName"
Register-ScheduledTask -TaskName $DeployWSLTaskName -InputObject $Task -User $User -Password $mccLocalAccountPassword -Force

# Start scheduled Task
Log-Message "Starting scheduled task $DeployWSLTaskName"
schtasks /run /tn $DeployWSLTaskName /i

# Add 5 seconds wait
Log-Message "Waiting 5 seconds for task to initialize"
Start-Sleep 5

$timeoutMinutes = 15
$startTime = Get-Date
Log-Message "Monitoring $DeployWSLTaskName for completion (timeout: $timeoutMinutes minutes)..."
do {
	$taskInstance = Get-ScheduledTaskInfo -TaskName $DeployWSLTaskName
	Start-Sleep -Seconds 30

	$elapsed = (Get-Date) - $startTime
	Log-Message "$([math]::Floor($elapsed.TotalMinutes)) minutes elapsed, still waiting for $DeployWSLTaskName to complete..."
	if ($elapsed.TotalMinutes -ge $timeoutMinutes) {
		Log-Message "Timeout reached for $DeployWSLTaskName. Exiting with code 1."
		exit 1
	}
} while ($taskInstance.LastTaskResult -eq 267009 -or $taskInstance.LastTaskResult -eq 0)

Log-Message "$DeployWSLTaskName completed with result: $($taskInstance.LastTaskResult)"

#Update Install task to fix broken paths
$taskName = "MCC_Install_Task"
Log-Message "Updating paths for $taskName"

# Get original task
$task = Get-ScheduledTask -TaskName $taskName
$action = $task.Actions[0]
$trigger = $task.Triggers[0]
$principal = $task.Principal

# Extract the StartIn path
$startInPath = "'" + ($task.Actions | Where-Object { $_.Execute -like "*powershell*" }).WorkingDirectory + "'"
$WorkingDirectory = ($task.Actions | Where-Object { $_.Execute -like "*powershell*" }).WorkingDirectory

# Build updated command with StartIn path substitution
$originalArguments = $action.Arguments
$updatedArguments = $originalArguments -replace '"\."', "$startInPath"

# Also update relative paths like .\filename to full path
$updatedArguments = $updatedArguments -replace '\.\\', "$WorkingDirectory\"

# Build new action
$newAction = New-ScheduledTaskAction -Execute $action.Execute -Argument $updatedArguments -WorkingDirectory $WorkingDirectory

# Re-register the task using its original components
Log-Message "Re-registering $taskName with updated paths"
Register-ScheduledTask -TaskName $taskName -Action $newAction -Trigger $trigger -User $User -Password $mccLocalAccountPassword -Force

#Update Monitor task to fix broken paths
$taskName = "MCC_Monitor_Task"
Log-Message "Updating paths for $taskName"

# Get original task
$task = Get-ScheduledTask -TaskName $taskName
$action = $task.Actions[0]
$trigger = $task.Triggers[0]
$principal = $task.Principal

# Extract the StartIn path
$startInPath = "'" + ($task.Actions | Where-Object { $_.Execute -like "*powershell*" }).WorkingDirectory + "'"
$WorkingDirectory = ($task.Actions | Where-Object { $_.Execute -like "*powershell*" }).WorkingDirectory

# Build updated command with StartIn path substitution
$originalArguments = $action.Arguments
$updatedArguments = $originalArguments -replace '"\."', "$startInPath"

# Also update relative paths like .\filename to full path
$updatedArguments = $updatedArguments -replace '\.\\', "$WorkingDirectory\"

# Build new action
$newAction = New-ScheduledTaskAction -Execute $action.Execute -Argument $updatedArguments -WorkingDirectory $WorkingDirectory

# Re-register the task using its original components
Log-Message "Re-registering $taskName with updated paths"
Register-ScheduledTask -TaskName $taskName -Action $newAction -Trigger $trigger -User $User -Password $mccLocalAccountPassword -Force

# Check for MCC_Install_Task and start it if queued
$MCCInstallTaskName = "MCC_Install_Task"
try {
	$MCCInstallTaskStatus = (Get-ScheduledTask -TaskName $MCCInstallTaskName -ErrorAction Stop).State
	if ($MCCInstallTaskStatus -eq 'Ready' -or $MCCInstallTaskStatus -eq 'Queued') {
		Log-Message "Starting $MCCInstallTaskName task..."		
		$maxRetries = 5
		$retryCount = 0
		$taskStatus = (Get-ScheduledTask -TaskName $MCCInstallTaskName).State

		while ($taskStatus -ne 'Running' -and $retryCount -lt $maxRetries) {
			Log-Message "Task $MCCInstallTaskName is not running, retrying in 30 seconds... (Attempt $($retryCount + 1) of $maxRetries)"
			Start-Sleep -Seconds 30
			schtasks /run /tn $MCCInstallTaskName /i
			$taskStatus = (Get-ScheduledTask -TaskName $MCCInstallTaskName).State
			$retryCount++
		}

		# Monitor MCC_Install_Task for 45 minutes
		$timeoutMinutes = 45
		$startTime = Get-Date
		Log-Message "Monitoring $MCCInstallTaskName for completion (timeout: $timeoutMinutes minutes)..."
		do {
			$taskStatus = (Get-ScheduledTask -TaskName $MCCInstallTaskName).State
			$installTaskInstance = Get-ScheduledTaskInfo -TaskName $MCCInstallTaskName
			Start-Sleep -Seconds 60
			
			$elapsed = (Get-Date) - $startTime
			Log-Message "$([math]::Floor($elapsed.TotalMinutes)) minutes elapsed, task state: $taskStatus, result: $($installTaskInstance.LastTaskResult)"
			
			if ($taskStatus -ne "Running") {
			Log-Message "$MCCInstallTaskName is no longer running (state: $taskStatus). Exiting monitoring loop."
			break
			}
			
			if ($elapsed.TotalMinutes -ge $timeoutMinutes) {
			Log-Message "Timeout reached for $MCCInstallTaskName. Continuing..."
			break
			}
		} while ($true)
		
		Log-Message "$MCCInstallTaskName completed with result: $($installTaskInstance.LastTaskResult)"
	}
	else {
		Log-Message "$MCCInstallTaskName is in state: $MCCInstallTaskStatus. Not starting."
	}
} catch {
	Log-Message "$MCCInstallTaskName task not found or not accessible."
}

# Check for MCC_Monitor_Task and start it if queued
$MCCMonitorTaskName = "MCC_Monitor_Task"
try {
	$MCCMonitorTaskStatus = (Get-ScheduledTask -TaskName $MCCMonitorTaskName -ErrorAction Stop).State
	if ($MCCMonitorTaskStatus -eq 'Ready' -or $MCCMonitorTaskStatus -eq 'Queued') {
		Log-Message "Starting $MCCMonitorTaskName task..."
		schtasks /run /tn $MCCMonitorTaskName /i
	}
	else {
		Log-Message "$MCCMonitorTaskName is in state: $MCCMonitorTaskStatus. Not starting."
	}
} catch {
	Log-Message "$MCCMonitorTaskName task not found or not accessible."
}

# De-register the task
Log-Message "Removing $DeployWSLTaskName scheduled task..."
Unregister-ScheduledTask -TaskName $DeployWSLTaskName -Confirm:$false

# Remove account from local admins
Log-Message "Removing $mccLocalAccountUser from local administrators group"
net localgroup Administrators $mccLocalAccountUser /delete

# Add port forwarding if missing
if (!(netsh interface portproxy show v4tov4))
{
	Log-Message "Port forwarding not found, adding required port mappings"
	$ipFilePath = Join-Path ([System.Environment]::GetEnvironmentVariable("MCC_INSTALLATION_FOLDER", "Machine")) "wslIp.txt"
	
	$ipAddress = (Get-Content $ipFilePath | Select-Object -First 1).Trim()
	Log-Message "Using WSL IP address: $ipAddress"
	
	Log-Message "Adding port forwarding for port 80"
	netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=$ipAddress
	
	Log-Message "Adding port forwarding for port 5000"
	netsh interface portproxy add v4tov4 listenport=5000 listenaddress=0.0.0.0 connectport=5000 connectaddress=$ipAddress
}
else {
	Log-Message "Port forwarding already configured"
}

# Add firewall rules if missing
if (-not (Get-NetFirewallRule -DisplayName "WSL2 Port Bridge (MCC SUMMARY)" -ErrorAction SilentlyContinue)) { 
	Log-Message "Adding firewall rule for port 5000 (Terse Summary page)"
	New-NetFirewallRule -DisplayName "WSL2 Port Bridge (MCC SUMMARY)" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 5000 
	Log-Message "Firewall rule added successfully"
}
else {
	Log-Message "Firewall rule already exists for Terse Summary page"
}

Log-Message "Script completed successfully..."
Stop-Transcript 

File Detection logic

The install commnad for this app will require a username and password which will be used to deploy the connected cache server with. That account can be created using a configuration profile as specified below. In this example, the account created was mcc and the password was stalls-steele-mirror-envy. Since this is a local standard account that can only be used on the connected cache node, we are passing the credentials in clear text (which is a requirement for this solution to work). If security deems this action too risky, optional settings on a configuration profile can be deployed to block interactive logons on that device with this account, just keep in mind that troubleshooting eventual problems with the connected cache node will be harder.

Dependency chain

Once we have the four apps created, we need to configure dependency between them so during our Autopilot they will install on the correct order and respect required reboots. Our apps (for this example) are named MCC Optional Features, WSL 2.6.1.0, MCC Installation Files and MCC Bootstrap MCC01 (MCC01 being designation for the cache name). If you have more than one cache, they should follow the dependency (below we have 2 distinct caches to depict that). Then, the Bootstrap apps should be assigned to its corresponding assigned group.

Configuration Profiles

As the MCC node is running with a local account and that account does not need to be an administrator on the device (after installation), we will be required to create an entire new account and a password and allow said account to start scheduled tasks (Log On As Batch Job). But as this account and password are going to be exposed through Intune, we will also use some other User Rights (optionally) to block it from login into the device interactively and via the network. Fo such we will create two profiles.

MCC Account Creation

Can only be done using a Custom type policy and should have the following information

NameMCC Account Creation
OMA-URI./Device/Vendor/MSFT/Accounts/Users/REPLACEWITHACCOUNTNAME/Password
Data typeString
ValueREPLACEWITHDESIREDPASSWORD

MCC User Rights Policy

This will be a settings catalog profile containing the account created above

Policy NamePolicy Value
(OPTIONAL) Deny Access From NetworkREPLACEWITHACCOUNTNAME
(OPTIONAL) Deny Local Log OnREPLACEWITHACCOUNTNAME
Log On As Batch JobREPLACEWITHACCOUNTNAME

Autopilot Profile

This is where we will configure self-deploying mode for our cache servers. This will be assigned to the dynamic group.

Enrollment Status Page Profile

The enrollment status page can also be assigned to the dynamic group, just make sure to add all your connected cache Bootstrap apps, othewise the self-deploying won’t install all necessary resources.

LAPS Profile (Optional)

A LAPS profile, while not mandatory is hihgly advised since this deployment does not require an entra id account but might require having physical access to the box to perform troubleshooting, and since the MCC account might be blocked from logging in, having anothert account which is a local adminstrator might come in handy. This is our example

Conclusion

Once these resources are all created and assigned all that is left to do is to boot the designated device and connect to the internet (wifi or wired). and at the end of the Autopilot Self-Deploying task, you will have your Connected Cache up and running.

In case you need to re-deploy an existing device, all you need to do is navigate to Azure, find the connected cache node, open it and navigate to the Deployment tab. Once there, copy the new registrationkey (they change after each successfull deployment) and update your Bootstrap App Win32 App with the bew registration key under Install Command and send a Wipe to your connected cache. All the rest should happen automatically, once the device goes through Autopilot Self Deploying again.

Jose Schenardie

As a co-founder of Devicie and Secure Measure (companies specialised in endpoint management and cyber security) and MVP since 2024, Jose possess great knowledge across many IT domains and is always happy to share and discuss new ideas in tech.

Outside IT, Jose loves to spend time with his family (wife and two children), prepare a brazilian barbecue and a good game of squash.

Add comment

Sponsors

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.