PrinterSwap.psm1

function Start-PrinterServerSwap {
    <#
    .SYNOPSIS
        Run as Admin, then creates a task to install printers in $ENV:USERNAME's profile when they log on after a delay of 2 min.
    .DESCRIPTION
        Assists with installing Migrating local printers to printers of same name as new Print Server by installing all drivers to admin
        then creating a user task to migrate user printers on Log on to Printers of the same name on the new Print Server.
        Can either be run without switches to only install drivers, ran with switches to also install a user task and/or only install the
        user task.
    .EXAMPLE
        PS C:\> Start-PrinterServerSwap -OldPrintServer "ABCPrintServer01" -NewPrintServer "ABCPrintServer02" -TaskUserOrGroup "USRDOM\Domain Users" -CreateUserTask -Confirm:$false -Verbose
        Installs all shared printers from the new print server and created scheduled task to installs user's previous printers on logon after delay.
    .EXAMPLE
        PS C:\> Start-PrinterServerSwap -OldPrintServer "ABCPrintServer01" -NewPrintServer "ABCPrintServer02" -TaskUserOrGroup "USRDOM\Domain Users" -OnlyCreateUserTask -Confirm:$false -Verbose
        Only creates the logon task for users.
    .EXAMPLE
        PS C:\> Start-PrinterServerSwap -OldPrintServer "ABCPrintServer01" -NewPrintServer "ABCPrintServer02" -TaskUserOrGroup "USRDOM\Domain Users" -Confirm:$false -Verbose
        Only installs all shared printers from the new print server.
    .PARAMETER OldPrintServer
    Specify the hostname of the old server. Ex: "Print01"
    .PARAMETER NewPrintServer
    Specify the hostname of the new server. Ex: "Print02"
    .PARAMETER TaskUserOrGroup
    Specifies the username or usergroup(Preferred) to run the task. Ex: Domain\Username
    .PARAMETER CreateUserTask
    Switch to also create the user task. Without the switch, only printers from the new server are installed.
    .PARAMETER OnlyCreateUserTask
    Switch to only create the user task without installing printer drivers.
    .PARAMETER Reset
    Switch to remove local files created by script and any scheduled tasks for starting over.
            Remove-Item "C:\temp\PrintLogs\Add-PrinterTask.ps1" -Force
            Remove-Item "C:\temp\PrintLogs\$($printserver).DriversAdded.txt" -Force
            Remove-Item "$($home)\Saved Games\PrintersAddedCheck.txt" -Force
            Unregister-ScheduledTask -TaskName "Migrate Printers to new Server" -Confirm:$false
    .INPUTS
        System.String
    .OUTPUTS
        Output (if any)
    .NOTES
        Only installs networked printers. Can be run as GPO immediate task for computer or
        can be run directly by loading both functions and then running Start-PrinterServerSwap
        with the appropriate parameters.
        Servernames used as input to create a logon task that
        removes the local printers and installs printers of the same name
        that are found on the new print server. If the new print server has a different share
        name for a printer, it will not be installed and will need to be added manually
        by navigating to the Printer share path "\\<PRNTSVRHostName>\" or through control panel
        if they are shared in active directory.
         
        Logs to C:\temp\PrintLogs.
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'Task not included',
        SupportsShouldProcess = $true,
        ConfirmImpact = 'High'
    )]
    param (
        [Parameter(
            Position = '0',
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [string]
        $OldPrintServer,
        # Parameter help description
        [Parameter(
            Position = '1',
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [string]
        $NewPrintServer,
        # Parameter help description
        [Parameter(
            Position = '2',
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [string]
        $TaskUserOrGroup,
        # Parameter help description
        [Parameter(
            Position = '3',
            ParameterSetName = 'Create User Task',
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true
        )]
        [switch]
        $CreateUserTask,
        # Parameter help description
        [Parameter(
            Position = '3',
            ParameterSetName = 'Only Create User Task',
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true
        )]
        [switch]
        $OnlyCreateUserTask,
        [Parameter(
            Position = '3',
            ParameterSetName = 'Reset',
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true
        )]
        [switch]
        $Reset


    )
    Begin {
        # Check for admin and throw exception if not.
        $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
        if (!($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))) {
            throw "Not Running as admin! Please rerun as administrator!"
        }
        # Create Log Path
        $DirPath = "C:\temp\PrintLogs"
        $DirPathCheck = Test-Path -Path $DirPath
        If (!($DirPathCheck)) {
            Try {
                #If not present then create the dir
                New-Item -ItemType Directory $DirPath -Force
            }
            Catch {
                Write-Output "Directory: $DirPath was not created."
                exit
            }
        }
        if ($reset) {
            Remove-Item "C:\temp\PrintLogs\Add-PrinterTask.ps1" -Force
            Remove-Item "C:\temp\PrintLogs\$($printserver).DriversAdded.txt" -Force
            Remove-Item "$($home)\Saved Games\PrintersAddedCheck.txt" -Force
            Unregister-ScheduledTask -TaskName "Migrate Printers to new Server" -Confirm:$false
            Write-Output "If this was deployed via an `"Immediate Task GPO`", please set the action to `"Remove`" to ensure the scheduled task is stopped." -ForegroundColor Green
            Start-Sleep 20
            Stop-Transcript
            Exit
        }

        # Log commands and input
        Start-Transcript -OutputDirectory C:\temp\PrintLogs -IncludeInvocationHeader -NoClobber
        if(Test-Path "C:\temp\PrintLogs\Add-PrinterTask.ps1"){
            Remove-Item "C:\temp\PrintLogs\Add-PrinterTask.ps1" -Confirm:$false -Force
            Unregister-ScheduledTask -TaskName "Migrate Printers to new Server"  -Confirm:$false

            if (Test-Path -Path "C:\temp\PrintLogs\$($printserver).DriversAdded.txt") {
                Remove-Item "C:\temp\PrintLogs\$($printserver).DriversAdded.txt"
            }
        }
        else{
            if (Test-Path -Path "C:\temp\PrintLogs\$($printserver).DriversAdded.txt") {
                exit
                Stop-Transcript
            }
        }
        Start-Service Spooler
        Set-Service -Name "Spooler" -StartupType Automatic

        Write-Host "OldPrintServer: $OldPrintServer"
        Write-Host "NewPrintServer: $NewPrintServer"
        Write-Host "Task User or Group Name in DOMAIN\USERNAME or DOMAIN\GROUP format: $TaskUserOrGroup"
    } # End Begin
    
    Process {
        # If $OnlyCreateUserTask switch
        if ($OnlyCreateUserTask) {
            # Create Script File for User Task.
            
            Start-CreatePrinterInstallTask -oldpserver $OldPrintServer -newpserver $NewPrintServer -tskusrorgrp $TaskUserOrGroup
            Stop-Transcript
            exit
        } # End Create User Task
        ##########END ONLYCREATEUSERTASK###########
        
        # Install all printers from New Print server locally.
        $printserver = $NewPrintServer
        $notinstalled = @{}
        $notinstalled.PrinterName = @()
            
        Get-Printer -ComputerName $printserver | Where-Object { $_.shared -eq $true } | `
            foreach-object {
            Write-Output "Installing Printer: $($_.Name)"
            try {
                if ($PSCmdlet.ShouldProcess(
                                        ("Overwritting existing Printer {0}" -f $($_.Name)),
                                        ("Would you like to overwrite {0}?" -f $($_.Name)),
                        "Create Printer Prompt")) {
                    Add-Printer -ConnectionName "\\$($printserver)\$($_.Name)" -ErrorVariable ErrorAddPrinter
                }
            }
            Catch {
                $notinstalled.PrinterName += $_.Name
                Write-Output "Failed: Printer $($_.Name) failed to install"
                Write-Output "The Error was: `n"
                $ErrorAddPrinter
            }
            if ($?) {
                Write-Output "Success: Printer $($_.Name) was installed successfully!`n"
            }
        }
        if ($?) {
            "Drivers Added on $((Get-Date).ToString('MM-dd-yyyy-hh-mm-ss'))" | Out-File "C:\temp\PrintLogs\$($printserver).DriversAdded.txt" -NoClobber
            $done = (Get-date).AddMinutes(10)
            Write-Output "Waiting 10 Minutes! Will be done at: $done"
            if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Sleep for 10 min")) {
                Start-Sleep -Seconds 600  
            }
        }
        else {
            Throw "$($_.Exception.Message)"
        }
        
        Write-Output "Printers not installed: `n"
        $notinstalled.PrinterName | Out-File "C:\temp\PrintLogs\$($printserver).Notinstalled.txt" -NoClobber
    } # End Process
    End {
        # Switch to also create a task to find and install printers with the same name on the new print server.
        if ($CreateUserTask) {
            # Create Script File for User Task.
            try {
                if ($PSCmdlet.ShouldProcess($OldPrintServer, $NewPrintServer, $TaskUserOrGroup)) {
                    Start-CreatePrinterInstallTask -oldpserver $OldPrintServer -newpserver $NewPrintServer -tskusrorgrp $TaskUserOrGroup
                    
                }
            }
            catch {
                Throw "$($_.Exception.Message)"
            }
            
        } # End CreateUserTask
        else {
            Write-Output "Installed Printers on new Print Server. User printer task has not been created"
        }
        Stop-Transcript
    } # End

}

function Start-CreatePrinterInstallTask {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string]
        $OldPServer,
        [Parameter()]
        [string]
        $NewPServer,
        [Parameter()]
        [string]
        $tskUsrOrGrp
    )
$scripts = {
Start-Transcript -OutputDirectory C:\temp\PrintLogs -IncludeInvocationHeader -NoClobber
if (Test-Path -Path "$($home)\Saved Games\PrintersAddedCheck.txt" ) {
    exit
}
$OldPrintServer = "oldpserver"
$NewPrintServer = "newpserver"
$waittxt = "Please wait for this to complete! Click here and press enter if it takes more than 10 min!"
$migratingtxt = "Migrating your printers from $OldPrintServer to $NewPrintServer for user: " 
Write-Host $migratingtxt -ForegroundColor Yellow
Write-Host "User: $($env:USERNAME)"
Write-Host $waittxt -ForegroundColor Green
        
try {
    # Get Printers of connection type "Connection"
    $MappedPrinters = Get-Printer | Where-Object { $_.type -eq "Connection" } 
}
catch {
    Write-Output "Could not connect to printer. The Error was: `n"
    Throw "$($_.Exception.Message)"
}
Write-Host "Successfully Connected to local printer!" -ForegroundColor Green
        
$path = "C:\temp\PrintLogs\OriginalPrinters.$env:USERNAME.$((Get-Date).ToString('MM-dd-yyyy-hh-mm-ss')).csv"
$xmlpath = "C:\temp\PrintLogs\OriginalPrinters.$env:USERNAME.$((Get-Date).ToString('MM-dd-yyyy-hh-mm-ss')).xml"
# Log initial values of printers per user.
$MappedPrinters | Export-CSV -Path $path -NoTypeInformation
$MappedPrinters | Export-Clixml -Path $xmlpath
            
Foreach ($Printer in $MappedPrinters) {
    $printername = $printer | Select-Object -ExpandProperty Name
    $printername
    If ($PrinterName -Like "*$OldPrintServer*") {
        Write-Host "Found Printer `"$PrinterName`" to be connected!" -ForegroundColor Green
        $PrinterNewName = $PrinterName -Replace "$OldPrintServer", "$NewPrintServer"
        Add-printer -ConnectionName $PrinterNewName -ErrorAction SilentlyContinue
        if ($?) {
            Remove-Printer -Name $printername
            Write-Host "Removed Printer `"$printername`" from your computer." `
            -ForegroundColor Yellow -BackgroundColor Blue
        }
    }
}
# Create File for verification on future runs
if ($?) {
    "Success" | Out-File "$($home)\Saved Games\PrintersAddedCheck.txt"
    Stop-Transcript
}

}
    
    # Resume Script Context
    # Output Scripts to File
    $scripts | Out-File -FilePath "C:\temp\PrintLogs\Add-PrinterTask.ps1" -Encoding utf8
    
    # Replace values in file with values from Parameters.
    ((Get-Content -path "C:\temp\PrintLogs\Add-PrinterTask.ps1" -Raw) -replace 'oldpserver', $($OldPrintServer)) | `
        Set-Content -Path "C:\temp\PrintLogs\Add-PrinterTask.ps1"
    ((Get-Content -path "C:\temp\PrintLogs\Add-PrinterTask.ps1" -Raw) -replace 'newpserver', $($NewPrintServer)) | `
        Set-Content -Path "C:\temp\PrintLogs\Add-PrinterTask.ps1"

    # Create User Task
    $jobName = "Migrate Printers to new Server"
    $script = '-NoLogo -ExecutionPolicy Bypass -File C:\temp\PrintLogs\Add-PrinterTask.ps1'
    $action = New-ScheduledTaskAction -Execute "$pshome\powershell.exe" -Argument  $script
    $taskPrincipal = New-ScheduledTaskPrincipal -GroupId $tskUsrOrGrp -RunLevel Highest
    $timeSpan = New-TimeSpan -Minutes 2
    $trigger = New-ScheduledTaskTrigger -AtLogOn -RandomDelay $timeSpan
    $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd
    Register-ScheduledTask -TaskName $jobName -Action $action -Principal $taskPrincipal -Settings $settings -Trigger $trigger 
}