Powershell Script to Enroll a Device to Intune

In this blog post, we’ll break down the PowerShell script provided, which is used to add a device to Microsoft Intune, a cloud-based service that manages mobile devices and computers. This script automates the process of configuring local machine registry settings and creating a scheduled task to facilitate device enrollment in Intune. Let’s go through the script step by step and understand its functionality.

Script Logic Overview

The script aims to achieve the following main objectives:

  1. Configure necessary registry settings for device enrollment.
  2. Create a scheduled task that triggers the device enrollment process.

Registry Settings Configuration

The script starts by defining various registry paths using variables. These paths represent the location where the required registry keys will be set. The keys are located under HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\MDM.

Registry Path Verification and Creation

The script then checks whether the specified registry paths exist and creates them if they don’t. If the paths do not exist, the script uses New-Item to create the necessary registry keys.

Setting Registry Properties

The script proceeds to set registry properties related to device enrollment. Specifically, it focuses on properties under the MDM key.

  • AutoEnrollMDM: This property is set to DWORD value 1, enabling automatic enrollment in Intune.
  • UseAADCredentialType: This property is set to DWORD value 1, indicating that Azure Active Directory (AAD) credentials will be used for enrollment.
  • MDMApplicationId: This property is set to an empty string, but later in the script, it is checked and updated if needed.

Scheduled Task Creation

The script configures a scheduled task that will execute the Intune enrollment process. Here’s how it’s done:

  • New-ScheduledTaskPrincipal: This cmdlet defines the principal under which the task will run. In this case, it specifies that the task will run under the NT AUTHORITY\SYSTEM account.
  • New-ScheduledTaskSettingsSet: This cmdlet defines various settings for the scheduled task, such as running only if network is available, not stopping when idle, and specifying a time limit for execution.
  • New-ScheduledTaskAction: This cmdlet defines the action that the scheduled task will perform. It specifies the executable (deviceenroller.exe) to run with the argument /c /AutoEnrollMDM, which likely triggers the device enrollment process.
  • New-ScheduledTaskTrigger: This cmdlet defines when the task will be triggered. In this script, the task is scheduled to run once, 5 minutes from the current time.

Modifying the Scheduled Task

The script then registers the scheduled task, retrieves the task, and modifies some of its properties:

  • The start and end boundaries of the trigger are adjusted to allow for a specific execution window.
  • The task’s setting to delete expired tasks after 0 seconds is configured to ensure that expired tasks are deleted immediately.
  • Finally, the modified task is saved using Set-ScheduledTask.

Error Handling

The script includes a try-catch block to handle exceptions. If an exception occurs, the script logs the error, exits gracefully, and returns an appropriate return code.

Conclusion

In summary, this PowerShell script automates the configuration of registry settings and creation of a scheduled task to facilitate device enrollment in Microsoft Intune. By running this script on target devices, administrators can ensure that devices are automatically enrolled in Intune and managed according to organization policies. It’s important to test the script thoroughly in a controlled environment before deploying it to production devices.

# Main Script Logic
try {

#### Local Machine Reg Section ####
#Reg Paths LM
$RegPoliciesLM = "HKLM:\SOFTWARE\Policies"
$RegMSLM = "$RegPoliciesLM\Microsoft"
$RegWINLM = "$RegMSLM\Windows"
$RegCVLM = "$RegWINLM\CurrentVersion"
$RegMDMLM = "$RegCVLM\MDM"


#Test Reg Locations and create if needed LM
$TestPoliciesLM = Test-Path $RegPoliciesLM
If ($TestPoliciesLM -eq $False){New-Item -Path "HKLM:\SOFTWARE" -Name "Policies" -Force}
$MSTestLM = Test-Path $RegMSLM
If ($MSTestLM -eq $False){New-Item -Path "$RegPoliciesLM" -Name "Microsoft" -Force}
$WINTestLM = Test-Path $RegWINLM
If ($WINTestLM -eq $False){New-Item -Path "$RegMSLM" -Name "Windows" -Force}
$CVTestLM = Test-Path $RegCVLM
If ($CVTestLM -eq $False){New-Item -Path "$RegWINLM" -Name "CurrentVersion" -Force}
$MDMTestLM = Test-Path $RegMDMLM
If ($MDMTestLM -eq $False){New-Item -Path "$RegCVLM" -Name "MDM" -Force}


#Test MDM LM
$MDMOldLM = Get-ItemProperty -Path "$RegMDMLM" -ErrorAction SilentlyContinue

If($MDMOldLM -eq $null) {
New-ItemProperty -Path "$RegMDMLM" -Name "AutoEnrollMDM" -PropertyType DWORD -Value "1" -Force
New-ItemProperty -Path "$RegMDMLM" -Name "UseAADCredentialType" -PropertyType DWORD -Value "1" -Force
New-ItemProperty -Path "$RegMDMLM" -Name "MDMApplicationId" -PropertyType String -Value "" -Force
}

$MDMAPPIDLM = Get-ItemProperty -Path "$RegMDMLM" -Name "MDMApplicationId" -ErrorAction SilentlyContinue

If (($MDMAPPIDLM -eq $Null) -or ($MDMAPPIDLM.'MDMApplicationId' -ne ""))
    {
        If ((Get-ItemProperty -Path $RegMDMLM -Name "MDMApplicationId" -ErrorAction SilentlyContinue) -eq $null)  {
            New-ItemProperty -Path "$RegMDMLM" -Name "MDMApplicationId" -PropertyType String -Value "" -Force}
        Else {Set-ItemProperty -Path "$RegMDMLM" -Name "MDMApplicationId" -Value "" -Force}

        If ((Get-ItemProperty -Path $RegMDMLM -Name "AutoEnrollMDM" -ErrorAction SilentlyContinue) -eq $null)  {
            New-ItemProperty -Path "$RegMDMLM" -Name "AutoEnrollMDM" -PropertyType DWORD -Value "1" -Force}
        Else {Set-ItemProperty -Path "$RegMDMLM" -Name "AutoEnrollMDM" -Value "1"  -Force}

        If ((Get-ItemProperty -Path $RegMDMLM -Name "UseAADCredentialType" -ErrorAction SilentlyContinue) -eq $null)  {
            New-ItemProperty -Path "$RegMDMLM" -Name "UseAADCredentialType" -PropertyType DWORD -Value "1" -Force}
        Else {Set-ItemProperty -Path "$RegMDMLM" -Name "UseAADCredentialType" -Value "1"  -Force}


        
    }

###Setup Scheduled Task
$RunTime = (Get-Date).AddMinutes(5)
$STPrin = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType S4U -RunLevel Highest
$Stset = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Hours 1)
$actionUpdate = New-ScheduledTaskAction -Execute %windir%\system32\deviceenroller.exe -Argument "/c /AutoEnrollMDM"
$triggerUpdate = New-ScheduledTaskTrigger -Once -At $RunTime


Register-ScheduledTask -Trigger $triggerUpdate -Action $actionUpdate -Settings $Stset -TaskName "MDMAutoEnroll" -Principal $STPrin -Force

$TargetTask = Get-ScheduledTask -TaskName "MDMAutoEnroll"
$TargetTask.Triggers[0].StartBoundary = $RunTime.ToString("yyyy-MM-dd'T'HH:mm:ss")
$TargetTask.Triggers[0].EndBoundary = $RunTime.AddMinutes(10).ToString("yyyy-MM-dd'T'HH:mm:ss")
$TargetTask.Settings.DeleteExpiredTaskAfter = "PT0S"
$TargetTask | Set-ScheduledTask



} catch [System.Exception] {
    Write-Log $_ -PrependText "FATAL: An unhandled exception was caught. The script will now exit as failed."
    Exit-Script -ReturnCode -999
    Return
}



Exit-Script -ReturnCode 0 # End successfully

PowerShell Desktop Information Script

The following Powershell script will display information such as the Hostname, IP Address, and Username of the computer hosting it. The script works on both Windows Server Desktop and Windows Server Core and is best implemented as a login script for an environment. Prior to enabling it as a login script, one would have to codesign the script, but that will be covered in another post.

add-type -name user32 -namespace win32 -memberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);'
[win32.user32]::showWindow((get-process -id $pid).mainWindowHandle, 0)

# Load the Winforms assembly
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms") | out-null

# Create the form
$form = New-Object Windows.Forms.Form

#Configure the form
$form.text = ""
$form.AutoScaleMode = 2
$form.FormBorderStyle = 0
$form.ControlBox = $false
$form.BackColor = [System.Drawing.Color]::Black
$form.TransparencyKey = [System.Drawing.Color]::Black
$form.AllowTransparency = $true
$form.Width = 400
$form.ShowInTaskbar = $false

#Systray Icon
$notifyIcon = New-Object Windows.Forms.NotifyIcon
$notifyIcon.Icon = [System.Drawing.SystemIcons]::Information
$notifyIcon.Text = "DesktopInfo POSH"
$notifyIcon.Visible = $true


#define a context menu
$contextMenu = New-Object Windows.Forms.ContextMenu
$contextMenuExit = New-Object Windows.Forms.MenuItem
$contextMenuExit.Text = "E&xit"
$contextMenuExit.Add_Click({
    $form.Close()
})
#Out-Null is added to suppress output of index
$contextMenu.MenuItems.Add($contextMenuExit) | Out-Null
$notifyIcon.ContextMenu = $contextMenu


$point = New-Object System.Drawing.Point
$point.Y = 0
$point.X = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Right - $form.Width
$form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$form.DesktopLocation = $point


# Create the hostName label control and set text, size and location
$hostName = New-Object Windows.Forms.Label
$hostName.Location = New-Object System.Drawing.Point(10,10)
$hostName.Size = New-Object System.Drawing.Size(100,25)
$hostName.Width = 300
$hostName.Font = New-Object System.Drawing.Font($hostName.font.Name,16,[System.Drawing.FontStyle]::Bold)
$hostName.ForeColor = [System.Drawing.Color]::White
$hostName.text = "Host Name: $($env:COMPUTERNAME)"

# Create the userName label control and set text, size and location
$userName = New-Object Windows.Forms.Label
$userName.Location = New-Object System.Drawing.Point(10,40)
$userName.Size = New-Object System.Drawing.Size(100,25)
$userName.Width = 300
$userName.Font = New-Object System.Drawing.Font($hostName.font.Name,16,[System.Drawing.FontStyle]::Bold)
$userName.ForeColor = [System.Drawing.Color]::White
$userName.text = "Username: $($env:USERNAME)"


$NetAdapters = Get-NetAdapter
$IPLabel = @()
$i = 70

foreach($na in $NetAdapters){
        $IP = New-Object Windows.Forms.Label
        $IP.Location = New-Object System.Drawing.Point(10,$i)
        $IP.Size = New-Object System.Drawing.Size(100,25)
        $IP.Width = 500
        $IP.Font = New-Object System.Drawing.Font($hostName.font.Name,16,[System.Drawing.FontStyle]::Bold)
        $IP.ForeColor = [System.Drawing.Color]::White
        $IP | Add-Member -NotePropertyName ifIndex -NotePropertyValue $na.ifIndex
        $AdapterAlias = $na.ifAlias
        if($adapterAlias.length -gt 15){
            $adapterAlias = "$($na.ifAlias)".Substring(0,15)
        }
        $IP.text = "$($AdapterAlias): $((Get-NetIPAddress -InterfaceIndex $na.ifIndex).IPv4Address)"
        $IPLabel+=$IP
        $i+=30
}


#refresh form every 2 seconds
$Timer = New-Object System.Windows.Forms.Timer
$Timer.Interval = 2000
$Timer.Add_Tick({
    $hostName.text = "Host Name: $($env:COMPUTERNAME)"
    $userName.text = "Username: $($env:USERNAME)"
    
    #cycle through known interfaces by index
    foreach($l in $IPLabel){
        $na = Get-NetAdapter -InterfaceIndex $l.ifIndex
        $AdapterAlias = $na.ifAlias
        if($adapterAlias.length -gt 15){
            $adapterAlias = "$($na.ifAlias)".Substring(0,15)
        }
        $l.text = "$($AdapterAlias): $((Get-NetIPAddress -InterfaceIndex $na.ifIndex).IPv4Address)"
    }
    $form.SendToBack()
})
$Timer.Enabled = $true


# Add the controls to the Form
$form.controls.add($hostName)
$form.controls.add($userName)
foreach($l in $IPLabel){
    $form.controls.add($l)
}

# Display the dialog
$form.SendToBack()
$form.ShowDialog()
$timer.Stop()
$notifyIcon.Dispose()

The script starts by adding the user32 namespace from the win32 DLL to access the ShowWindow function, which hides the script’s console window. Then, it loads the System.Windows.Forms assembly to create a form for displaying the desktop information.

The form is configured with various settings such as size, background color, transparency, and positioning on the desktop. It also includes a system tray icon with a context menu that allows users to exit the script.

The script retrieves the host name and username from environment variables and displays them as labels on the form. It also fetches network adapter information and dynamically creates labels to display the IP addresses of each adapter.

The form is refreshed every 2 seconds to update the information displayed. It is a work in progress, and more will be added, as well as a configuration file to allow customization of the information displayed. This is only the beginning.

The script can be viewed and downloaded from my github: https://github.com/Thurdi/POSH-DesktopInfo