From 5bd936d648509fad900acb270607a23fa964841a Mon Sep 17 00:00:00 2001 From: SaltySOMAdmin <157048676+SaltySOMAdmin@users.noreply.github.com> Date: Wed, 7 Jan 2026 13:25:49 -0500 Subject: [PATCH 1/3] Additions Added toggle for B&W default. Testing preference cloning. Added unblock for IntuneWinAppUtil download. --- IntuneWinAppUtil.exe | Bin 0 -> 62520 bytes PackageMyPrinters.ps1 | 272 ++++++++++++++++++++++++ PackageMyPrintersAndPreferences.ps1 | 255 +++++++++++++++++++++++ UploadIntuneWinPrinters.ps1 | 311 ++++++++++++++++++++++++++++ printericon.jpg | Bin 0 -> 26803 bytes 5 files changed, 838 insertions(+) create mode 100644 IntuneWinAppUtil.exe create mode 100644 PackageMyPrinters.ps1 create mode 100644 PackageMyPrintersAndPreferences.ps1 create mode 100644 UploadIntuneWinPrinters.ps1 create mode 100644 printericon.jpg diff --git a/IntuneWinAppUtil.exe b/IntuneWinAppUtil.exe new file mode 100644 index 0000000000000000000000000000000000000000..566b5e0371a82ef5bd4e59f4314d72f0996d57f3 GIT binary patch literal 62520 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 literal 0 HcmV?d00001 diff --git a/PackageMyPrinters.ps1 b/PackageMyPrinters.ps1 new file mode 100644 index 0000000..0e5df12 --- /dev/null +++ b/PackageMyPrinters.ps1 @@ -0,0 +1,272 @@ +#Log Dir +$LogDir = ".\Logs" +New-Item -ItemType Directory -Path $LogDir -Force | Out-Null +$LogPath = Join-Path $LogDir "SkippedPrinters.csv" + +# Show installed printers and let an admin pick one or many +$SelectedPrinters = Get-Printer | Out-GridView -Title 'Select Printers to Migrate to Intune' -PassThru +Select-Object Name,DriverName,PortName,ComputerName,ShareName | + +#Create Directory Structure +New-Item -Path .\Drivers -ItemType Directory + +if (-not $SelectedPrinters) { + Write-Host "No printers selected." -ForegroundColor Yellow + return +} + +$defaultbw = Read-Host "**Do you want to default printers to black and white? (Type Y or N and press enter)" +$defaultbw = $defaultbw.Trim().ToUpper() + +ForEach ($selectedprinter in $selectedprinters) { +If ($selectedprinter.ShareName) { +$PrinterName = $selectedprinter.ShareName +} +else { +$PrinterName = $selectedPrinter.Name +} +$PortName = $selectedPrinter.PortName +$PrinterIP = (Get-PrinterPort -Name $PortName).PrinterHostAddress +$DriverName = $selectedprinter.DriverName + +#Grab the 64-bit driver if there are multiple listed and check for INF path. Skip if no INF path. +$Driver = Get-PrinterDriver -Name $DriverName | Where-Object PrinterEnvironment -eq 'Windows x64' | Select-Object -First 1 + +#Skip if no driver: +if (!$Driver) { +$logskipped = [pscustomobject]@{ + PrinterName = $PrinterName + DriverName = $DriverName + PortName = $PortName + PrinterIP = $PrinterIP + PrinterEnvironment = $Driver.PrinterEnvironment + InfPath = $Driver.InfPath + Reason = "No driver object present" + } +$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation +Write-Host "Skipping '$printername' - There's no driver object found. See log for additional details." -ForegroundColor Red +continue +} + +#Skip Driver export if an integrated Windows/Microsoft driver (IPP or similar) +if ($Driver.Manufacturer -eq 'Microsoft') { +$logskipped = [pscustomobject]@{ + PrinterName = $PrinterName + DriverName = $DriverName + PortName = $PortName + PrinterIP = $PrinterIP + PrinterEnvironment = $Driver.PrinterEnvironment + InfPath = $Driver.InfPath + Reason = "Microsoft driver - will be provided by OS/Windows Update" + } + +$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation +Write-Host "Skipping driver export for '$PrinterName' - Microsoft class driver (no export needed)" -ForegroundColor Yellow +continue +} + +#Skip drivers with no exportable INF + if (!$Driver.InfPath) { +$logskipped = [pscustomobject]@{ + PrinterName = $PrinterName + DriverName = $DriverName + PortName = $PortName + PrinterIP = $PrinterIP + PrinterEnvironment = $Driver.PrinterEnvironment + InfPath = $Driver.InfPath + Reason = "INF Path Empty. Cannot export with this script" + } +$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation +Write-Host "Skipping driver export for '$PrinterName' - Microsoft class driver (no export needed)" -ForegroundColor Yellow +continue +} + +$DriverPath = $Driver.InfPath | Split-Path +$DriverINF = $Driver.InfPath | Split-Path -Leaf + +#Copy Driver Files to directory for packaging +If (Test-Path .\Drivers\$Drivername) { +Write-Host "Driver directory already exist" +} +Else { +$DriverDir = New-Item -Path .\ExportedPrinters\$PrinterName\driver -ItemType Directory +Copy-Item -Path "$DriverPath\*" -Destination $DriverDir -Recurse + +#Generate Install script for the printer +$PkgDir = ".\ExportedPrinters\$PrinterName" +$InstallPath = Join-Path $PkgDir 'Install.ps1' +New-Item -ItemType Directory -Path $PkgDir -Force | Out-Null # in case folder wasn't created yet +If ($defaultbw.Trim().ToUpper() -eq "Y") { +$install = @" +# Auto-generated installer for: $PrinterName + +`$DriverINF = '$DriverINF' +`$DriverName = '$DriverName' +`$PortName = '$PortName' +`$PrinterIP = '$PrinterIP' +`$PrinterName = '$PrinterName' + +pnputil.exe /add-driver ".\Driver\`$DriverINF" /install +Add-PrinterDriver -Name `$drivername -ErrorAction SilentlyContinue + +`$checkPortExists = Get-Printerport -Name `$portname -ErrorAction SilentlyContinue + +if (-not `$checkPortExists) +{ +Add-PrinterPort -name `$portName -PrinterHostAddress `$PrinterIP +} + +`$printDriverExists = Get-PrinterDriver -name `$DriverName -ErrorAction SilentlyContinue + +if (`$printDriverExists) +{ +Add-Printer -Name `$PrinterName -PortName `$portName -DriverName `$DriverName +} +else +{ +Write-Warning "Printer Driver not installed" +} + +Set-PrintConfiguration -PrinterName `$PrinterName -Color `$false + +SLEEP 30 +"@ +} +If ($defaultbw.Trim().ToUpper() -ne "Y") { +$install = @" +# Auto-generated installer for: $PrinterName + +`$DriverINF = '$DriverINF' +`$DriverName = '$DriverName' +`$PortName = '$PortName' +`$PrinterIP = '$PrinterIP' +`$PrinterName = '$PrinterName' + +pnputil.exe /add-driver ".\Driver\`$DriverINF" /install +Add-PrinterDriver -Name `$drivername -ErrorAction SilentlyContinue + +`$checkPortExists = Get-Printerport -Name `$portname -ErrorAction SilentlyContinue + +if (-not `$checkPortExists) +{ +Add-PrinterPort -name `$portName -PrinterHostAddress `$PrinterIP +} + +`$printDriverExists = Get-PrinterDriver -name `$DriverName -ErrorAction SilentlyContinue + +if (`$printDriverExists) +{ +Add-Printer -Name `$PrinterName -PortName `$portName -DriverName `$DriverName +} +else +{ +Write-Warning "Printer Driver not installed" +} + +SLEEP 30 +"@ +} + +Set-Content -Path $InstallPath -Value $install -Encoding UTF8 -Force +Write-Host "Created: $InstallPath" -ForegroundColor Green +} + +#Generate Detection Script +$detectionPath = Join-Path $pkgDir 'detection.ps1' +$detectionScript = @" +`$PrinterName = "$PrinterName" + +`$printerinstalled = Get-Printer -Name "`$PrinterName" -ErrorAction SilentlyContinue +if (`$printerinstalled) { + Write-Output "Printer exists" + exit 0 +} +else { + Write-Output "Printer not installed" + exit 1 +} +"@ + +Set-Content -Path $detectionPath -Value $detectionScript -Encoding UTF8 -Force +Write-Host "Created: $detectionPath" -ForegroundColor Cyan + +#Generate Uninstall Script +$uninstallPath = Join-Path $pkgDir 'uninstall.ps1' +$uninstallScript = @" +`$PrinterName = "$PrinterName" +`Remove-Printer -Name "`$PrinterName" +"@ + +Set-Content -Path $uninstallPath -Value $uninstallScript -Encoding UTF8 -Force +Write-Host "Created: $uninstallPath" -ForegroundColor Cyan + +#Build a manifest file with printer details +$manifest = @{ + PrinterName = $PrinterName + DriverName = $DriverName + DriverINF = $DriverINF + PortName = $PortName + PrinterIP = $PrinterIP + DriverSourcePath = $DriverPath + ExportedOnLocal = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss zzz") +} + +#Save as manifest.json next to install.ps1 +$manifestPath = Join-Path $pkgDir 'manifest.json' +$manifest | ConvertTo-Json -Depth 5 | Set-Content -Path $manifestPath -Encoding UTF8 + +Write-Host "Created manifest: $manifestPath" -ForegroundColor Cyan +} + + +#Grab the IntuneWinAppUtil +$dest = Join-Path (Get-Location) "IntuneWinAppUtil.exe" +$url = "https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool/raw/master/IntuneWinAppUtil.exe" + +Write-Host "Downloading IntuneWinAppUtil.exe from GitHub..." + + Invoke-WebRequest -Uri $url -OutFile $dest + +if (Test-Path $dest) { + Write-Host "Download successful" -ForegroundColor Green +} else { + Write-Warning "Download failed. Please check the URL or your network." -Foreground Red +} +# Unblock the downloaded exe +Unblock-File -Path $dest -ErrorAction SilentlyContinue + +# Ensure it's executable +Start-Sleep 1 + + +#Package Printer Files for Win32 App Deployment +$IntuneWinAppUtil = ".\IntuneWinAppUtil.exe" +$SourcePath = ".\ExportedPrinters" +$PrinterFolders = Get-Childitem $SourcePath -Directory + +foreach ($PrinterFolder in $PrinterFolders) { + $setupFolder = $PrinterFolder.FullName + $printerName = $PrinterFolder.Name + $setupFile = "install.ps1" + $setupPath = Join-Path $setupFolder $setupFile + + if (-not (Test-Path $setupPath)) { + Write-Warning "No install.ps1 in $setupFolder - skipping" + continue + } + + Write-Host "Packaging $printerName for Intune deployment..." -ForegroundColor Cyan + & $IntuneWinAppUtil -c $setupFolder -s $setupFile -o $setupFolder -q + Write-Host "Successfully Created .intunewin for $printername" -ForegroundColor Green +} + +$runuploadscript = Read-Host "**All printers & drivers have been exported and packaged for Intune upload. Do you want to upload these printers now?** (Type Y or N and press enter)" +$runuploadscript = $runuploadscript.Trim().ToUpper() +If ($runuploadscript.Trim().ToUpper() -eq "Y") { + Write-Host "User entered $runuploadscript - running script to upload printers to Intune" -ForegroundColor Yellow + Start-Sleep 2 + & .\UploadIntuneWinPrinters.ps1 +} +else { + Write-Host "User entered $runuploadscript - ending script" -ForegroundColor Yellow +} \ No newline at end of file diff --git a/PackageMyPrintersAndPreferences.ps1 b/PackageMyPrintersAndPreferences.ps1 new file mode 100644 index 0000000..6b32f9e --- /dev/null +++ b/PackageMyPrintersAndPreferences.ps1 @@ -0,0 +1,255 @@ +#Log Dir +$LogDir = ".\Logs" +New-Item -ItemType Directory -Path $LogDir -Force | Out-Null +$LogPath = Join-Path $LogDir "SkippedPrinters.csv" + +# Show installed printers and let an admin pick one or many +$SelectedPrinters = Get-Printer | Out-GridView -Title 'Select Printers to Migrate to Intune' -PassThru +Select-Object Name,DriverName,PortName,ComputerName,ShareName | + +#Create Directory Structure +New-Item -Path .\Drivers -ItemType Directory + +if (-not $SelectedPrinters) { + Write-Host "No printers selected." -ForegroundColor Yellow + return +} + +ForEach ($selectedprinter in $selectedprinters) { +If ($selectedprinter.ShareName) { +$PrinterName = $selectedprinter.ShareName +} +else { +$PrinterName = $selectedPrinter.Name +} +$PortName = $selectedPrinter.PortName +$PrinterIP = (Get-PrinterPort -Name $PortName).PrinterHostAddress +$DriverName = $selectedprinter.DriverName +# Path to save user printer preferences +$PrefsFile = ".\ExportedPrinters\$PrinterName\user_prefs.dat" + + +#Grab the 64-bit driver if there are multiple listed and check for INF path. Skip if no INF path. +$Driver = Get-PrinterDriver -Name $DriverName | Where-Object PrinterEnvironment -eq 'Windows x64' | Select-Object -First 1 + +#Skip if no driver: +if (!$Driver) { +$logskipped = [pscustomobject]@{ + PrinterName = $PrinterName + DriverName = $DriverName + PortName = $PortName + PrinterIP = $PrinterIP + PrinterEnvironment = $Driver.PrinterEnvironment + InfPath = $Driver.InfPath + Reason = "No driver object present" + } +$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation +Write-Host "Skipping '$printername' - There's no driver object found. See log for additional details." -ForegroundColor Red +continue +} + +#Skip Driver export if an integrated Windows/Microsoft driver (IPP or similar) +if ($Driver.Manufacturer -eq 'Microsoft') { +$logskipped = [pscustomobject]@{ + PrinterName = $PrinterName + DriverName = $DriverName + PortName = $PortName + PrinterIP = $PrinterIP + PrinterEnvironment = $Driver.PrinterEnvironment + InfPath = $Driver.InfPath + Reason = "Microsoft driver - will be provided by OS/Windows Update" + } + +$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation +Write-Host "Skipping driver export for '$PrinterName' - Microsoft class driver (no export needed)" -ForegroundColor Yellow +continue +} + +#Skip drivers with no exportable INF + if (!$Driver.InfPath) { +$logskipped = [pscustomobject]@{ + PrinterName = $PrinterName + DriverName = $DriverName + PortName = $PortName + PrinterIP = $PrinterIP + PrinterEnvironment = $Driver.PrinterEnvironment + InfPath = $Driver.InfPath + Reason = "INF Path Empty. Cannot export with this script" + } +$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation +Write-Host "Skipping driver export for '$PrinterName' - Microsoft class driver (no export needed)" -ForegroundColor Yellow +continue +} + +$DriverPath = $Driver.InfPath | Split-Path +$DriverINF = $Driver.InfPath | Split-Path -Leaf + +#Copy Driver Files to directory for packaging +If (Test-Path .\Drivers\$Drivername) { +Write-Host "Driver directory already exist" +} +Else { +$DriverDir = New-Item -Path .\ExportedPrinters\$PrinterName\driver -ItemType Directory +Copy-Item -Path "$DriverPath\*" -Destination $DriverDir -Recurse + +# Export current user's printer preferences (if any) +Write-Host "Exporting printer preferences for $PrinterName" -ForegroundColor Cyan + +$proc = Start-Process -FilePath "rundll32.exe" ` + -ArgumentList "printui.dll,PrintUIEntry /Sr /n `"$PrinterName`" /a `"$PrefsFile`" d u g" ` + -Wait -PassThru -NoNewWindow + +if (Test-Path $PrefsFile) { + Write-Host "Preferences exported successfully" -ForegroundColor Green +} +else { + Write-Warning "Could not export preferences for $PrinterName (driver does not support it or access denied)" +} + + +#Generate Install script for the printer +$PkgDir = ".\ExportedPrinters\$PrinterName" +$InstallPath = Join-Path $PkgDir 'Install.ps1' +New-Item -ItemType Directory -Path $PkgDir -Force | Out-Null # in case folder wasn't created yet + +$install = @" +# Auto-generated installer for: $PrinterName + +`$DriverINF = '$DriverINF' +`$DriverName = '$DriverName' +`$PortName = '$PortName' +`$PrinterIP = '$PrinterIP' +`$PrinterName = '$PrinterName' + +pnputil.exe /add-driver ".\Driver\`$DriverINF" /install +Add-PrinterDriver -Name `$drivername -ErrorAction SilentlyContinue + +`$checkPortExists = Get-Printerport -Name `$portname -ErrorAction SilentlyContinue + +if (-not `$checkPortExists) +{ +Add-PrinterPort -name `$portName -PrinterHostAddress `$PrinterIP +} + +`$printDriverExists = Get-PrinterDriver -name `$DriverName -ErrorAction SilentlyContinue + +if (`$printDriverExists) +{ +Add-Printer -Name `$PrinterName -PortName `$portName -DriverName `$DriverName +} +else +{ +Write-Warning "Printer Driver not installed" +} + +# Restore printer preferences if present +`$PrefsFile = ".\user_prefs.dat" +if (Test-Path `$PrefsFile) { + Write-Host "Restoring printer preferences..." + rundll32 printui.dll,PrintUIEntry /Ss /n "`$PrinterName" /a "`$PrefsFile" d u g +} +else { + Write-Host "No preferences file found to restore." +} + +SLEEP 30 +"@ + +Set-Content -Path $InstallPath -Value $install -Encoding UTF8 -Force +Write-Host "Created: $InstallPath" -ForegroundColor Green +} + +#Generate Detection Script +$detectionPath = Join-Path $pkgDir 'detection.ps1' +$detectionScript = @" +`$PrinterName = "$PrinterName" + +`$printerinstalled = Get-Printer -Name "`$PrinterName" -ErrorAction SilentlyContinue +if (`$printerinstalled) { + Write-Output "Printer exists" + exit 0 +} +else { + Write-Output "Printer not installed" + exit 1 +} +"@ + +Set-Content -Path $detectionPath -Value $detectionScript -Encoding UTF8 -Force +Write-Host "Created: $detectionPath" -ForegroundColor Cyan + +#Generate Uninstall Script +$uninstallPath = Join-Path $pkgDir 'uninstall.ps1' +$uninstallScript = @" +`$PrinterName = "$PrinterName" +`Remove-Printer -Name "`$PrinterName" +"@ + +Set-Content -Path $uninstallPath -Value $uninstallScript -Encoding UTF8 -Force +Write-Host "Created: $uninstallPath" -ForegroundColor Cyan + +#Build a manifest file with printer details +$manifest = @{ + PrinterName = $PrinterName + DriverName = $DriverName + DriverINF = $DriverINF + PortName = $PortName + PrinterIP = $PrinterIP + DriverSourcePath = $DriverPath + ExportedOnLocal = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss zzz") +} + +#Save as manifest.json next to install.ps1 +$manifestPath = Join-Path $pkgDir 'manifest.json' +$manifest | ConvertTo-Json -Depth 5 | Set-Content -Path $manifestPath -Encoding UTF8 + +Write-Host "Created manifest: $manifestPath" -ForegroundColor Cyan +} + +<# +#Grab the IntuneWinAppUtil +$dest = Join-Path (Get-Location) "IntuneWinAppUtil.exe" +$url = "https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool/raw/master/IntuneWinAppUtil.exe" + +Write-Host "Downloading IntuneWinAppUtil.exe from GitHub..." + + Invoke-WebRequest -Uri $url -OutFile $dest + +if (Test-Path $dest) { + Write-Host "Download successful" -ForegroundColor Green +} else { + Write-Warning "Download failed. Please check the URL or your network." -Foreground Red +} +#> + +#Package Printer Files for Win32 App Deployment +$IntuneWinAppUtil = ".\IntuneWinAppUtil.exe" +$SourcePath = ".\ExportedPrinters" +$PrinterFolders = Get-Childitem $SourcePath -Directory + +foreach ($PrinterFolder in $PrinterFolders) { + $setupFolder = $PrinterFolder.FullName + $printerName = $PrinterFolder.Name + $setupFile = "install.ps1" + $setupPath = Join-Path $setupFolder $setupFile + + if (-not (Test-Path $setupPath)) { + Write-Warning "No install.ps1 in $setupFolder - skipping" + continue + } + + Write-Host "Packaging $printerName for Intune deployment..." -ForegroundColor Cyan + & $IntuneWinAppUtil -c $setupFolder -s $setupFile -o $setupFolder -q + Write-Host "Successfully Created .intunewin for $printername" -ForegroundColor Green +} + +$runuploadscript = Read-Host "**All printers & drivers have been exported and packaged for Intune upload. Do you want to upload these printers now?** (Type Y or N and press enter)" +$runuploadscript = $runuploadscript.Trim().ToUpper() +If ($runuploadscript.Trim().ToUpper() -eq "Y") { + Write-Host "User entered $runuploadscript - running script to upload printers to Intune" -ForegroundColor Yellow + Start-Sleep 2 + & .\UploadIntuneWinPrinters.ps1 +} +else { + Write-Host "User entered $runuploadscript - ending script" -ForegroundColor Yellow +} \ No newline at end of file diff --git a/UploadIntuneWinPrinters.ps1 b/UploadIntuneWinPrinters.ps1 new file mode 100644 index 0000000..ea2a28a --- /dev/null +++ b/UploadIntuneWinPrinters.ps1 @@ -0,0 +1,311 @@ +function Upload-IntuneWinFile { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string]$FilePath, + + [Parameter(Mandatory)] + [string]$SasUrl, + + [int]$ChunkSizeBytes = 16MB, + + [switch]$SendContentMD5 + ) + + if (-not (Test-Path $FilePath)) { + throw "File not found: $FilePath" + } + + $blockIds = New-Object System.Collections.Generic.List[string] + $totalBytesSent = 0L + + $handler = New-Object System.Net.Http.HttpClientHandler + $client = New-Object System.Net.Http.HttpClient($handler) + $client.Timeout = [TimeSpan]::FromMinutes(30) + + $fs = [System.IO.File]::OpenRead($FilePath) + try { + $index = 0 + $buffer = New-Object byte[] $ChunkSizeBytes + + while (($read = $fs.Read($buffer, 0, $buffer.Length)) -gt 0) { + $blockIdPlain = ($index).ToString("0000000000") + $blockIdB64 = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($blockIdPlain)) + $blockIds.Add($blockIdB64) | Out-Null + + $blockUri = "{0}&comp=block&blockid={1}" -f $SasUrl, [Uri]::EscapeDataString($blockIdB64) + + $chunkBytes = New-Object byte[] $read + [System.Buffer]::BlockCopy($buffer, 0, $chunkBytes, 0, $read) + + $content = New-Object System.Net.Http.ByteArrayContent -ArgumentList (, $chunkBytes) + + if ($SendContentMD5) { + $md5 = [System.Security.Cryptography.MD5]::Create().ComputeHash($chunkBytes) + $md5b64 = [Convert]::ToBase64String($md5) + $content.Headers.Add("Content-MD5", $md5b64) + } + + $resp = $client.PutAsync($blockUri, $content).GetAwaiter().GetResult() + if (-not $resp.IsSuccessStatusCode) { + $err = $resp.Content.ReadAsStringAsync().GetAwaiter().GetResult() + throw "Put Block failed at index $index (size=$read, HTTP $([int]$resp.StatusCode)): $err" + } + + $totalBytesSent += $read + $index++ + } + } + finally { + $fs.Dispose() + } + + $sb = New-Object System.Text.StringBuilder + [void]$sb.Append('') + $blockIds | ForEach-Object { [void]$sb.Append("$($_)") } + [void]$sb.Append('') + $xml = $sb.ToString() + + $uriList = "$SasUrl&comp=blocklist" + $xmlContent = New-Object System.Net.Http.StringContent($xml, [Text.Encoding]::UTF8, "application/xml") + + $xmlContent.Headers.Remove("Content-Type") | Out-Null + $xmlContent.Headers.Add("Content-Type","application/xml") + + $req = New-Object System.Net.Http.HttpRequestMessage([System.Net.Http.HttpMethod]::Put, $uriList) + $req.Content = $xmlContent + $req.Headers.Add("x-ms-version","2019-12-12") + + $resp2 = $client.SendAsync($req).GetAwaiter().GetResult() + if (-not $resp2.IsSuccessStatusCode) { + $err2 = $resp2.Content.ReadAsStringAsync().GetAwaiter().GetResult() + throw "Put Block List failed (HTTP $([int]$resp2.StatusCode)): $err2" + } + + [pscustomobject]@{ + FilePath = $FilePath + FileLength = (Get-Item $FilePath).Length + ChunkSizeBytes = $ChunkSizeBytes + BlocksUploaded = $blockIds.Count + BytesSent = $totalBytesSent + Finalized = $true + } +} +Start-Transcript -path ".\UploadIntuneWinPrinters.log" + +$modules = 'Microsoft.Graph.Authentication', 'Microsoft.Graph.DeviceManagement', 'Microsoft.Graph.Beta.DeviceManagement' +Write-Host -ForegroundColor DarkYellow "Installing Required Modules if they're missing..." +Foreach ($module in $modules) { +if (Get-Module -ListAvailable -Name $module) { + Write-Host -ForegroundColor Yellow "$module module is already installed" +} +else { + Write-Host -ForegroundColor Yellow "Installing the $module Module for Current User" + Install-Module -Name $module -Scope CurrentUser -Force + Write-Host "Installed $module module for current user" +} +} + +#Login to Graph +$scopes = @( + "DeviceManagementApps.ReadWrite.All", + "DeviceManagementConfiguration.ReadWrite.All", + "Files.ReadWrite.All" +) +Connect-MgGraph -Scopes $scopes + +#Root where all printer packages live +$source = ".\ExportedPrinters" + +#Get Base64 value of image for app icon +$imagefile = ".\printericon.jpg" +$imageBytes = [System.IO.File]::ReadAllBytes((Resolve-Path $imageFile)) +$imageBase64 = [Convert]::ToBase64String($imageBytes) + +#Find out if we should make printers available to the all users group +$assignmentresponse = Read-Host "Do you want to assign the printers as available to All Users? (Type Y or N)" +$assignmentresponse = $assignmentresponse.Trim().ToUpper() +If ($assignmentresponse -eq "Y") { + Write-Host "User entered $assignmentresponse - Printers will be assigned as available to All Users" -ForegroundColor Yellow +} +else { + Write-Host "User entered $assignmentresponse - Printers will be NOT be assigned" -ForegroundColor Yellow +} + +Start-Sleep 2 + +#Loop each printer folder and create Win32 App +$PrinterFolders = Get-ChildItem $source -Directory +:printerloop foreach ($Printerfolder in $PrinterFolders) { + $printerName = $Printerfolder.Name + $intunewinPath = Join-Path $Printerfolder.FullName "install.intunewin" + $appdetectPath = Join-Path $Printerfolder.FullName "detection.ps1" + + if (-not (Test-Path $intunewinPath)) { + Write-Warning "No .intunewin found for $printerName — skipping" + continue + } + if (-not (Test-Path $appdetectPath)) { + Write-Warning "No detection.ps1 for $printerName — skipping" + continue + } + Write-Host "Creating Win32 App Shell for $printerName..." -ForegroundColor Cyan + + #Create Win32 app shell + $body = @{ + "@odata.type" = "#microsoft.graph.win32LobApp" + displayName = "Printer - $printerName" + description = "Installs printer $printerName with packaged driver." + publisher = "SMBtotheCloud" + isFeatured = $false + setupFilePath = "install.ps1" + fileName = "install.intunewin" + installCommandLine = '%windir%\sysnative\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -File .\install.ps1' + uninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + installExperience = @{ runAsAccount = "system" } + applicableArchitectures = "x64" + minimumSupportedOperatingSystem = @{ v10_2004 = $true } + detectionRules = @( + @{ + "@odata.type" = "#microsoft.graph.win32LobAppPowerShellScriptDetection" + scriptContent = [Convert]::ToBase64String([IO.File]::ReadAllBytes($appdetectPath)) + enforceSignatureCheck = $false + runAs32Bit = $false + } + ) + returnCodes = @( + @{ type = "success"; returnCode = 0 }, + @{ type = "success"; returnCode = 3010 }, + @{ type = "failed"; returnCode = 1603 } + ) + largeIcon = @{ + type = "image/png" + value = "$imageBase64" + } + } + +#Send Win32 App Shell and get appID +$app = Invoke-MgGraphRequest -Method POST -Uri "/beta/deviceAppManagement/mobileApps" -Body ($body | ConvertTo-Json -Depth 10 -Compress) +$appId = $app.id + +#Create directory for extracted .intunewin contents, set locations and get info from detectionXML +$tempRoot = Join-Path (Get-Location).Path "ExtractedIntuneWinFiles" +$safePrinterName = ($PrinterName -replace '[<>:"/\\|?*]', '_') +$temp = Join-Path $tempRoot ("$safePrinterName" + "_" + $appId) +New-Item -ItemType Directory -Path $temp -Force | Out-Null +Add-Type -AssemblyName System.IO.Compression.FileSystem +[System.IO.Compression.ZipFile]::ExtractToDirectory($intunewinPath, $temp) #need to use this because of file extension +[xml]$detectionxml = Get-Content (Join-Path $temp 'IntuneWinPackage\Metadata\Detection.xml') +$unencryptedSize = [int64]$detectionxml.ApplicationInfo.UnencryptedContentSize +$innerintunewin = Get-ChildItem -Path (Join-Path $temp 'IntuneWinPackage\Contents\') -Filter *.intunewin +$encryptedsize = [int64]$innerintunewin.Length + +#Get Encryption Info from detection.xml for commit to finish Win32App creation +$encXml = $detectionxml.ApplicationInfo.EncryptionInfo +$commitBody = @{ fileEncryptionInfo = @{ + encryptionKey = $encXml.EncryptionKey + fileDigest = $encXml.FileDigest + fileDigestAlgorithm = $encXml.FileDigestAlgorithm + initializationVector = $encXml.InitializationVector + mac = $encXml.Mac + macKey = $encXml.MacKey + profileIdentifier = $encXml.ProfileIdentifier +}} | ConvertTo-Json -Depth 10 + +#Set info for intunewin file. Need to send this to generate SAS URL. +$packagejson = @{ + name = (Split-Path $intunewinPath -Leaf) + size = $unencryptedSize + sizeEncrypted = $encryptedsize + manifest = $null + isDependency = $false + } | ConvertTo-Json -Depth 6 + +#Create new Content Version +$cv = Invoke-MgGraphRequest POST "/beta/deviceAppManagement/mobileApps/$AppId/microsoft.graph.win32LobApp/contentVersions" -Body "{}" -ContentType "application/json" +$cvId = $cv.id + +#Register file upload for new CV +$fileObj = Invoke-MgGraphRequest -Method POST -Uri "/beta/deviceAppManagement/mobileApps/$AppId/microsoft.graph.win32LobApp/contentVersions/$cvId/files" -Body $packageJson -ContentType "application/json" +$fileID = $fileobj.id +Write-Host "New Content Version $cvid has been created. Waiting for SAS URL to be generated..." -ForegroundColor Cyan + +#Wait for SAS URL to populate so we can upload intunewin +do { + Start-Sleep 2 + $fileObjstatus = Invoke-MgGraphRequest -Method GET -Uri "/beta/deviceAppManagement/mobileApps/$AppId/microsoft.graph.win32LobApp/contentVersions/$cvId/files/$($fileObj.id)" + } while (-not $fileObjstatus.azureStorageUri) +Start-Sleep 2 +Write-Host "Starting upload of intunewin file to Intune" -ForegroundColor Cyan + +#upload .intunewin file +$uploadResult = Upload-IntuneWinFile -FilePath $innerIntunewin.FullName -SasUrl $fileObjStatus.azureStorageUri -ChunkSizeBytes 16MB -SendContentMD5 +$uploadResult | Format-List + +start-sleep 3 + +#Commit App +Invoke-MgGraphRequest POST "/beta/deviceAppManagement/mobileApps/$AppId/microsoft.graph.win32LobApp/contentVersions/$cvId/files/$fileId/commit" -Body $commitBody -ContentType "application/json" + +#Point app at new CV after upload state moved to commitFileSuccess. Timeout of 90 seconds to prevent the script from hanging. +Write-Host "App committed. Waiting for file upload state to move to success before assigning content version" -ForegroundColor Cyan +$startTime = Get-Date +$timeout = [TimeSpan]::FromSeconds(90) +do { + Start-Sleep 2 + $appstatus = Invoke-MgGraphRequest GET "/beta/deviceAppManagement/mobileApps/$AppId/microsoft.graph.win32LobApp/contentVersions/$cvId/files/$fileId`?$select=id,name,isCommitted,uploadState,size,sizeEncrypted" + Write-Host "Current State" - $appstatus.uploadState + $elapsed = (Get-Date) - $startTime + if ($elapsed -ge $timeout) { + Write-Warning "Timeout after 90s while waiting for $($PrinterFolder.Name). Deleting printer app and moving onto the next printer" + try { + Invoke-MgGraphRequest -Method DELETE -Uri "/beta/deviceAppManagement/mobileApps/$AppId" + Write-Host "Deleted orphaned app for $printerName" -ForegroundColor Yellow + } + catch { + Write-Warning "Failed to delete orphaned app for $printerName : $($_.Exception.Message)" + } + continue printerloop + } + if ($appstatus.uploadState -eq "commitFileFailed") + { + Write-Warning "Commit File Failed for $printername. Deleting App and Moving on to next printer" + try { + Invoke-MgGraphRequest -Method DELETE -Uri "/beta/deviceAppManagement/mobileApps/$AppId" + Write-Host "Deleted orphaned app for $printerName" -ForegroundColor Yellow + } + catch { + Write-Warning "Failed to delete orphaned app for $printerName : $($_.Exception.Message)" + } + continue printerloop + } + } while ($appstatus.uploadstate -ne "commitFileSuccess") + +$patchbody = @{ +"@odata.type" = "#microsoft.graph.win32LobApp" +committedContentVersion = "$cvId" +} | ConvertTo-Json + +Invoke-MgGraphRequest -Method PATCH -Uri "/beta/deviceAppManagement/mobileApps/$AppId" -Body $patchbody -ContentType "application/json" + +#Verify Commited version is correct: +$app = Invoke-MgGraphRequest GET "/beta/deviceAppManagement/mobileApps/$AppId" +Write-Host "Committed version (app) = $($app.committedContentVersion) (expected $cvId)" +Write-Host "Finished creating deployment for $printername - Moving to the next printer in the list." -ForegroundColor Green + +#Assign to All Users if chosen +If ($assignmentresponse -eq "Y") { + $assignment = @{ + "@odata.type" = "#microsoft.graph.mobileAppAssignment" + intent = "available" + target = @{ + "@odata.type" = "#microsoft.graph.allLicensedUsersAssignmentTarget" + } + } | ConvertTo-Json -Depth 5 + + Invoke-MgGraphRequest -Method POST -Uri "/beta/deviceAppManagement/mobileApps/$AppId/assignments" -Body $assignment -ContentType "application/json" +} +} + +Disconnect-MgGraph +Stop-Transcript \ No newline at end of file diff --git a/printericon.jpg b/printericon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f5fb5c75114cd369d77ef18e165ac2d0331639de GIT binary patch literal 26803 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 Date: Thu, 8 Jan 2026 13:47:28 -0500 Subject: [PATCH 2/3] Delete PackageMyPrintersAndPreferences.ps1 --- PackageMyPrintersAndPreferences.ps1 | 255 ---------------------------- 1 file changed, 255 deletions(-) delete mode 100644 PackageMyPrintersAndPreferences.ps1 diff --git a/PackageMyPrintersAndPreferences.ps1 b/PackageMyPrintersAndPreferences.ps1 deleted file mode 100644 index 6b32f9e..0000000 --- a/PackageMyPrintersAndPreferences.ps1 +++ /dev/null @@ -1,255 +0,0 @@ -#Log Dir -$LogDir = ".\Logs" -New-Item -ItemType Directory -Path $LogDir -Force | Out-Null -$LogPath = Join-Path $LogDir "SkippedPrinters.csv" - -# Show installed printers and let an admin pick one or many -$SelectedPrinters = Get-Printer | Out-GridView -Title 'Select Printers to Migrate to Intune' -PassThru -Select-Object Name,DriverName,PortName,ComputerName,ShareName | - -#Create Directory Structure -New-Item -Path .\Drivers -ItemType Directory - -if (-not $SelectedPrinters) { - Write-Host "No printers selected." -ForegroundColor Yellow - return -} - -ForEach ($selectedprinter in $selectedprinters) { -If ($selectedprinter.ShareName) { -$PrinterName = $selectedprinter.ShareName -} -else { -$PrinterName = $selectedPrinter.Name -} -$PortName = $selectedPrinter.PortName -$PrinterIP = (Get-PrinterPort -Name $PortName).PrinterHostAddress -$DriverName = $selectedprinter.DriverName -# Path to save user printer preferences -$PrefsFile = ".\ExportedPrinters\$PrinterName\user_prefs.dat" - - -#Grab the 64-bit driver if there are multiple listed and check for INF path. Skip if no INF path. -$Driver = Get-PrinterDriver -Name $DriverName | Where-Object PrinterEnvironment -eq 'Windows x64' | Select-Object -First 1 - -#Skip if no driver: -if (!$Driver) { -$logskipped = [pscustomobject]@{ - PrinterName = $PrinterName - DriverName = $DriverName - PortName = $PortName - PrinterIP = $PrinterIP - PrinterEnvironment = $Driver.PrinterEnvironment - InfPath = $Driver.InfPath - Reason = "No driver object present" - } -$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation -Write-Host "Skipping '$printername' - There's no driver object found. See log for additional details." -ForegroundColor Red -continue -} - -#Skip Driver export if an integrated Windows/Microsoft driver (IPP or similar) -if ($Driver.Manufacturer -eq 'Microsoft') { -$logskipped = [pscustomobject]@{ - PrinterName = $PrinterName - DriverName = $DriverName - PortName = $PortName - PrinterIP = $PrinterIP - PrinterEnvironment = $Driver.PrinterEnvironment - InfPath = $Driver.InfPath - Reason = "Microsoft driver - will be provided by OS/Windows Update" - } - -$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation -Write-Host "Skipping driver export for '$PrinterName' - Microsoft class driver (no export needed)" -ForegroundColor Yellow -continue -} - -#Skip drivers with no exportable INF - if (!$Driver.InfPath) { -$logskipped = [pscustomobject]@{ - PrinterName = $PrinterName - DriverName = $DriverName - PortName = $PortName - PrinterIP = $PrinterIP - PrinterEnvironment = $Driver.PrinterEnvironment - InfPath = $Driver.InfPath - Reason = "INF Path Empty. Cannot export with this script" - } -$logskipped | Export-Csv -Path $LogPath -Append -NoTypeInformation -Write-Host "Skipping driver export for '$PrinterName' - Microsoft class driver (no export needed)" -ForegroundColor Yellow -continue -} - -$DriverPath = $Driver.InfPath | Split-Path -$DriverINF = $Driver.InfPath | Split-Path -Leaf - -#Copy Driver Files to directory for packaging -If (Test-Path .\Drivers\$Drivername) { -Write-Host "Driver directory already exist" -} -Else { -$DriverDir = New-Item -Path .\ExportedPrinters\$PrinterName\driver -ItemType Directory -Copy-Item -Path "$DriverPath\*" -Destination $DriverDir -Recurse - -# Export current user's printer preferences (if any) -Write-Host "Exporting printer preferences for $PrinterName" -ForegroundColor Cyan - -$proc = Start-Process -FilePath "rundll32.exe" ` - -ArgumentList "printui.dll,PrintUIEntry /Sr /n `"$PrinterName`" /a `"$PrefsFile`" d u g" ` - -Wait -PassThru -NoNewWindow - -if (Test-Path $PrefsFile) { - Write-Host "Preferences exported successfully" -ForegroundColor Green -} -else { - Write-Warning "Could not export preferences for $PrinterName (driver does not support it or access denied)" -} - - -#Generate Install script for the printer -$PkgDir = ".\ExportedPrinters\$PrinterName" -$InstallPath = Join-Path $PkgDir 'Install.ps1' -New-Item -ItemType Directory -Path $PkgDir -Force | Out-Null # in case folder wasn't created yet - -$install = @" -# Auto-generated installer for: $PrinterName - -`$DriverINF = '$DriverINF' -`$DriverName = '$DriverName' -`$PortName = '$PortName' -`$PrinterIP = '$PrinterIP' -`$PrinterName = '$PrinterName' - -pnputil.exe /add-driver ".\Driver\`$DriverINF" /install -Add-PrinterDriver -Name `$drivername -ErrorAction SilentlyContinue - -`$checkPortExists = Get-Printerport -Name `$portname -ErrorAction SilentlyContinue - -if (-not `$checkPortExists) -{ -Add-PrinterPort -name `$portName -PrinterHostAddress `$PrinterIP -} - -`$printDriverExists = Get-PrinterDriver -name `$DriverName -ErrorAction SilentlyContinue - -if (`$printDriverExists) -{ -Add-Printer -Name `$PrinterName -PortName `$portName -DriverName `$DriverName -} -else -{ -Write-Warning "Printer Driver not installed" -} - -# Restore printer preferences if present -`$PrefsFile = ".\user_prefs.dat" -if (Test-Path `$PrefsFile) { - Write-Host "Restoring printer preferences..." - rundll32 printui.dll,PrintUIEntry /Ss /n "`$PrinterName" /a "`$PrefsFile" d u g -} -else { - Write-Host "No preferences file found to restore." -} - -SLEEP 30 -"@ - -Set-Content -Path $InstallPath -Value $install -Encoding UTF8 -Force -Write-Host "Created: $InstallPath" -ForegroundColor Green -} - -#Generate Detection Script -$detectionPath = Join-Path $pkgDir 'detection.ps1' -$detectionScript = @" -`$PrinterName = "$PrinterName" - -`$printerinstalled = Get-Printer -Name "`$PrinterName" -ErrorAction SilentlyContinue -if (`$printerinstalled) { - Write-Output "Printer exists" - exit 0 -} -else { - Write-Output "Printer not installed" - exit 1 -} -"@ - -Set-Content -Path $detectionPath -Value $detectionScript -Encoding UTF8 -Force -Write-Host "Created: $detectionPath" -ForegroundColor Cyan - -#Generate Uninstall Script -$uninstallPath = Join-Path $pkgDir 'uninstall.ps1' -$uninstallScript = @" -`$PrinterName = "$PrinterName" -`Remove-Printer -Name "`$PrinterName" -"@ - -Set-Content -Path $uninstallPath -Value $uninstallScript -Encoding UTF8 -Force -Write-Host "Created: $uninstallPath" -ForegroundColor Cyan - -#Build a manifest file with printer details -$manifest = @{ - PrinterName = $PrinterName - DriverName = $DriverName - DriverINF = $DriverINF - PortName = $PortName - PrinterIP = $PrinterIP - DriverSourcePath = $DriverPath - ExportedOnLocal = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss zzz") -} - -#Save as manifest.json next to install.ps1 -$manifestPath = Join-Path $pkgDir 'manifest.json' -$manifest | ConvertTo-Json -Depth 5 | Set-Content -Path $manifestPath -Encoding UTF8 - -Write-Host "Created manifest: $manifestPath" -ForegroundColor Cyan -} - -<# -#Grab the IntuneWinAppUtil -$dest = Join-Path (Get-Location) "IntuneWinAppUtil.exe" -$url = "https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool/raw/master/IntuneWinAppUtil.exe" - -Write-Host "Downloading IntuneWinAppUtil.exe from GitHub..." - - Invoke-WebRequest -Uri $url -OutFile $dest - -if (Test-Path $dest) { - Write-Host "Download successful" -ForegroundColor Green -} else { - Write-Warning "Download failed. Please check the URL or your network." -Foreground Red -} -#> - -#Package Printer Files for Win32 App Deployment -$IntuneWinAppUtil = ".\IntuneWinAppUtil.exe" -$SourcePath = ".\ExportedPrinters" -$PrinterFolders = Get-Childitem $SourcePath -Directory - -foreach ($PrinterFolder in $PrinterFolders) { - $setupFolder = $PrinterFolder.FullName - $printerName = $PrinterFolder.Name - $setupFile = "install.ps1" - $setupPath = Join-Path $setupFolder $setupFile - - if (-not (Test-Path $setupPath)) { - Write-Warning "No install.ps1 in $setupFolder - skipping" - continue - } - - Write-Host "Packaging $printerName for Intune deployment..." -ForegroundColor Cyan - & $IntuneWinAppUtil -c $setupFolder -s $setupFile -o $setupFolder -q - Write-Host "Successfully Created .intunewin for $printername" -ForegroundColor Green -} - -$runuploadscript = Read-Host "**All printers & drivers have been exported and packaged for Intune upload. Do you want to upload these printers now?** (Type Y or N and press enter)" -$runuploadscript = $runuploadscript.Trim().ToUpper() -If ($runuploadscript.Trim().ToUpper() -eq "Y") { - Write-Host "User entered $runuploadscript - running script to upload printers to Intune" -ForegroundColor Yellow - Start-Sleep 2 - & .\UploadIntuneWinPrinters.ps1 -} -else { - Write-Host "User entered $runuploadscript - ending script" -ForegroundColor Yellow -} \ No newline at end of file From de48d2fd272c3fd773b26073254d622f4ba698ed Mon Sep 17 00:00:00 2001 From: SaltySOMAdmin <157048676+SaltySOMAdmin@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:14:12 -0500 Subject: [PATCH 3/3] Update PackageMyPrinters.ps1 --- PackageMyPrinters.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PackageMyPrinters.ps1 b/PackageMyPrinters.ps1 index 0e5df12..d57959b 100644 --- a/PackageMyPrinters.ps1 +++ b/PackageMyPrinters.ps1 @@ -1,3 +1,4 @@ +Set-Location -Path $PSScriptRoot #Log Dir $LogDir = ".\Logs" New-Item -ItemType Directory -Path $LogDir -Force | Out-Null @@ -15,6 +16,7 @@ if (-not $SelectedPrinters) { return } +# Get default B&W Flag $defaultbw = Read-Host "**Do you want to default printers to black and white? (Type Y or N and press enter)" $defaultbw = $defaultbw.Trim().ToUpper() @@ -96,6 +98,7 @@ Copy-Item -Path "$DriverPath\*" -Destination $DriverDir -Recurse $PkgDir = ".\ExportedPrinters\$PrinterName" $InstallPath = Join-Path $PkgDir 'Install.ps1' New-Item -ItemType Directory -Path $PkgDir -Force | Out-Null # in case folder wasn't created yet +Copy-Item -path "$PSScriptRoot\printericon.jpg" -Destination $PkgDir If ($defaultbw.Trim().ToUpper() -eq "Y") { $install = @" # Auto-generated installer for: $PrinterName