WPNinjas HeaderWPNinjas Header

Map printers with Microsoft Endpoint Manager

When moving to the cloud managed modern workplace based on Azure AD Join you will see that there are many benefits available. But especially designing the workplace can lead to problems as Microsoft Endpoint Manager currently supports nearly all policies and settings, but lacks the possibilities of GPO Preferences like drive mapping, file copy and connecting printer. 

All of them can simply be solved with a script or proactive remediation items. But all of them have the problem, that they are not executed during logon of a user and it can happen that it takes a while. Nicola Suter created a nice solution to map network drives. I created now a solution based on the same logic to copy files and connect printers which I share in this blog. 

My scripts provide the following benefits:

GPO Printer Mapping Import

You can use an existing GPO or create a new config directly in the PowerShell script. In this section I will show how you can migrate existing printer mappings from GPO Preferences.

First of all it’s important to export the current GPO’s as XML files.

Then you can use the following script to convert the xml to the PowerShell array which we require in the main script.


The executed script will looks as in the following screenshot:

Now you can just copy the output or locate the “PrinterInfo.txt” file in the current directory. Both locations contain an array with the printer information which is required in the next section.

Setup the script

Now we can use the main script to deploy the printers. The script will create a scheduled task when executed as SYSTEM and when not it will map the printers according to the memberships of the executing user.

To start the customization, open it and add the generated array items in the “Manual Variable Definition” section.

Now you can save the script or adjust the entries as required. 

Deploy Printer and Monitor

The customized script can now be uploaded to MEM Intune for deployment.

Select a name according to your naming convention and add a description if required.

Then upload the script and verify that it is executed as a SYSTEM account and in 64-Bit context.

Assign the script to the groups you wish to provide this functionality.

In the review screen you have the possibility to verify everithing and create the object in MEM.

You can now monitor the deployment as with any other script. On the endpoints you will find logs of executions in the temp folder of the user which logged on. 


I hope this solution helps when facing the same requirements as I had in my project. Improvements and feedback can easily be submitted via Github

Follow me


Frank · February 20, 2022 at 22:32

Hi Thomas, that looks like a really great solution but when running the first script I get the error “Method invocation failed because [System.String] does not contain a method named ‘GetElementsByTagName'”. It looks like a .Net module is missing. Do you know how to get around that?
Thx, Frank

Thomas Kurth · February 22, 2022 at 09:12

Thank you! There was a missing statement due to WordPress which has removed it in the output. Now it should work

Willem · March 8, 2022 at 17:07

Hi Thomas, when using this script as described above no scheduled task is created on the end users device.
The log only shows:
Running as SYSTEM: True
TerminatingError(): “System error.”

If we execute the script manually with psexec, PowerShell shows:
Transcript started, output file is c:\windows\TEMP\PrinterMapping.log
Running as SYSTEM: True

But there is no task created and also the transcript keeps running.

On the same devices we can use the drive mapping script from Nicola Sluter without any issues.
Any idea on what’s going wrong here?
Thanks in advance!

    Thomas Kurth · April 27, 2022 at 23:00

    Just updated the script on Github with a fix

      Willem · May 2, 2022 at 11:00

      Thanks Thomas, issues are resolved now!

Dave · April 4, 2022 at 15:48

Getting the following error for every printer I specify.

Get-Printer : Cannot validate argument on parameter ‘ComputerName’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At line:151 char:54
+ … (Get-Printer -ComputerName ([URI]($Printer.PrintServer).host) -Name $ …

    Thomas Kurth · April 27, 2022 at 23:00

    Just updated the script on Github with a fix

Ákos · June 14, 2022 at 13:57

Salü Thomas, don’t forget AppLocker.
I was copying from this reason the source files into $env:ProgramFiles.
Cheers, Ákos

    Thomas Kurth · June 15, 2022 at 22:32

    Thanks for the feedback, that is a good point. Or perhaps even better would be to sign the scripts.

LEE AP · October 6, 2022 at 01:34

I am getting the below error when set to default=1
Failed to map the printer
Invoke-CimMethod : Cannot bind argument to parameter ‘InputObject’ because it is null.
At C:\Users\BlueConnTest\Downloads\PrinterMapping.ps1:162 char:37
+ … Invoke-CimMethod -InputObject $printer -Method …
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-CimMethod], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.Management.Infrastructure.CimCmdlets.InvokeCimMethodCommand

Oz · October 18, 2022 at 21:43

Does the script have a trigger which detects change in the network and rerun the script to map the printers. I say this because I have a user initiated vpn that sometimes it doesn’t run after login and need a trigger to allow the script to rerun when a user reconnects to the network.

    Thomas Kurth · November 11, 2022 at 11:59

    Currently this is not implemented but would be possible as you can extend the current scheduled task which is used with additional triggers based on Windows Event Logs.

Jessie Hernandez · January 17, 2023 at 18:31

Hi Thomas thanks for doing this! This script is extremely useful for Hybrid environments that need printer mappings. I noticed that the 1st script is missing the tag when setting up the $policy variable. You have it in your source code: https://github.com/ThomasKur/ModernAndSecureWorkplace/blob/master/IntuneScripts/GPOPreferenceReplacement/Generate-PrinterArrayFromGPO.ps1 but not on this page.

    Thomas Kurth · January 30, 2023 at 12:52

    thanks for this feedback.

Manuel Jong · February 18, 2023 at 14:07

Hi all,
You could add this to the end 9f the script for detecting when its on corporate network or not.

$trigger = New-ScheduledTaskTrigger -AtLogOn

$class = cimclass MSFT_TaskEventTrigger root/Microsoft/Windows/TaskScheduler
$trigger2 = $class | New-CimInstance -ClientOnly
$trigger2.Enabled = $True
$trigger2.Subscription = ‘*[System[Provider[@Name=”Microsoft-Windows-NetworkProfile”] and EventID=10002]]’

$trigger3 = $class | New-CimInstance -ClientOnly
$trigger3.Enabled = $True
$trigger3.Subscription = ‘*[System[Provider[@Name=”Microsoft-Windows-NetworkProfile”] and EventID=4004]]’

#Execute task in users context
$principal= New-ScheduledTaskPrincipal -GroupId “S-1-5-32-545” -Id “Author”

#call the vbscript helper and pass the PosH script as argument
$action = New-ScheduledTaskAction -Execute $wscriptPath -Argument “`”$dummyScriptPath`” `”$scriptPath`””

$settings= New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries

$null=Register-ScheduledTask -TaskName $schtaskName -Trigger $trigger,$trigger2,$trigger3 -Action $action -Principal $principal -Settings $settings -Description $schtaskDescription -Force

Start-ScheduledTask -TaskName $schtaskName

Based on events in eventviewer.

    Thomas Kurth · February 20, 2023 at 15:41

    Thanks for this improvement!

Leave a Reply

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

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