I was having some discussions lately after my session Our journey to a Modern Windows Workplace at the Workplace Ninja Summit. With several attendees of the summit, we discussed the challenges we have when moving from a traditionally managed Windows device (controlled with GPOs and Configuration Managed) to an Azure AD joined (Microsoft Entra joined) Intune-managed Windows device (Modern Windows workplace).
A few challenges people have is how to handle automatically assigning group tags to Windows Autopilot objects when the company has multiple countries or business units. Or how to manage printer mappings or drive mappings for the end users. The drive or printer mappings might be considered as legacy you want to get rid of, but for a lot of companies that’s currently impossible, unfortunately.
We sometimes need to be creative as we don`t have GPOs (GPO preferences) available and not everything can be done natively with Microsoft Intune. Most of the time by being creative and with some scripting, we can workaround our challenges. Although I’m certainly not a scripting guru (like a few of my colleagues), it might be interesting to share with other people how I’ve done printer mappings for a group of users.
The solution
The solution I use is a PowerShell script which is triggered via a scheduled task. Every time a user logs on to the device, the script is triggered, with a short delay of a few minutes. This way I know the connection to the domain is up and running.
If your devices are not always connected to the domain, a better trigger might be on an event log item. An example is event ID 10000 which is found in the NetworkProfile events folder. This log entry is written to the event logs by a network change.
The scheduled task starts a VBS script. The only thing the VBS script does is start another (PowerShell) script. This is to avoid any user-facing pop-ups because the scheduled task runs under Users.
The PowerShell script that is eventually triggered, checks if the domain connection is available, and if that is the case, it connects the printer.
If you counted correctly, you now know my solution consists of three scripts. I wrap these scripts as a win32 app and deploy this package as a required application with Microsoft Intune (tracked by the ESP) to our Windows devices.
Depending on your needs, another package containing the printer driver might also be needed.
The scripts
Let`s walk through the different scripts involved.
The script whose name ends on CreateScheduledTask, creates the scheduled task as the name already shows.
First, the variables are set, from which you most likely want to change the company name.
In the functions region, we define a ClaenUpAndExit function, which is also used for Intune detection when wrapped as a win32 package.
Next, we handle copying the other two scripts to a local folder. The location is defined in the variables. In my case, the location is C:\Program Files\Common Files\CompanyName\PrinterMapping.
In the last part, the script creates the Scheduled task.
As you can see the trigger is AtLogon.
It executes wscript.exe with an argument of the vbs script.
I used the SID S-1-5-32-545 instead of a group name, to make sure the script not only runs correct on a device running an English OS.
And a delay is set at 4 minutes.
Then we have the vbs script whose name ends on ScriptRunFromTaskScheduler.vbs.
As said, it only triggers the initial PowerShell script that does the actual printer mapping.
And last we have the script whose name ends with ScriptRunFromTaskScheduler.ps1.
First, the CleanUpAndExit function is defined. Second, a function to check the connection to the domain is defined, followed by two functions to test the connection to the printers.
In the second part, the Test-DCConnection function is used to test domain connectivity. If the connection is not available, it stops and the status is written to a log file.
If there is a domain connection, the script tries to connect the printers, if the printer is not already connected.
In the last part, a final check is done to check the end state of the printers.
And that`s all to connect one or more network printers to your (cloud-managed) Windows devices. It’s a pretty simple solution, but it does the job.
In case something goes wrong in connecting the printer(s), the log file can be found in %programdata%\Microsoft\IntuneManagementExtension\Logs. I chose this location so it is part of the Device Diagnostics zip folder you can retrieve remotely from your Intune managed devices. Makes troubleshooting a little easier.
In case you want to use the scripts to build your own solution, it is found on my Github repo.
Another challenge you might have when moving to a cloud-managed Windows workplace is mapping network drives. I also shared a post on that topic.
Below is a short video to show that on-premises resources are available, although some people still think this is not possible.
Microsoft Technical Takeoff video:
During the Technical Takeoff days of Microsoft, I participated in the session On-premises to cloud native in Intune: expert tips and key considerations.
This might be interesting for you when you are moving to cloud management.
3 Comments
Hello Peter,
nicely done!
I also use a similar approach, however less elegant than yours: running a Remediation every few fours that will map the printer, if not already mapped.
function Set-NewPrinter {
[cmdletbinding()]
param (
[Parameter (Mandatory=$true)][string]$printerName,
[Parameter (Mandatory=$true)][string]$printServer
)
$returnCode = 0 # successfully mapped – at least added a job that will map it
$printer = “\\” + $printServer + “\” + $printerName
Write-Verbose “Printer: $printer”
$printerFound = Get-Printer -Name $printer -ErrorAction SilentlyContinue
Write-Verbose “Printer found: $printerFound”
if (-not $printerFound) {
$pingtest = Test-Connection -ComputerName $printServer -Quiet -Count 1 -ErrorAction SilentlyContinue
Write-Verbose “Ping test: $pingtest”
if($pingtest){
try {
$addPrinter = Add-Printer -ConnectionName $printer -AsJob -Verbose
Write-Verbose “$printServer;$printerName;Add-Printer-AsJob”
} catch {
Write-Verbose “Exception while adding printer.”
Write-Verbose $_ -ForegroundColor Red
$returnCode = 99 # Exception
}
} else{
Write-Verbose “$printServer is not reachable”
$returnCode = 50 # printServer is not reachable
}
} else { # if (-not (Get-Printer -Name $printer))
Write-Verbose “$printServer;$printerName;printerFound”
$returnCode = 1 # OK, printer found – already mapped
}
return $errorCode
}
Set-NewPrinter -printServer MyPrintServer -printerName MyPrinter
And I even pasted an incorrect code (facepalm)
It should be ‘return $returnCode’
As written in the post, we have to be creative 🙂
I think a lot of different approaches are used to overcome these kind of challenges.