PowerShell-script installerer nettverksskriver automatisk fra lokal mappe

🖨️ Installer nettverksskriver fra lokal mappe med PowerShell

Har du driverne liggende lokalt – enten som ZIP-fil eller utpakkede filer – men vil unngå å installere skriveren manuelt på hver PC? Dette PowerShell-scriptet tar seg av hele jobben automatisk, finner INF-filer selv, lar deg velge riktig driver fra en liste og genererer et selvforsynt installasjonsscript som fungerer uansett hvor det kopieres.

⚙️ Hva gjør scriptet?

  1. Spør om du vil bruke en lokal mappe eller ZIP-fil som driverkilde
  2. Validerer at stien eksisterer og at filen er en gyldig ZIP hvis det er valgt
  3. Spør om IP-adresse og skrivernavn
  4. Rydder opp eksisterende skrivere og porter på samme IP
  5. Pakker ut ZIP-filen hvis det er valgt, eller bruker mappen direkte
  6. Finner automatisk alle INF-filer og leser ut tilgjengelige drivernavn
  7. Lar deg velge hvilken driver som skal installeres
  8. Installerer driver, port og skriver
  9. Logger alt til en loggfil oppkalt etter skrivernavnet
  10. Spør om du vil generere et ferdig selvforsynt script og ZIP for gjenbruk

🌐 Finn IP-adressen til skriveren

Før du kjører scriptet trenger du IP-adressen til skriveren på nettverket – og vi anbefaler sterkt at skriveren har en fast IP-adresse før du installerer den.

👉 Les vår komplette guide: Fast IP-adresse på nettverksskriver – hvorfor og hvordan

Der finner du fire metoder for å finne IP-adressen, inkludert et PowerShell-script som skanner nettverket automatisk – pluss en grundig forklaring på hvorfor fast IP er viktig og hvordan du setter det opp.

📄 Fullt script

PS! husk «Set-ExecutionPolicy Bypass» i powershell for å kunne kjøre skript som ikke er signert.

					# =============================================================================
# Powershell script fra Logje Data AS
# Install-NetworkPrinter-Local.ps1
# Installerer nettverksskriver fra lokal mappe eller ZIP-fil
# =============================================================================

# ----- Variabler (faste) ----
$TempDir = "C:\temp\skriver"

# ----- Spør etter variabler ----
Write-Host "=== Nettverksskriver installasjon ===" -ForegroundColor Cyan

# ----- Velg kilde ----
Write-Host "`nVelg driverkilde:" -ForegroundColor Cyan
Write-Host "  [1] Lokal mappe med utpakkede filer"
Write-Host "  [2] Lokal ZIP-fil"

do {
    $sourceChoice = Read-Host "Velg (1 eller 2)"
} while ($sourceChoice -notin @("1", "2"))

switch ($sourceChoice) {
    "1" {
        do {
            $driverSource = Read-Host "Sti til mappe med driverfiler (f.eks. C:\drivere\skriver)"
            if (-not (Test-Path $driverSource)) { Write-Warning "Mappen finnes ikke. Prøv igjen." }
        } while (-not (Test-Path $driverSource))
        $useZip = $false
    }
    "2" {
        do {
            $driverSource = Read-Host "Sti til ZIP-fil (f.eks. C:\drivere\skriver.zip)"
            if (-not (Test-Path $driverSource)) { Write-Warning "Filen finnes ikke. Prøv igjen." }
            elseif ($driverSource -notmatch "\.zip$") { Write-Warning "Filen må være en ZIP-fil." }
        } while (-not (Test-Path $driverSource) -or $driverSource -notmatch "\.zip$")
        $useZip = $true
    }
}

do {
    $Printer1_IP = Read-Host "Skriv inn IP-adresse til skriver"
    $validIP = $Printer1_IP -match "^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$"
    if (-not $validIP) { Write-Warning "Ugyldig IP-adresse. Prøv igjen." }
} while (-not $validIP)

do {
    $Printer_Name = Read-Host "Skriv inn skrivernavn (vises i Windows)"
} while ($Printer_Name -eq "")

# ----- Opprett temp-mappe og start logging ----
if (-not (Test-Path $TempDir)) {
    New-Item -ItemType Directory -Path $TempDir | Out-Null
}

$logFile = "$TempDir\$($Printer_Name -replace '\s+', '_').log"
Start-Transcript -Path $logFile -Append
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starter installasjon av $Printer_Name"

# ----- Cleanup eksisterende installasjon ----
Write-Host "Sjekker etter eksisterende skriver på $Printer1_IP..."
$printers = Get-Printer
$targetPrinters = $printers | Where-Object {
    $port = Get-PrinterPort -Name $_.PortName -ErrorAction SilentlyContinue
    $port.PrinterHostAddress -eq $Printer1_IP
}
foreach ($printer in $targetPrinters) {
    Write-Host "Fjerner skriver: $($printer.Name)"
    Remove-Printer -Name $printer.Name
}
$portToRemove = Get-PrinterPort | Where-Object { $_.PrinterHostAddress -eq $Printer1_IP }
if ($portToRemove) {
    Remove-PrinterPort -Name $portToRemove.Name
    Write-Host "Fjernet port: $($portToRemove.Name)"
}

# ----- Håndter driverkilde ----
if ($useZip) {
    $extractPath = "$TempDir\extracted"
    try {
        Write-Host "Pakker ut ZIP-fil fra $driverSource..."
        Expand-Archive -Path $driverSource -DestinationPath $extractPath -Force
        Write-Host "Utpakking fullført."
        $searchPath = $extractPath
    } catch {
        Write-Error "Utpakking feilet: $_"
        Stop-Transcript; exit 1
    }
} else {
    Write-Host "Bruker driverfiler fra $driverSource..."
    $searchPath = $driverSource
}

# ----- Finn INF-filer automatisk ----
Write-Host "`nSøker etter INF-filer i $searchPath..." -ForegroundColor Cyan
$infFiles = Get-ChildItem -Path $searchPath -Filter "*.inf" -Recurse

if ($infFiles.Count -eq 0) {
    Write-Error "Ingen INF-filer funnet i $searchPath. Sjekk at driverfilene er på plass."
    Stop-Transcript; exit 1
}

# ----- Les alle drivernavn fra INF-filene ----
$allDrivers = @()

foreach ($inf in $infFiles) {
    $content = Get-Content $inf.FullName -ErrorAction SilentlyContinue

    foreach ($line in $content) {
        if ($line -match '^"([^"]+)"\s*=') {
            $driverName = $matches[1].Trim()
            if ($driverName -ne "") {
                $allDrivers += [PSCustomObject]@{
                    Driver  = $driverName
                    INFFile = $inf.FullName
                }
            }
        }
    }
}

$allDrivers = $allDrivers | Sort-Object Driver -Unique

if ($allDrivers.Count -eq 0) {
    Write-Error "Ingen drivernavn funnet i INF-filene. Sjekk INF-filene manuelt."
    Stop-Transcript; exit 1
}

# ----- Vis liste og la bruker velge driver ----
Write-Host "`nFølgende drivere ble funnet:" -ForegroundColor Cyan
for ($i = 0; $i -lt $allDrivers.Count; $i++) {
    Write-Host "  [$($i + 1)] $($allDrivers[$i].Driver)" -ForegroundColor White
    Write-Host "       INF: $($allDrivers[$i].INFFile)" -ForegroundColor DarkGray
}

do {
    $selection = Read-Host "`nVelg drivermodell (skriv inn nummer)"
    $selectionInt = $selection -as [int]
} while ($selectionInt -lt 1 -or $selectionInt -gt $allDrivers.Count)

$selectedDriver = $allDrivers[$selectionInt - 1]
$Driver_Name    = $selectedDriver.Driver
$inf_File       = $selectedDriver.INFFile

Write-Host "`nValgt driver : $Driver_Name" -ForegroundColor Green
Write-Host "INF-fil      : $inf_File" -ForegroundColor Green

# ----- Installer driver og skriver ----
try {
    Write-Host "`nInstallerer driver med pnputil..."
    pnputil.exe /add-driver "$inf_File" /install

    Write-Host "Legger til printerdriver: $Driver_Name"
    Add-PrinterDriver -Name $Driver_Name

    Write-Host "Legger til printerport: $Printer1_IP"
    Add-PrinterPort -Name $Printer1_IP -PrinterHostAddress $Printer1_IP

    Write-Host "Legger til skriver: $Printer_Name"
    Add-Printer -Name $Printer_Name -DriverName $Driver_Name -PortName $Printer1_IP

    Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Installasjon fullført: $Printer_Name" -ForegroundColor Green
} catch {
    Write-Error "Installasjon feilet: $_"
    exit 1
} finally {
    if ($useZip -and (Test-Path $extractPath)) {
        Write-Host "Rydder opp midlertidige filer..."
        Remove-Item -Path $extractPath -Recurse -Force
    }
    Stop-Transcript
}

# ----- Generer eget script med hardkodede valg ----
$generateScript = Read-Host "`nVil du generere et ferdig script med disse valgene? (j/n)"

if ($generateScript -eq "j") {
    $scriptFileBaseName = $Printer_Name -replace '\s+', '_'
    $scriptFileName     = "${scriptFileBaseName}_install.ps1"
    $bundleZipName      = "${scriptFileBaseName}_driver.zip"

    do {
        $outputFolder = Read-Host "Hvor skal script og ZIP lagres? (standard: C:\temp\skriver)"
        if ($outputFolder -eq "") { $outputFolder = "C:\temp\skriver" }
    } while ($outputFolder -eq "")

    if (-not (Test-Path $outputFolder)) {
        New-Item -ItemType Directory -Path $outputFolder | Out-Null
    }

    $scriptPath    = "$outputFolder\$scriptFileName"
    $bundleZipPath = "$outputFolder\$bundleZipName"

    Write-Host "`nLager ZIP-fil av driverfilene..."
    try {
        if ($useZip) {
            Copy-Item -Path $driverSource -Destination $bundleZipPath -Force
            Write-Host "Kopierte eksisterende ZIP til: $bundleZipPath" -ForegroundColor Green
        } else {
            Compress-Archive -Path "$driverSource\*" -DestinationPath $bundleZipPath -Force
            Write-Host "Laget ny ZIP fra mappe: $bundleZipPath" -ForegroundColor Green
        }
    } catch {
        Write-Error "Kunne ikke lage ZIP-fil: $_"
        exit 1
    }

    $generatedScript = @"
# =============================================================================
# $scriptFileName
# Automatisk generert av Install-NetworkPrinter-Local.ps1
# Generert: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
#
# BRUK: Legg denne filen og '$bundleZipName' i samme mappe.
#       Kopier begge filene til ønsket maskin eller delt mappe og kjør scriptet.
# =============================================================================

`$Driver_Name  = "$Driver_Name"
`$Printer_Name = "$Printer_Name"
`$inf_File     = "$inf_File"
`$Printer1_IP  = "$Printer1_IP"
`$TempDir      = "C:\temp\skriver"
`$extractPath  = "`$TempDir\extracted"
`$logFile      = "`$TempDir\$($Printer_Name -replace '\s+', '_').log"

`$scriptDir   = Split-Path -Parent `$MyInvocation.MyCommand.Path
`$zipFileName = "$bundleZipName"
`$zipPath     = Join-Path `$scriptDir `$zipFileName

if (-not (Test-Path `$zipPath)) {
    Write-Error "Finner ikke '$bundleZipName' i samme mappe som scriptet (`$scriptDir). Legg ZIP-filen ved siden av scriptet og prøv igjen."
    exit 1
}

if (-not (Test-Path `$TempDir)) {
    New-Item -ItemType Directory -Path `$TempDir | Out-Null
}

Start-Transcript -Path `$logFile -Append
Write-Host "`$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starter installasjon av `$Printer_Name"

`$printers = Get-Printer
`$targetPrinters = `$printers | Where-Object {
    `$port = Get-PrinterPort -Name `$_.PortName -ErrorAction SilentlyContinue
    `$port.PrinterHostAddress -eq `$Printer1_IP
}
foreach (`$printer in `$targetPrinters) {
    Write-Host "Fjerner skriver: `$(`$printer.Name)"
    Remove-Printer -Name `$printer.Name
}
`$portToRemove = Get-PrinterPort | Where-Object { `$_.PrinterHostAddress -eq `$Printer1_IP }
if (`$portToRemove) {
    Remove-PrinterPort -Name `$portToRemove.Name
    Write-Host "Fjernet port: `$(`$portToRemove.Name)"
}

try {
    Write-Host "Pakker ut driverfiler fra `$zipPath..."
    Expand-Archive -Path `$zipPath -DestinationPath `$extractPath -Force
    Write-Host "Utpakking fullført."
} catch {
    Write-Error "Utpakking feilet: `$_"
    Stop-Transcript; exit 1
}

try {
    Write-Host "Installerer driver med pnputil..."
    pnputil.exe /add-driver "`$inf_File" /install
    Add-PrinterDriver -Name `$Driver_Name
    Add-PrinterPort -Name `$Printer1_IP -PrinterHostAddress `$Printer1_IP
    Add-Printer -Name `$Printer_Name -DriverName `$Driver_Name -PortName `$Printer1_IP
    Write-Host "`$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Installasjon fullført: `$Printer_Name" -ForegroundColor Green
} catch {
    Write-Error "Installasjon feilet: `$_"
    exit 1
} finally {
    if (Test-Path `$extractPath) {
        Write-Host "Rydder opp midlertidige filer..."
        Remove-Item -Path `$extractPath -Recurse -Force
    }
    Stop-Transcript
}

exit 0
"@

    try {
        $generatedScript | Out-File -FilePath $scriptPath -Encoding UTF8
        Write-Host "`n=======================================" -ForegroundColor Cyan
        Write-Host "Ferdig! To filer er klare i: $outputFolder" -ForegroundColor Green
        Write-Host "  📄 $scriptFileName" -ForegroundColor White
        Write-Host "  📦 $bundleZipName" -ForegroundColor White
        Write-Host "=======================================" -ForegroundColor Cyan
        Write-Host "Kopier begge filene til ønsket mappe eller nettverksdisk." -ForegroundColor Cyan
        Write-Host "Scriptet finner ZIP-filen automatisk så lenge de ligger i samme mappe." -ForegroundColor Cyan
    } catch {
        Write-Error "Kunne ikke lagre scriptet: $_"
    }
}

exit 0
				

🔍 Steg-for-steg forklaring

📌 Del 1 – Velg driverkilde

					Write-Host "  [1] Lokal mappe med utpakkede filer"
Write-Host "  [2] Lokal ZIP-fil"
do {
    $sourceChoice = Read-Host "Velg (1 eller 2)"
} while ($sourceChoice -notin @("1", "2"))
				

Scriptet starter med å spørre hvor driverfilene finnes. Velger du mappe brukes filene direkte uten utpakking. Velger du ZIP pakkes den ut til en midlertidig mappe først. Begge valg valideres – scriptet sjekker at stien eksisterer og at ZIP-filen har riktig endelse.

💬 Del 2 – IP-validering og skrivernavn

					$validIP = $Printer1_IP -match "^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$"
				

IP-adressen valideres med et strengt regex-mønster som sikrer at alle fire oktetter er gyldige tall mellom 0 og 255. Vet du ikke IP-adressen til skriveren?
👉 Se vår guide: Fast IP-adresse på nettverksskriver – hvorfor og hvordan

📋 Del 3 – Loggfil oppkalt etter skrivernavnet

					$logFile = "$TempDir\$($Printer_Name -replace '\s+', '_').log"
Start-Transcript -Path $logFile -Append
				

Loggfilen får automatisk samme navn som skriveren du valgte, med mellomrom byttet ut med understrek. Velger du «Resepsjon Skriver» får du Resepsjon_Skriver.log i temp-mappen.

🧹 Del 4 – Cleanup av eksisterende installasjon

					$targetPrinters = $printers | Where-Object {
    $port = Get-PrinterPort -Name $_.PortName -ErrorAction SilentlyContinue
    $port.PrinterHostAddress -eq $Printer1_IP
}
				

Scriptet sjekker om det allerede finnes en skriver registrert på samme IP og fjerner den automatisk – sammen med tilhørende port. Du får alltid en ren installasjon uten konflikter.

📦 Del 5 – Håndter driverkilde

					if ($useZip) {
    $extractPath = "$TempDir\extracted"
    Expand-Archive -Path $driverSource -DestinationPath $extractPath -Force
    $searchPath = $extractPath
} else {
    $searchPath = $driverSource
}
				

Basert på valget ditt bruker scriptet enten den utpakkede mappen eller den lokale mappen direkte som søkesti for INF-filer. Brukes ZIP ryddes den utpakkede mappen opp i finally-blokken etterpå. Brukes en lokal mappe røres ingen filer.

🔍 Del 6 – Automatisk søk og parsing av INF-filer

					$infFiles = Get-ChildItem -Path $searchPath -Filter "*.inf" -Recurse
				

Scriptet søker rekursivt gjennom hele mappestrukturen etter .inf-filer og leser ut alle drivernavn som matcher standardformatet "Drivernavnet" = i INF-filene. Duplikater fjernes og listen sorteres alfabetisk. Du trenger ikke vite filnavnet på forhånd.

🖱️ Del 7 – Interaktiv drivervelgerrsing av INF-filer

					for ($i = 0; $i -lt $allDrivers.Count; $i++) {
    Write-Host "  [$($i + 1)] $($allDrivers[$i].Driver)" -ForegroundColor White
    Write-Host "       INF: $($allDrivers[$i].INFFile)" -ForegroundColor DarkGray
}
				

Du får en nummerert liste over alle tilgjengelige drivere med tilhørende INF-fil og velger med et tall. Ugyldig input gjentar spørsmålet.

🖨️ Del 8 – Installasjon i tre steg

					pnputil.exe /add-driver "$inf_File" /install
Add-PrinterDriver -Name $Driver_Name
Add-PrinterPort -Name $Printer1_IP -PrinterHostAddress $Printer1_IP
Add-Printer -Name $Printer_Name -DriverName $Driver_Name -PortName $Printer1_IP
				

pnputil.exe registrerer INF-filen i Windows driver store. Add-PrinterDriver legger til driveren. Add-PrinterPort og Add-Printer oppretter port og skriver med riktig IP og drivernavn.

🤖 Del 9 – Generer selvforsynt script og ZIP

					$scriptFileBaseName = $Printer_Name -replace '\s+', '_'
$scriptFileName     = "${scriptFileBaseName}_install.ps1"
$bundleZipName      = "${scriptFileBaseName}_driver.zip"
				

Etter fullført installasjon spør scriptet om du vil generere et ferdig pakke bestående av to filer – et .ps1-script og en .zip med driverfilene – begge navngitt etter skrivernavnet du valgte.

Brukte du en mappe pakkes driverfilene automatisk inn i en ny ZIP med Compress-Archive. Brukte du en eksisterende ZIP kopieres den direkte med Copy-Item.

					$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$zipPath   = Join-Path $scriptDir $zipFileName
				

Det genererte scriptet bruker $MyInvocation.MyCommand.Path til å finne sin egen plassering og leter alltid etter ZIP-filen i samme mappe. Du kan kopiere de to filene til en hvilken som helst maskin, nettverksdisk eller delt mappe og scriptet fungerer uten endringer.

Etter generering vises en oppsummering:

					=======================================
Ferdig! To filer er klare i: C:\temp\skriver
  📄 Resepsjon_Skriver_install.ps1
  📦 Resepsjon_Skriver_driver.zip
=======================================
Kopier begge filene til ønsket mappe eller nettverksdisk.
				

⚠️ Advarsel

Scriptet gjør endringer i Windows driver store og skriveroppsett. Test alltid i Microsoft Sandbox eller en virtuell maskin før bruk i produksjon.

📞 Trenger du hjelp?

Vil du automatisere skriverinstallasjon eller annen IT-drift med PowerShell? Ta kontakt med Logje Data AS – vi hjelper deg med skreddersydde løsninger for din bedrift. ✅ Én leverandør. Én kontakt. Full kontroll.