Task Scheduler How to Set Up Recurring Tasks on Windows

Intune + Task Scheduler: The Ultimate Guide to Automated Device Renaming

Introduction

One area I find lacking in Intune is the native ability to execute actions based on specific system events—such as triggering a task before a restart or after a user logs on. This kind of control is incredibly useful for running background tasks without disrupting the end user’s workflow. Fortunately, there’s a workaround: if the task can be handled using Task Scheduler, you can package it as a Win32 app and deploy it via Intune, then let the scheduled trigger handle the rest.

A few scenarios come to mind, but one particular use case is renaming Hybrid Azure AD Join devices after the Autopilot process completes. Michael Niehaus covered this in his blog post Renaming Autopilot-deployed Hybrid Azure AD Join devices – Out of Office Hours. Still, I wanted to experiment with my own approach—leveraging Task Scheduler to handle the renaming automatically. My goal here is to illustrate how we can still control task execution timing, even within Intune’s current limitations.

Let’s dive in.


Why Rename Devices on Shutdown?

There are scenarios where renaming at shutdown is more appropriate:

  • Devices are provisioned generically and customized later.
  • Post-deployment logic determines naming (e.g., user name, site, or role).
  • Users move across departments and need reclassification.

Renaming during shutdown ensures the name change happens cleanly and safely, with minimal disruption.


Solution Overview

We’ll use:

  • A PowerShell script to rename the device.
  • Task Scheduler XML to trigger renaming on shutdown.
  • Packaging scripts for installation and uninstallation.
  • Intune Win32 App Packaging Tool to create a deployable .intunewin file.

Step 1 :Creat the Install.ps1 Script

The Install.ps1 script was inspired from Michael Niehaus

It consists of three main parts:

  • Creating a log – to track the execution and status of the process.
# Start Transcript for logging script execution
try {
    Write-Verbose "Starting transcript to: $logFilePath"
    Start-Transcript -Path $logFilePath -Append -ErrorAction Stop
} catch {
    Write-Warning "Could not start transcript to '$logFilePath'. Error: $($_.Exception.Message)"
}

#-----
#-----
# Stop Transcript
if ($Transcript) { # Check if transcript was successfully started
    try {
        Stop-Transcript
        Write-Verbose "Transcript stopped."
    } catch {
        Write-Warning "Could not stop transcript. Error: $($_.Exception.Message)"
    }
}
  • Creating a tag – which helps with detection logic later in the process.
# Create a tag file to indicate installation status (e.g., for Intune)
try {
    Write-Verbose "Creating tag file: $tagFilePath"
    Set-Content -Path $tagFilePath -Value "Installed" -Force -ErrorAction Stop
} catch {
    Write-Error "Failed to create tag file '$tagFilePath'. Error: $($_.Exception.Message)"
    # Decide if this should be a critical error or allow continuation
}
  • Registering the scheduled task using the Rename Device on Shutdown.xml file.
    It also copies the Rename-Device-on-Shutdown.ps1 script to a secure folder: C:\ProgramData\Microsoft\Task\.
# Schedule the task using the provided XML file
Write-Host "Attempting to create scheduled task 'Rename Device on Shutdown'..."
try {
    if (-not (Test-Path $taskXmlPath -PathType Leaf)) {
        Write-Error "Scheduled task XML file not found at '$taskXmlPath'. Cannot create task."
        Exit 1
    }

    # -f (Force) will overwrite an existing task with the same name
    $schtasksCommand = "schtasks"
    $schtasksArgs = @("/create", "/tn", "`"Rename Device on Shutdown`"", "/xml", "`"$taskXmlPath`"", "/f")

    # Using Start-Process for external commands provides more control over output and error streams
    $process = Start-Process -FilePath $schtasksCommand -ArgumentList $schtasksArgs -NoNewWindow -PassThru -Wait
    
    if ($process.ExitCode -eq 0) {
        Write-Host "Successfully created scheduled task 'Rename Device on Shutdown'."
    } else {
        Write-Error "Failed to create scheduled task. schtasks exited with code $($process.ExitCode)."
        # You might want to capture and display schtasks output for more details
    }
} catch {
    Write-Error "An error occurred while trying to create the scheduled task: $($_.Exception.Message)"
    Exit 1
}

Step 2 :Creat the Uninstall.ps1 Script

The uninsatll.ps1 script will delete the following

  • Delete the Scheduled Task
# 1. Delete the Scheduled Task
Write-Host "Attempting to delete scheduled task '$taskName'..."
try {
    # Check if the task exists before trying to delete it
    $taskExists = (schtasks /query /tn "`"$taskName`"" /fo LIST 2>$null) -notmatch "ERROR:"
    
    if ($taskExists) {
        $schtasksCommand = "schtasks"
        $schtasksArgs = @("/delete", "/tn", "`"$taskName`"", "/f") # /f for force delete without prompt

        $process = Start-Process -FilePath $schtasksCommand -ArgumentList $schtasksArgs -NoNewWindow -PassThru -Wait
        
        if ($process.ExitCode -eq 0) {
            Write-Host "Successfully deleted scheduled task '$taskName'."
        } else {
            Write-Error "Failed to delete scheduled task '$taskName'. schtasks exited with code $($process.ExitCode)."
        }
    } else {
        Write-Host "Scheduled task '$taskName' not found. Nothing to delete."
    }
} catch {
    Write-Error "An error occurred while trying to delete the scheduled task: $($_.Exception.Message)"
    # Continue with other cleanup even if task deletion fails
}
  • Delete the Tag File
# 2. Delete the Tag File
Write-Host "Attempting to delete tag file: $tagFilePath"
try {
    if (Test-Path $tagFilePath -PathType Leaf) {
        Remove-Item -Path $tagFilePath -Force -ErrorAction Stop
        Write-Host "Successfully deleted tag file: $tagFilePath"
    } else {
        Write-Host "Tag file '$tagFilePath' not found. Nothing to delete."
    }
} catch {
    Write-Error "Failed to delete tag file '$tagFilePath'. Error: $($_.Exception.Message)"
}
  • Delete the application directory (if empty or only contains log files)
try {
    if (Test-Path $baseDir -PathType Container) {
        # Get all items in the directory
        $itemsInDir = Get-ChildItem -Path $baseDir -Recurse -Force -ErrorAction SilentlyContinue
        
        # Define files that are safe to ignore (e.g., log files)
        $safeToIgnore = @(
            (Join-Path $baseDir "Task.log").ToLower()
            (Join-Path $baseDir "Uninstall-Task.log").ToLower()
        )

        # Check if there are any files other than the logs
        $otherFilesExist = $itemsInDir | Where-Object { 
            $_.PSIsContainer -eq $false -and 
            ($safeToIgnore -notcontains $_.FullName.ToLower()) 
        }

        if ($otherFilesExist.Count -eq 0) {
            # Only remove if it's empty or contains only the specified log files
            Remove-Item -Path $baseDir -Recurse -Force -ErrorAction Stop
            Write-Host "Successfully removed directory: $baseDir"
        } else {
            Write-Warning "Directory '$baseDir' contains other files. Not removing to prevent data loss."
            $otherFilesExist | ForEach-Object { Write-Warning "  - Found: $($_.FullName)" }
        }
    } else {
        Write-Host "Directory '$baseDir' not found. Nothing to remove."
    }
} catch {
    Write-Error "Failed to remove directory '$baseDir'. Error: $($_.Exception.Message)"
}

Step 3 : Create the Task Scheduler (Rename Device on Shutdown.xml)

I recommend creating the Task Scheduler task manually first, then exporting the .xml file and placing it alongside your Install.ps1 script.

Check out my post on how to create a Task Scheduler, or if you’re comfortable editing XML directly, you can use the provided template here.

This Task Scheduler XML is configured to listen for Event ID 1074 from the User32 source, which is triggered when a user initiates a shutdown or restart. Once triggered, it executes a PowerShell script that renames the device.

  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="System"&gt;&lt;Select Path="System"&gt;*[System[Provider[@Name='User32'] and EventID=1074]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>
    </EventTrigger>
  </Triggers>

Step 4: Writing the Rename Script

Create a script named Rename-Device-on-Shutdown.ps1 with your custom logic. Here’s a basic example:

# Get the computer's serial number
$serial = Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber
$serial = $serial.SerialNumber

# Set your desired new computer name here (e.g., "Shtech" + SerialNumber)
$newName = "Shtech" + $serial

# Get the current computer name
$currentName = $env:COMPUTERNAME

# Check if a rename is needed
if ($currentName -ne $newName) {
    Write-Host "Renaming computer from '$currentName' to '$newName'..."
    # Rename the computer without forcing a restart
    Rename-Computer -NewName $newName -Force -ErrorAction Stop
    exit 0
}

📝 Tip: Use more sophisticated naming logic (e.g., serial number, domain, department) for enterprise needs.


Step 5: Package Task Scheduler as a Win32 App

Folder Structure

Place the following in a working folder:

📁 RenameDeviceWin32App
├── Install.ps1
├── Uninstall.ps1
├── Rename Device on Shutdown.xml
├── Rename-Device-on-Shutdown.ps1

Use IntuneWinAppUtil tool Content Prep Tool

Download the IntuneWinAppUtil tool, then run:

IntuneWinAppUtil.exe -c "C:\RenameDeviceWin32App" -s Install.ps1 -o C:\Output

This generates a .intunewin file for upload.


Step 6: Deploy with Intune

  1. Go to Intune Admin CenterAppsWindows+ Add.
  2. Choose App type: Windows app (Win32).
  3. Upload the .intunewin file.
  4. Create Name for the application <Rename Laptops>
  5. Install behavior: System
  6. Configure:
    • Install command: powershell.exe -ExecutionPolicy Bypass -File Install.ps1
    • Uninstall command: powershell.exe -ExecutionPolicy Bypass -File Uninstall.ps1
    • Detection Rule: Check for existence of C:\ProgramData\Microsoft\Task\Task.Tag
  • Dependencies/Requirements: Optional based on environment
  • Assign to appropriate device groups.

Step 7: Validate the Task Scheduler

  • On the target machine, open Task Scheduler (run as administrator as the task will run at system level) → Task Scheduler Library.
  • Look for the task: Rename Device on Shutdown.
  • Shutdown the machine — upon startup, confirm the hostname has changed.
Task Scheduler

You can also inspect the Event Viewer for EventID 1074 in the System log to confirm the task trigger.


Security and Permissions Considerations in Creating Task Scheduler

  • Ensure the scheduled task runs with SYSTEM privileges for full permission to rename.
  • Sign the PowerShell scripts if you’re in a secure environment.
  • Avoid hardcoding sensitive info — use parameters and environment variables.

Benefits of using Task Scheduler Approach

FeatureBenefit
Flexible TimingRenames after full user setup or policy application
Fully AutomatedNo manual input needed post-deployment
Intune DeployableScales enterprise-wide easily
Custom Naming LogicUse any scriptable logic to define device names

Final Thoughts

By combining PowerShell, Task Scheduler, and Intune Win32 app deployment, you gain a powerful, flexible mechanism to automate device naming — even outside of Autopilot flows. It’s especially useful in hybrid environments or when reassigning devices with dynamic contexts.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *