From 2bf216bcc211fa726e51c7dfe8907f2af9e646cb Mon Sep 17 00:00:00 2001 From: GCH Date: Fri, 22 May 2026 10:34:36 +0200 Subject: [PATCH 1/4] Upload af RDPSign fra arbejde-noter repo --- README.md | 191 ++++++++++++++++++++++++++++++++++++ app/Clearsigning.ps1 | 58 +++++++++++ app/Detect.ps1 | 69 +++++++++++++ app/Install.ps1 | 172 +++++++++++++++++++++++++++++++++ app/SignOnly.ps1 | 150 +++++++++++++++++++++++++++++ app/SignOnly_detect.ps1 | 61 ++++++++++++ app/Uninstall.ps1 | 60 ++++++++++++ app/sandbox.ps1 | 208 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 969 insertions(+) create mode 100644 app/Clearsigning.ps1 create mode 100644 app/Detect.ps1 create mode 100644 app/Install.ps1 create mode 100644 app/SignOnly.ps1 create mode 100644 app/SignOnly_detect.ps1 create mode 100644 app/Uninstall.ps1 create mode 100644 app/sandbox.ps1 diff --git a/README.md b/README.md index e69de29..e92f033 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,191 @@ +# RDP - IntuneWin Pakke + +> Denne pakke installerer og signerer RDP-genveje på skrivebordet via et selvsigneret certifikat, så brugerne ikke får en sikkerhedsadvarsel ved åbning. +> Som standard arbejder alle scripts mod det **offentlige skrivebord** (`C:\Users\Public\Desktop`). +> Brug `-AllUsers` switchen for at køre mod alle brugeres individuelle skriveborde i stedet. + +--- + +## Indhold + +- [Pakkens indhold](#pakkens-indhold) +- [Intune App Konfiguration](#intune-app-konfiguration) +- [Hvad Install.ps1 gør](#hvad-installps1-gør) +- [AllUsers Switch](#allusers-switch) +- [Registry-ændringer](#registry-ændringer) +- [Logning og fejlfinding](#logning-og-fejlfinding) +- [SignOnly Intune App Konfiguration](#signonly-intune-app-konfiguration) +- [Øvrige scripts i pakken](#øvrige-scripts-i-pakken) + +--- + +## Pakkens indhold + +| Fil | Formål | +|-----|--------| +| `Install.ps1` | Kopierer RDP-filer til skrivebord(e), opretter selvsigneret certifikat og signerer alle RDP-filer. Understøtter `-AllUsers` switch. | +| `Detect.ps1` | Registrerer om alle RDP-filer fra pakken er til stede på skrivebord(e). Understøtter `-AllUsers` switch. | +| `Uninstall.ps1` | Fjerner RDP-filer fra skrivebord(e). Understøtter `-AllUsers` switch. | +| `SignOnly.ps1` | Signerer eksisterende RDP-filer på skrivebord(e) — ingen filkopiering. Understøtter `-AllUsers` switch. | +| `SignOnly_detect.ps1` | Registrerer om certifikat er til stede og alle RDP-filer på skrivebord(e) er signerede. Understøtter `-AllUsers` switch. | +| `Clearsigning.ps1` | Fjerner signaturer fra RDP-filer og rydder op i certifikat og registry (til oprydning/debug). Understøtter `-AllUsers` switch. | +| `sandbox.ps1` | Kombineret install + detect script til lokal sandkasse-test. Understøtter `-AllUsers` switch. | +| `rdp-files\*.rdp` | Kilde-RDP-filer der installeres på skrivebord(e) | + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## Intune App Konfiguration + +### Program +- **Installationskommando:** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1` +- **Installationskommando (alle brugeres skriveborde):** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1 -AllUsers` +- **Afinstallationskommando:** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Uninstall.ps1` +- **Afinstallationskommando (alle brugeres skriveborde):** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Uninstall.ps1 -AllUsers` +- **Installationsadfærd:** System + +### Registreringsregel +Brug et brugerdefineret registreringsscript: +- **Scriptfil:** `Detect.ps1` +- **Kør script som 32-bit proces på 64-bit klienter:** Nej +- **Gennemtving scriptsignaturkontrol:** Nej + +Registreringslogik: +- Uden `-AllUsers`: tjekker at alle `.rdp`-filer er til stede på det offentlige skrivebord (`C:\Users\Public\Desktop`) +- Med `-AllUsers`: tjekker alle brugeres skriveborde under `C:\Users\` +- Returnerer `exit 0` = installeret +- Returnerer `exit 1` = ikke installeret + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## Hvad Install.ps1 gør + +1. Finder målskrivebord(e) — offentligt skrivebord som standard, alle brugeres skriveborde med `-AllUsers` +2. Kopierer alle `.rdp`-filer fra `.\rdp-files\` til de fundne skrivebord(e) +3. Søger efter eksisterende selvsigneret certifikat (`CN=RDPSign`) i `Cert:\LocalMachine\My` +4. Opretter et nyt selvsigneret kodesigneringscertifikat hvis intet findes (gyldigt i 25 år, ikke-eksporterbart) +5. Tilføjer certifikatet til `Trusted Root` og `Trusted Publishers` i den lokale maskines certifikatstore +6. Tilføjer certifikatets thumbprint til registry-nøglen `TrustedCertThumbprints` +7. Signerer alle `.rdp`-filer på skrivebord(e) med `rdpsign.exe /sha256` +8. Sætter `RedirectionWarningDialogVersion = 1` i registry for at undertrykke RDP-advarselsdialoger + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## AllUsers Switch + +Alle scripts understøtter `-AllUsers` switchen. Som standard — uden `-AllUsers` — køres alle scripts kun mod det **offentlige skrivebord** (`C:\Users\Public\Desktop`). Når `-AllUsers` angives, itererer scriptet i stedet over alle brugerprofiler under `C:\Users\` og behandler hver brugers `Desktop`-mappe. + +```powershell +# Kun offentligt skrivebord (standard) +.\Install.ps1 + +# Alle brugeres skriveborde +.\Install.ps1 -AllUsers +``` + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## Registry-ændringer + +| Sti | Værdi | Type | Data | +|-----|-------|------|------| +| `HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services` | `TrustedCertThumbprints` | String | Certifikatets thumbprint | +| `HKLM\Software\Policies\Microsoft\Windows NT\Terminal Services\Client` | `RedirectionWarningDialogVersion` | DWORD | `1` | + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## Logning og fejlfinding + +| Script | Logfil | +|--------|--------| +| `Install.ps1` | `C:\Intune\DesktopShortcuts.log` | +| `Detect.ps1` | `C:\Intune\DesktopShortcuts.log` | +| `Uninstall.ps1` | `C:\Intune\DesktopShortcuts.log` | +| `SignOnly.ps1` | `C:\Intune\RDPSign.log` | + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## SignOnly Intune App Konfiguration + +### Program +- **Installationskommando:** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1` +- **Installationskommando (alle brugeres skriveborde):** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1 -AllUsers` +- **Afinstallationskommando:** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1` +- **Afinstallationskommando (alle brugeres skriveborde):** + `powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1 -AllUsers` +- **Installationsadfærd:** System + +### Registreringsregel +Brug et brugerdefineret registreringsscript: +- **Scriptfil:** `SignOnly_detect.ps1` +- **Kør script som 32-bit proces på 64-bit klienter:** Nej +- **Gennemtving scriptsignaturkontrol:** Nej + +Registreringslogik: +- Tjekker at `CN=RDPSign`-certifikatet findes i `My`, `Root` og `TrustedPublisher` stores +- Tjekker at thumbprint er til stede i registry +- Uden `-AllUsers`: tjekker at alle `.rdp`-filer på det offentlige skrivebord er signerede +- Med `-AllUsers`: tjekker alle `.rdp`-filer på tværs af alle brugeres skriveborde +- Returnerer `exit 0` + `"Detected"` = installeret +- Returnerer `exit 1` = ikke installeret + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) + +--- + +## Øvrige scripts i pakken + +> **Bemærk:** Alle PowerShell-scripts er pakket ind i samme IntuneWin-pakke. Det betyder at man altid kan kalde på et vilkårligt script direkte fra Intune eller manuelt, f.eks.: +> +> ```powershell +> powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1 +> powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1 -AllUsers +> powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1 +> powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1 -AllUsers +> powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1 +> powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1 -AllUsers +> ``` +> osv. for alle scripts i pakken. + +### `SignOnly.ps1` +Signerer alle eksisterende `.rdp`-filer på skrivebord(e) uden at kopiere filer. Nyttigt til gensignering efter en opdatering eller hvis filer allerede er installeret. Kør som administrator. Understøtter `-AllUsers` switch. + +### `SignOnly_detect.ps1` +Registreringsscript til brug med `SignOnly.ps1` som Intune-pakke. Tjekker: +- Certifikat findes i `My`, `Root` og `TrustedPublisher` stores +- Thumbprint er til stede i registry +- Alle `.rdp`-filer på skrivebord(e) indeholder en gyldig signatur + +Understøtter `-AllUsers` switch. + +### `Clearsigning.ps1` +Fjerner alle signeringsartefakter. Nyttigt til test eller oprydning. Kør som administrator. Understøtter `-AllUsers` switch. +- Fjerner `signscope`- og `signature`-linjer fra alle `.rdp`-filer på skrivebord(e) +- Fjerner `CN=RDPSign`-certifikatet fra `My`, `Root` og `TrustedPublisher` stores +- Fjerner `TrustedCertThumbprints` fra registry +- Fjerner `RedirectionWarningDialogVersion` fra registry + +### `sandbox.ps1` +Kombinerer install og detect i ét script til lokal sandkasse-test. Understøtter `-AllUsers` switch. +Kør fra mappen der indeholder `rdp-files\` som administrator. +Output skrives til både konsollen og `C:\Intune\DesktopShortcuts.log`. + +[↑ Tilbage til toppen](#rdp---intunewin-pakke) diff --git a/app/Clearsigning.ps1 b/app/Clearsigning.ps1 new file mode 100644 index 0000000..1b57cf0 --- /dev/null +++ b/app/Clearsigning.ps1 @@ -0,0 +1,58 @@ +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to remove signatures from RDP +# files on all user desktops instead of only the public +# desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, clears signing on public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +$certSubject = "CN=RDPSign" + +# 1. Unsign RDP files +foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" + foreach ($file in $rdpFiles) { + $content = Get-Content $file.FullName + $cleaned = $content | Where-Object { $_ -notmatch "^signscope:s:" -and $_ -notmatch "^signature:s:" } + $cleaned | Set-Content $file.FullName -Encoding Unicode + Write-Host "Unsigned: $($file.Name) on $desktopPath" + } +} + +# 2. Remove certificate from all stores +foreach ($storeName in @("My", "Root", "TrustedPublisher")) { + $store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeName, "LocalMachine") + $store.Open("ReadWrite") + $certs = $store.Certificates | Where-Object { $_.Subject -eq $certSubject } + foreach ($cert in $certs) { + $store.Remove($cert) + Write-Host "Removed certificate from store: $storeName" + } + $store.Close() +} + +# 3. Remove thumbprint from registry +$gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" +Remove-ItemProperty -Path $gpoPath -Name "TrustedCertThumbprints" -ErrorAction SilentlyContinue +Write-Host "Removed TrustedCertThumbprints" + +# 4. Remove RedirectionWarningDialogVersion +$clientPath = "HKLM:\Software\Policies\Microsoft\Windows NT\Terminal Services\Client" +Remove-ItemProperty -Path $clientPath -Name "RedirectionWarningDialogVersion" -ErrorAction SilentlyContinue +Write-Host "Removed RedirectionWarningDialogVersion" diff --git a/app/Detect.ps1 b/app/Detect.ps1 new file mode 100644 index 0000000..04774f1 --- /dev/null +++ b/app/Detect.ps1 @@ -0,0 +1,69 @@ +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to check all user desktops +# instead of only the public desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, checks public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "DesktopShortcuts.log" + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +try { + $desktopPaths = Get-DesktopPaths + $allFound = $true + + foreach ($desktopPath in $desktopPaths) { + $rdpFiles = Get-ChildItem -Path "$desktopPath\*.rdp" -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "DETECT [FAIL]: No .rdp files found on desktop: $desktopPath" + $allFound = $false + continue + } + + foreach ($file in $rdpFiles) { + if (-not (Test-Path (Join-Path $desktopPath $file.Name))) { + Write-Log "DETECT [FAIL]: Missing: $($file.Name) on $desktopPath" + $allFound = $false + } + } + } + + if ($allFound) { + Write-Log "DETECT [OK]: All .rdp files found on all desktop(s)" + exit 0 + } else { + exit 1 + } +} catch { + Write-Log "Detect error: $_" + exit 1 +} diff --git a/app/Install.ps1 b/app/Install.ps1 new file mode 100644 index 0000000..4abeee9 --- /dev/null +++ b/app/Install.ps1 @@ -0,0 +1,172 @@ +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to deploy to all user desktops +# instead of only the public desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, deploys to public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "DesktopShortcuts.log" + +# Check if Sysnative exists (means script is running in 32-bit mode on x64 OS) +if (Test-Path "$($env:windir)\Sysnative") { + $rdpSignPath = "$($env:windir)\Sysnative\rdpsign.exe" +} else { + $rdpSignPath = "$($env:windir)\System32\rdpsign.exe" +} + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +function Get-DesktopPaths { + if ($AllUsers) { + # Return desktop path for each user profile found + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +try { + $desktopPaths = Get-DesktopPaths + Write-Log "Running in mode: $(if ($AllUsers) { 'All Users' } else { 'Public Desktop' })" + + foreach ($desktopPath in $desktopPaths) { + Write-Log "Processing desktop: $desktopPath" + + # Copy RDP files to desktop + Get-ChildItem -Path ".\rdp-files\*.rdp" | ForEach-Object { + try { + Copy-Item -Path $_.FullName -Destination $desktopPath -Force + } catch { + Write-Log "Error copying file: $_" + exit 1 + } + } + } + + Start-Sleep -Seconds 2 # Wait for files to be fully copied before signing + Write-Log "Copied .rdp files to desktop(s)" + + # Certificate setup + $certSubjectName = "RDPSign" + $certSubject = "CN=$certSubjectName" + + Write-Log "Searching for existing certificate: $certSubjectName..." + + $existingCert = Get-ChildItem Cert:\LocalMachine\My | + Where-Object { $_.Subject -eq $certSubject } | + Select-Object -First 1 + + if ($existingCert) { + Write-Log "Found existing certificate with Thumbprint: $($existingCert.Thumbprint)" + $thumbprint = $existingCert.Thumbprint + } else { + Write-Log "No existing certificate found. Creating new one..." + + $cert = New-SelfSignedCertificate ` + -Subject $certSubject ` + -CertStoreLocation "Cert:\LocalMachine\My" ` + -Type CodeSigningCert ` + -KeyExportPolicy NonExportable ` + -NotAfter (Get-Date).AddYears(25) + + $thumbprint = $cert.Thumbprint + + # Add to Trusted Root + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") + $rootStore.Open("ReadWrite") + $rootStore.Add($cert) + $rootStore.Close() + + # Add to Trusted Publishers + $pubStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine") + $pubStore.Open("ReadWrite") + $pubStore.Add($cert) + $pubStore.Close() + + # Add thumbprint to RDP trusted certs in registry + $gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" + $keyName = "TrustedCertThumbprints" + + if (-not (Test-Path $gpoPath)) { + New-Item -Path $gpoPath -Force | Out-Null + } + + $currentValue = (Get-ItemProperty -Path $gpoPath -Name $keyName -ErrorAction SilentlyContinue).$keyName + + if ($currentValue -notmatch [regex]::Escape($thumbprint)) { + $newValue = if ([string]::IsNullOrWhiteSpace($currentValue)) { $thumbprint } else { "$currentValue,$thumbprint" } + + if ($null -eq $currentValue) { + New-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue -PropertyType String -Force | Out-Null + } else { + Set-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue + } + Write-Log "Updated TrustedCertThumbprints registry value." + } else { + Write-Log "Thumbprint already exists in registry. Skipping update." + } + + Write-Log "Certificate created and trusted successfully." + } + + # Sign RDP files on all desktop paths + $successCount = 0 + $failCount = 0 + + foreach ($desktopPath in $desktopPaths) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -Recurse -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "No .rdp files found on desktop: $desktopPath" + continue + } + + Write-Log "Found $($rdpFiles.Count) file(s) to sign on: $desktopPath" + + foreach ($rdpFile in $rdpFiles) { + Write-Log "Signing: $($rdpFile.Name)" + & $rdpSignPath /sha256 $thumbprint $rdpFile.FullName + + if ($LASTEXITCODE -eq 0) { + Write-Log " [OK] $($rdpFile.Name)" + $successCount++ + } else { + Write-Log " [FAILED] $($rdpFile.Name) - rdpsign exit code: $LASTEXITCODE" + $failCount++ + } + } + } + + # Set registry key to suppress RDP warning dialogs + reg add "HKLM\Software\Policies\Microsoft\Windows NT\Terminal Services\Client" /v RedirectionWarningDialogVersion /t REG_DWORD /d 1 /f + + if ($failCount -eq 0) { + Write-Log "All $successCount file(s) signed successfully." + } else { + Write-Log "$successCount file(s) signed successfully, $failCount file(s) failed." + exit 1 + } + exit 0 +} catch { + Write-Log "Error: $_" + exit 1 +} diff --git a/app/SignOnly.ps1 b/app/SignOnly.ps1 new file mode 100644 index 0000000..3d48797 --- /dev/null +++ b/app/SignOnly.ps1 @@ -0,0 +1,150 @@ +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to sign RDP files on all user +# desktops instead of only the public desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, signs on public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "RDPSign.log" + +# Check if Sysnative exists (means script is running in 32-bit mode on x64 OS) +if (Test-Path "$($env:windir)\Sysnative") { + $rdpSignPath = "$($env:windir)\Sysnative\rdpsign.exe" +} else { + $rdpSignPath = "$($env:windir)\System32\rdpsign.exe" +} + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +try { + $certSubjectName = "RDPSign" + $certSubject = "CN=$certSubjectName" + + Write-Log "Running in mode: $(if ($AllUsers) { 'All Users' } else { 'Public Desktop' })" + Write-Log "Searching for existing certificate: $certSubjectName..." + + $existingCert = Get-ChildItem Cert:\LocalMachine\My | + Where-Object { $_.Subject -eq $certSubject } | + Select-Object -First 1 + + if ($existingCert) { + Write-Log "Found existing certificate with Thumbprint: $($existingCert.Thumbprint)" + $thumbprint = $existingCert.Thumbprint + } else { + Write-Log "No existing certificate found. Creating new one..." + + $cert = New-SelfSignedCertificate ` + -Subject $certSubject ` + -CertStoreLocation "Cert:\LocalMachine\My" ` + -Type CodeSigningCert ` + -KeyExportPolicy NonExportable ` + -NotAfter (Get-Date).AddYears(25) + + $thumbprint = $cert.Thumbprint + + # Add to Trusted Root + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") + $rootStore.Open("ReadWrite") + $rootStore.Add($cert) + $rootStore.Close() + + # Add to Trusted Publishers + $pubStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine") + $pubStore.Open("ReadWrite") + $pubStore.Add($cert) + $pubStore.Close() + + # Add thumbprint to RDP trusted certs in registry + $gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" + $keyName = "TrustedCertThumbprints" + + if (-not (Test-Path $gpoPath)) { + New-Item -Path $gpoPath -Force | Out-Null + } + + $currentValue = (Get-ItemProperty -Path $gpoPath -Name $keyName -ErrorAction SilentlyContinue).$keyName + + if ($currentValue -notmatch [regex]::Escape($thumbprint)) { + $newValue = if ([string]::IsNullOrWhiteSpace($currentValue)) { $thumbprint } else { "$currentValue,$thumbprint" } + + if ($null -eq $currentValue) { + New-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue -PropertyType String -Force | Out-Null + } else { + Set-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue + } + Write-Log "Updated TrustedCertThumbprints registry value." + } else { + Write-Log "Thumbprint already exists in registry. Skipping update." + } + + Write-Log "Certificate created and trusted successfully." + } + + $successCount = 0 + $failCount = 0 + + foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -Recurse -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "No .rdp files found on desktop: $desktopPath" + continue + } + + Write-Log "Found $($rdpFiles.Count) file(s) to sign on: $desktopPath" + + foreach ($rdpFile in $rdpFiles) { + Write-Log "Signing: $($rdpFile.Name)" + & $rdpSignPath /sha256 $thumbprint $rdpFile.FullName + + if ($LASTEXITCODE -eq 0) { + Write-Log " [OK] $($rdpFile.Name)" + $successCount++ + } else { + Write-Log " [FAILED] $($rdpFile.Name) - rdpsign exit code: $LASTEXITCODE" + $failCount++ + } + } + } + + # Set registry key to suppress RDP warning dialogs + reg add "HKLM\Software\Policies\Microsoft\Windows NT\Terminal Services\Client" /v RedirectionWarningDialogVersion /t REG_DWORD /d 1 /f + + if ($failCount -eq 0) { + Write-Log "All $successCount file(s) signed successfully." + } else { + Write-Log "$successCount file(s) signed successfully, $failCount file(s) failed." + exit 1 + } + exit 0 +} catch { + Write-Log "Error: $_" + exit 1 +} diff --git a/app/SignOnly_detect.ps1 b/app/SignOnly_detect.ps1 new file mode 100644 index 0000000..71d2cc6 --- /dev/null +++ b/app/SignOnly_detect.ps1 @@ -0,0 +1,61 @@ +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to check certificate and signed +# RDP files across all user desktops instead of only the +# public desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, checks public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +$certSubject = "CN=RDPSign" + +# Check certificate exists in all three stores +$certInMy = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -eq $certSubject } +$certInRoot = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq $certSubject } +$certInPub = Get-ChildItem Cert:\LocalMachine\TrustedPublisher | Where-Object { $_.Subject -eq $certSubject } + +if (-not $certInMy -or -not $certInRoot -or -not $certInPub) { + exit 1 +} + +# Check registry thumbprint +$gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" +$thumbprintValue = (Get-ItemProperty -Path $gpoPath -Name "TrustedCertThumbprints" -ErrorAction SilentlyContinue).TrustedCertThumbprints +if ([string]::IsNullOrWhiteSpace($thumbprintValue)) { + exit 1 +} + +# Check that all RDP files on desktop(s) are signed +foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + exit 1 + } + + foreach ($file in $rdpFiles) { + $content = Get-Content $file.FullName -ErrorAction SilentlyContinue + $hasSig = $content | Where-Object { $_ -match "^signature:s:" } + if (-not $hasSig) { + exit 1 + } + } +} + +Write-Host "Detected" +exit 0 diff --git a/app/Uninstall.ps1 b/app/Uninstall.ps1 new file mode 100644 index 0000000..6776a24 --- /dev/null +++ b/app/Uninstall.ps1 @@ -0,0 +1,60 @@ +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to remove files from all user +# desktops instead of only the public desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, removes from public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "DesktopShortcuts.log" + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +try { + $desktopPaths = Get-DesktopPaths + Write-Log "Running in mode: $(if ($AllUsers) { 'All Users' } else { 'Public Desktop' })" + + foreach ($desktopPath in $desktopPaths) { + Get-ChildItem -Path ".\rdp-files\*.rdp" | ForEach-Object { + $targetFile = Join-Path $desktopPath $_.Name + if (Test-Path $targetFile) { + Remove-Item -Path $targetFile -Force + Write-Log "Removed: $($_.Name) from $desktopPath" + } else { + Write-Log "Not found, skipping: $($_.Name) on $desktopPath" + } + } + } + + Write-Log "Uninstall completed." + exit 0 +} catch { + Write-Log "An error occurred: $_" + exit 1 +} diff --git a/app/sandbox.ps1 b/app/sandbox.ps1 new file mode 100644 index 0000000..5244f00 --- /dev/null +++ b/app/sandbox.ps1 @@ -0,0 +1,208 @@ +# ============================================================ +# INSTALL + DETECT - Sandbox test script +# ============================================================ +# CHANGELOG +# v1.1 - Added -AllUsers switch to deploy and detect across all +# user desktops instead of only the public desktop. +# Added Get-DesktopPaths helper function. +# v1.0 - Initial version, public desktop only. +# ============================================================ + +param( + [switch]$AllUsers +) + +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "DesktopShortcuts.log" + +# Check if Sysnative exists (means script is running in 32-bit mode on x64 OS) +if (Test-Path "$($env:windir)\Sysnative") { + $rdpSignPath = "$($env:windir)\Sysnative\rdpsign.exe" +} else { + $rdpSignPath = "$($env:windir)\System32\rdpsign.exe" +} + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory | ForEach-Object { + $path = Join-Path $_.FullName "Desktop" + if (Test-Path $path) { $path } + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +# ============================================================ +# INSTALL +# ============================================================ +Write-Log "=== START INSTALL ===" +Write-Log "Running in mode: $(if ($AllUsers) { 'All Users' } else { 'Public Desktop' })" + +try { + $desktopPaths = Get-DesktopPaths + + foreach ($desktopPath in $desktopPaths) { + Write-Log "Copying files to: $desktopPath" + Get-ChildItem -Path ".\rdp-files\*.rdp" | ForEach-Object { + try { + Copy-Item -Path $_.FullName -Destination $desktopPath -Force + } catch { + Write-Log "Error copying file: $_" + } + } + } + + Start-Sleep -Seconds 2 # Wait for files to be fully copied before signing + Write-Log "Copied .rdp files to desktop(s)" + + # Certificate setup + $certSubjectName = "RDPSign" + $certSubject = "CN=$certSubjectName" + + Write-Log "Searching for existing certificate: $certSubjectName..." + + $existingCert = Get-ChildItem Cert:\LocalMachine\My | + Where-Object { $_.Subject -eq $certSubject } | + Select-Object -First 1 + + if ($existingCert) { + Write-Log "Found existing certificate with Thumbprint: $($existingCert.Thumbprint)" + $thumbprint = $existingCert.Thumbprint + } else { + Write-Log "No existing certificate found. Creating new one..." + + $cert = New-SelfSignedCertificate ` + -Subject $certSubject ` + -CertStoreLocation "Cert:\LocalMachine\My" ` + -Type CodeSigningCert ` + -KeyExportPolicy NonExportable ` + -NotAfter (Get-Date).AddYears(25) + + $thumbprint = $cert.Thumbprint + + # Add to Trusted Root + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") + $rootStore.Open("ReadWrite") + $rootStore.Add($cert) + $rootStore.Close() + + # Add to Trusted Publishers + $pubStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine") + $pubStore.Open("ReadWrite") + $pubStore.Add($cert) + $pubStore.Close() + + # Add thumbprint to RDP trusted certs in registry + $gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" + $keyName = "TrustedCertThumbprints" + + if (-not (Test-Path $gpoPath)) { + New-Item -Path $gpoPath -Force | Out-Null + } + + $currentValue = (Get-ItemProperty -Path $gpoPath -Name $keyName -ErrorAction SilentlyContinue).$keyName + + if ($currentValue -notmatch [regex]::Escape($thumbprint)) { + $newValue = if ([string]::IsNullOrWhiteSpace($currentValue)) { $thumbprint } else { "$currentValue,$thumbprint" } + + if ($null -eq $currentValue) { + New-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue -PropertyType String -Force | Out-Null + } else { + Set-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue + } + Write-Log "Updated TrustedCertThumbprints registry value." + } else { + Write-Log "Thumbprint already exists in registry. Skipping update." + } + + Write-Log "Certificate created and trusted successfully." + } + + $successCount = 0 + $failCount = 0 + + foreach ($desktopPath in $desktopPaths) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -Recurse -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "No .rdp files found on desktop: $desktopPath" + continue + } + + Write-Log "Found $($rdpFiles.Count) file(s) to sign on: $desktopPath" + + foreach ($rdpFile in $rdpFiles) { + Write-Log "Signing: $($rdpFile.Name)" + & $rdpSignPath /sha256 $thumbprint $rdpFile.FullName + + if ($LASTEXITCODE -eq 0) { + Write-Log " [OK] $($rdpFile.Name)" + $successCount++ + } else { + Write-Log " [FAILED] $($rdpFile.Name) - rdpsign exit code: $LASTEXITCODE" + $failCount++ + } + } + } + + # Set registry key to suppress RDP warning dialogs + reg add "HKLM\Software\Policies\Microsoft\Windows NT\Terminal Services\Client" /v RedirectionWarningDialogVersion /t REG_DWORD /d 1 /f + + if ($failCount -eq 0) { + Write-Log "All $successCount file(s) signed successfully." + } else { + Write-Log "$successCount file(s) signed successfully, $failCount file(s) failed." + } + +} catch { + Write-Log "Install error: $_" +} + +# ============================================================ +# DETECT +# ============================================================ +Write-Log "=== START DETECT ===" + +try { + $allFound = $true + + foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFilesOnDesktop = Get-ChildItem -Path "$desktopPath\*.rdp" -ErrorAction SilentlyContinue + + if ($rdpFilesOnDesktop.Count -eq 0) { + Write-Log "DETECT [FAIL]: No .rdp files found on desktop: $desktopPath" + $allFound = $false + continue + } + + foreach ($file in $rdpFilesOnDesktop) { + if (-not (Test-Path (Join-Path $desktopPath $file.Name))) { + Write-Log "DETECT [FAIL]: Missing: $($file.Name) on $desktopPath" + $allFound = $false + } + } + } + + if ($allFound) { + Write-Log "DETECT [OK]: All .rdp files found on all desktop(s)" + exit 0 + } else { + exit 1 + } +} catch { + Write-Log "Detect error: $_" + exit 1 +} From 13005cf1617f47f9d79449c558f5d55ded36178d Mon Sep 17 00:00:00 2001 From: GCH Date: Fri, 22 May 2026 11:13:46 +0200 Subject: [PATCH 2/4] Oprettet install.intunewin, og mappen rdp-files under app er oprettet --- app/rdp-files/PUT_RDP_FILES_HERE | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/rdp-files/PUT_RDP_FILES_HERE diff --git a/app/rdp-files/PUT_RDP_FILES_HERE b/app/rdp-files/PUT_RDP_FILES_HERE new file mode 100644 index 0000000..e69de29 From 0593f8c042a97207fe3c77c011ed8a9d98b47cf0 Mon Sep 17 00:00:00 2001 From: GlennIgen Date: Sun, 24 May 2026 19:27:09 +0200 Subject: [PATCH 3/4] feat: opdater Detect.ps1 med specifik fil-tjek og opdater README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implementer $expectedFiles array i Detect.ps1 for at tjekke specifikke .rdp-filnavne - Opdater beskrivelse af Detect.ps1 i pakkens indhold tabel - Tilføj afsnit 'Sådan opsætter du Detect.ps1' med eksempel og forklaring - Opdater indholdsfortegnelse med nyt afsnit --- README.md | 25 ++++++++++++++++++++++++- app/Detect.ps1 | 31 ++++++++++++++++++------------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index e92f033..59ee5a5 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ - [Pakkens indhold](#pakkens-indhold) - [Intune App Konfiguration](#intune-app-konfiguration) - [Hvad Install.ps1 gør](#hvad-installps1-gør) +- [Sådan opsætter du Detect.ps1](#sådan-opsætter-du-detectps1) - [AllUsers Switch](#allusers-switch) - [Registry-ændringer](#registry-ændringer) - [Logning og fejlfinding](#logning-og-fejlfinding) @@ -24,7 +25,7 @@ | Fil | Formål | |-----|--------| | `Install.ps1` | Kopierer RDP-filer til skrivebord(e), opretter selvsigneret certifikat og signerer alle RDP-filer. Understøtter `-AllUsers` switch. | -| `Detect.ps1` | Registrerer om alle RDP-filer fra pakken er til stede på skrivebord(e). Understøtter `-AllUsers` switch. | +| `Detect.ps1` | Tjekker at specifikke forventede .rdp-filer (defineret i `$expectedFiles` array) eksisterer på skrivebord(e). Understøtter `-AllUsers` switch. | | `Uninstall.ps1` | Fjerner RDP-filer fra skrivebord(e). Understøtter `-AllUsers` switch. | | `SignOnly.ps1` | Signerer eksisterende RDP-filer på skrivebord(e) — ingen filkopiering. Understøtter `-AllUsers` switch. | | `SignOnly_detect.ps1` | Registrerer om certifikat er til stede og alle RDP-filer på skrivebord(e) er signerede. Understøtter `-AllUsers` switch. | @@ -36,6 +37,28 @@ --- +## Sådan opsætter du Detect.ps1 + +Før du uploader `Detect.ps1` til Intune som registreringsregel, skal du åbne filen og udfylde `$expectedFiles` array med de `.rdp` filnavne der ligger i `.\\rdp-files\\`: + +```powershell +$expectedFiles = @( + "Server1.rdp", + "Server2.rdp", + "DesktopApp.rdp" +) +``` + +Når scriptet kører: +- Uden `-AllUsers`: tjekker at alle filer i `$expectedFiles` findes på det offentlige skrivebord (`C:\Users\Public\Desktop`) +- Med `-AllUsers`: tjekker alle filer i `$expectedFiles` på tværs af alle brugeres skriveborde +- Returnerer `exit 0` = installeret (alle filer fundet) +- Returnerer `exit 1` = ikke installeret (en eller flere filer mangler) + +> **Vigtigt:** Husk at opdatere `$expectedFiles` hver gang du tilføjer eller fjerner `.rdp` filer i pakken, ellers vil detekteringen være forkert. + +--- + ## Intune App Konfiguration ### Program diff --git a/app/Detect.ps1 b/app/Detect.ps1 index 04774f1..6a01ea6 100644 --- a/app/Detect.ps1 +++ b/app/Detect.ps1 @@ -1,5 +1,7 @@ # ============================================================ # CHANGELOG +# v1.2 - Checks for specific expected .rdp filenames instead +# of just "any .rdp file exists on desktop". # v1.1 - Added -AllUsers switch to check all user desktops # instead of only the public desktop. # Added Get-DesktopPaths helper function. @@ -10,6 +12,16 @@ param( [switch]$AllUsers ) +# ============================================================ +# Update this list whenever .rdp files are added or removed +# from the rdp-files\\ folder. +# ============================================================ +$expectedFiles = @( + # Add your .rdp filenames here, e.g.: + # "RemoteServer1.rdp", + # "RemoteServer2.rdp" +) + # Setup logging $baseFolder = Join-Path $env:SystemDrive "Intune" $logFile = Join-Path $baseFolder "DesktopShortcuts.log" @@ -37,28 +49,21 @@ function Get-DesktopPaths { } try { - $desktopPaths = Get-DesktopPaths + $desktopPaths = Get-desktopPaths $allFound = $true foreach ($desktopPath in $desktopPaths) { - $rdpFiles = Get-ChildItem -Path "$desktopPath\*.rdp" -ErrorAction SilentlyContinue - - if ($rdpFiles.Count -eq 0) { - Write-Log "DETECT [FAIL]: No .rdp files found on desktop: $desktopPath" - $allFound = $false - continue - } - - foreach ($file in $rdpFiles) { - if (-not (Test-Path (Join-Path $desktopPath $file.Name))) { - Write-Log "DETECT [FAIL]: Missing: $($file.Name) on $desktopPath" + foreach ($fileName in $expectedFiles) { + $targetFile = Join-Path $desktopPath $fileName + if (-not (Test-Path $targetFile)) { + Write-Log "DETECT [FAIL]: Missing: $fileName on $desktopPath" $allFound = $false } } } if ($allFound) { - Write-Log "DETECT [OK]: All .rdp files found on all desktop(s)" + Write-Log "DETECT [OK]: All expected .rdp files found" exit 0 } else { exit 1 From efaceaa528268e5d6efef79e732a3cf8d2fb72eb Mon Sep 17 00:00:00 2001 From: GlennIgen Date: Sun, 24 May 2026 19:46:52 +0200 Subject: [PATCH 4/4] =?UTF-8?q?docs:=20tilf=C3=B8j=20README.html=20-=20pla?= =?UTF-8?q?in=20HTML=20version=20af=20dokumentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tilføjer README.html som plain HTML uden farver/darkmode - Tabeller med border=1 cellpadding=6 cellspacing=0 - Kommandoer, registreringsregler og logik i tabelformat --- README.html | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 README.html diff --git a/README.html b/README.html new file mode 100644 index 0000000..a4364f6 --- /dev/null +++ b/README.html @@ -0,0 +1,340 @@ +

RDP - IntuneWin Pakke

+
+

Denne pakke installerer og signerer RDP-genveje på skrivebordet via + et selvsigneret certifikat, så brugerne ikke får en sikkerhedsadvarsel + ved åbning. Som standard arbejder alle scripts mod det + offentlige skrivebord + (C:\Users\Public\Desktop). Brug -AllUsers + switchen for at køre mod alle brugeres individuelle skriveborde i + stedet. +

+
+
+

Indhold

+ +
+

Pakkens indhold

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FilFormål
Install.ps1Kopierer RDP-filer til skrivebord(e), opretter selvsigneret + certifikat og signerer alle RDP-filer. Understøtter + -AllUsers switch. +
Detect.ps1Tjekker at specifikke forventede .rdp-filer (defineret i + $expectedFiles array) eksisterer på skrivebord(e). + Understøtter -AllUsers switch. +
Uninstall.ps1Fjerner RDP-filer fra skrivebord(e). Understøtter + -AllUsers switch. +
SignOnly.ps1Signerer eksisterende RDP-filer på skrivebord(e) — ingen + filkopiering. Understøtter -AllUsers switch.
SignOnly_detect.ps1Registrerer om certifikat er til stede og alle RDP-filer på + skrivebord(e) er signerede. Understøtter -AllUsers + switch.
Clearsigning.ps1Fjerner signaturer fra RDP-filer og rydder op i certifikat og + registry (til oprydning/debug). Understøtter -AllUsers + switch.
sandbox.ps1Kombineret install + detect script til lokal sandkasse-test. + Understøtter -AllUsers switch.
rdp-files\*.rdpKilde-RDP-filer der installeres på skrivebord(e)
+

↑ Tilbage til toppen

+
+

Sådan opsætter du Detect.ps1

+

Før du uploader Detect.ps1 til Intune som + registreringsregel, skal du åbne filen og udfylde + $expectedFiles array med de .rdp filnavne der + ligger i .\\rdp-files\\: +

+
+
$expectedFiles = @(
+    "Server1.rdp",
+    "Server2.rdp",
+    "DesktopApp.rdp"
+)
+
+

Når scriptet kører: - Uden -AllUsers: tjekker at alle + filer i $expectedFiles findes på det offentlige skrivebord + (C:\Users\Public\Desktop) - Med -AllUsers: + tjekker alle filer i $expectedFiles på tværs af alle + brugeres skriveborde - Returnerer exit 0 = installeret + (alle filer fundet) - Returnerer exit 1 = ikke installeret + (en eller flere filer mangler)

+
+

Vigtigt: Husk at opdatere + $expectedFiles hver gang du tilføjer eller fjerner + .rdp filer i pakken, ellers vil detekteringen være + forkert. +

+
+
+

Intune App Konfiguration

+

Program

+
    +
  • Installationskommando: + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1 +
  • +
  • Installationskommando (alle brugeres skriveborde): + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1 -AllUsers +
  • +
  • Afinstallationskommando: + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Uninstall.ps1 +
  • +
  • Afinstallationskommando (alle brugeres + skriveborde): + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Uninstall.ps1 -AllUsers +
  • +
  • Installationsadfærd: System
  • +
+

Registreringsregel

+

Brug et brugerdefineret registreringsscript: - + Scriptfil: Detect.ps1 - Kør script + som 32-bit proces på 64-bit klienter: Nej - Gennemtving + scriptsignaturkontrol: Nej +

+

Registreringslogik: - Uden -AllUsers: tjekker at alle + .rdp-filer er til stede på det offentlige skrivebord + (C:\Users\Public\Desktop) - Med -AllUsers: + tjekker alle brugeres skriveborde under C:\Users\ - + Returnerer exit 0 = installeret - Returnerer + exit 1 = ikke installeret +

+

↑ Tilbage til toppen

+
+

Hvad Install.ps1 gør

+
    +
  1. Finder målskrivebord(e) — offentligt skrivebord som standard, alle + brugeres skriveborde med -AllUsers
  2. +
  3. Kopierer alle .rdp-filer fra .\rdp-files\ + til de fundne skrivebord(e)
  4. +
  5. Søger efter eksisterende selvsigneret certifikat + (CN=RDPSign) i Cert:\LocalMachine\My
  6. +
  7. Opretter et nyt selvsigneret kodesigneringscertifikat hvis intet + findes (gyldigt i 25 år, ikke-eksporterbart)
  8. +
  9. Tilføjer certifikatet til Trusted Root og + Trusted Publishers i den lokale maskines + certifikatstore +
  10. +
  11. Tilføjer certifikatets thumbprint til registry-nøglen + TrustedCertThumbprints +
  12. +
  13. Signerer alle .rdp-filer på skrivebord(e) med + rdpsign.exe /sha256 +
  14. +
  15. Sætter RedirectionWarningDialogVersion = 1 i registry + for at undertrykke RDP-advarselsdialoger
  16. +
+

↑ Tilbage til toppen

+
+

AllUsers Switch

+

Alle scripts understøtter -AllUsers switchen. Som + standard — uden -AllUsers — køres alle scripts kun mod det + offentlige skrivebord + (C:\Users\Public\Desktop). Når -AllUsers + angives, itererer scriptet i stedet over alle brugerprofiler under + C:\Users\ og behandler hver brugers + Desktop-mappe. +

+
+
# Kun offentligt skrivebord (standard)
+.\Install.ps1
+
+# Alle brugeres skriveborde
+.\Install.ps1 -AllUsers
+
+

↑ Tilbage til toppen

+
+

Registry-ændringer

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StiVærdiTypeData
HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal ServicesTrustedCertThumbprintsStringCertifikatets thumbprint
HKLM\Software\Policies\Microsoft\Windows NT\Terminal Services\ClientRedirectionWarningDialogVersionDWORD1
+

↑ Tilbage til toppen

+
+

Logning og fejlfinding

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ScriptLogfil
Install.ps1C:\Intune\DesktopShortcuts.log
Detect.ps1C:\Intune\DesktopShortcuts.log
Uninstall.ps1C:\Intune\DesktopShortcuts.log
SignOnly.ps1C:\Intune\RDPSign.log
+

↑ Tilbage til toppen

+
+

SignOnly Intune App + Konfiguration

+

Program

+
    +
  • Installationskommando: + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1 +
  • +
  • Installationskommando (alle brugeres skriveborde): + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1 -AllUsers +
  • +
  • Afinstallationskommando: + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1 +
  • +
  • Afinstallationskommando (alle brugeres + skriveborde): + powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1 -AllUsers +
  • +
  • Installationsadfærd: System
  • +
+

Registreringsregel

+

Brug et brugerdefineret registreringsscript: - + Scriptfil: SignOnly_detect.ps1 - + Kør script som 32-bit proces på 64-bit klienter: Nej - + Gennemtving scriptsignaturkontrol: Nej +

+

Registreringslogik: - Tjekker at CN=RDPSign-certifikatet + findes i My, Root og + TrustedPublisher stores - Tjekker at thumbprint er til + stede i registry - Uden -AllUsers: tjekker at alle + .rdp-filer på det offentlige skrivebord er signerede - Med + -AllUsers: tjekker alle .rdp-filer på tværs af + alle brugeres skriveborde - Returnerer exit 0 + + "Detected" = installeret - Returnerer exit 1 = + ikke installeret +

+

↑ Tilbage til toppen

+
+

Øvrige scripts i pakken

+
+

Bemærk: Alle PowerShell-scripts er pakket ind i + samme IntuneWin-pakke. Det betyder at man altid kan kalde på et + vilkårligt script direkte fra Intune eller manuelt, f.eks.:

+
+
powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1
+powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Install.ps1 -AllUsers
+powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1
+powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\SignOnly.ps1 -AllUsers
+powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1
+powershell.exe -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File .\Clearsigning.ps1 -AllUsers
+
+

osv. for alle scripts i pakken.

+
+

SignOnly.ps1

+

Signerer alle eksisterende .rdp-filer på skrivebord(e) + uden at kopiere filer. Nyttigt til gensignering efter en opdatering + eller hvis filer allerede er installeret. Kør som administrator. + Understøtter -AllUsers switch.

+

SignOnly_detect.ps1

+

Registreringsscript til brug med SignOnly.ps1 som + Intune-pakke. Tjekker: - Certifikat findes i My, + Root og TrustedPublisher stores - Thumbprint + er til stede i registry - Alle .rdp-filer på skrivebord(e) + indeholder en gyldig signatur +

+

Understøtter -AllUsers switch.

+

Clearsigning.ps1

+

Fjerner alle signeringsartefakter. Nyttigt til test eller oprydning. + Kør som administrator. Understøtter -AllUsers switch. - + Fjerner signscope- og signature-linjer fra + alle .rdp-filer på skrivebord(e) - Fjerner + CN=RDPSign-certifikatet fra My, + Root og TrustedPublisher stores - Fjerner + TrustedCertThumbprints fra registry - Fjerner + RedirectionWarningDialogVersion fra registry +

+

sandbox.ps1

+

Kombinerer install og detect i ét script til lokal sandkasse-test. + Understøtter -AllUsers switch. Kør fra mappen der + indeholder rdp-files\ som administrator. Output skrives til + både konsollen og C:\Intune\DesktopShortcuts.log.

+

↑ Tilbage til toppen

\ No newline at end of file