From 2e783a26f7a6d4038dad734a287a25c03b686fba Mon Sep 17 00:00:00 2001 From: Michael Morten Sonne | Microsoft MVP <49366751+michaelmsonne@users.noreply.github.com> Date: Wed, 17 Jun 2026 07:00:49 +0200 Subject: [PATCH 1/2] Update PowerShell script to version 1.3 with enhancements Added comprehensive error handling, logging, and user feedback enhancements. Updated script to enforce version requirements and improve cleanup logic. Updated PowerShell script to version 1.3 with comprehensive error handling, logging, and user feedback enhancements. - Added comprehensive error handling with try-catch-finally blocks throughout the script - Added #Requires statements for version validation and administrator rights enforcement - Implemented transcript logging for full execution history and debugging - Added color-coded console output (Green=Success, Yellow=Warning, Red=Error, Cyan=Info) - Enhanced download validation with file size and existence checks - Added exit code checking for installer/uninstaller processes - Improved cleanup logic with array-based folder management - Added automatic cleanup on script failure - Enhanced user feedback with progress indicators and status messages - Added validation for MSAL library existence before loading Implemented strict mode for better error detection - Added error-specific cleanup in catch block to ensure clean state In regards to old: https://github.com/MicrosoftDocs/entra-docs/pull/2005 where this should be included ref. @kenwith --- .../scripts/powershell-get-token.md | 402 +++++++++++++----- 1 file changed, 302 insertions(+), 100 deletions(-) diff --git a/docs/global-secure-access/scripts/powershell-get-token.md b/docs/global-secure-access/scripts/powershell-get-token.md index ae60a65dd7d..7614ee57cf3 100644 --- a/docs/global-secure-access/scripts/powershell-get-token.md +++ b/docs/global-secure-access/scripts/powershell-get-token.md @@ -29,7 +29,25 @@ The sample requires the [Microsoft Graph Beta PowerShell module](/powershell/mic ```powershell # This sample script lets you obtain the Auth Token that you can use for registering the Entra private network connector through Marketplace. # +# Version 1.3 +# +# CHANGELOG: +# Version 1.3 (2026-06-17) - Michael Morten Sonne, https://github.com/michaelmsonne +# - Added comprehensive error handling with try-catch-finally blocks throughout the script +# - Added #Requires statements for version validation and administrator rights enforcement +# - Implemented transcript logging for full execution history and debugging +# - Added color-coded console output (Green=Success, Yellow=Warning, Red=Error, Cyan=Info) +# - Enhanced download validation with file size and existence checks +# - Added exit code checking for installer/uninstaller processes +# - Improved cleanup logic with array-based folder management +# - Added automatic cleanup on script failure +# - Enhanced user feedback with progress indicators and status messages +# - Added validation for MSAL library existence before loading +# - Implemented strict mode for better error detection +# - Added error-specific cleanup in catch block to ensure clean state +# # Version 1.2 +# - Original version # # This script requires following # - PowerShell 5.1 (x64) or beyond @@ -44,142 +62,326 @@ The sample requires the [Microsoft Graph Beta PowerShell module](/powershell/mic # - You are on Windows Machine which is not running the Entra Private Network Connector already. If you already have a connector installed, quiet registration step below will fail. # - Make sure there is no C:\temp folder on the machine. If you have some files stored, please move those before running the script -# Make sure ExecutionPolicy is set to Unrestricted -Set-ExecutionPolicy UnRestricted -Force +#Requires -Version 5.1 +#Requires -RunAsAdministrator -# The script will use a temp folder on C Drive. First it will remove the folder and create a new folder to ensure its empty. -$tempPath = "C:\temp" -$tokenPath = "C:\token.txt" +# Set strict mode for better error detection +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" -# Check if the folder exists -if (Test-Path -Path $tempPath) { - Write-Host "Your C Drive has existing temp folder that is being deleted" - Remove-Item -Path $tempPath -Recurse -Force -} +# Start transcript for logging +$transcriptPath = Join-Path $env:TEMP "EntraConnectorToken_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" +Start-Transcript -Path $transcriptPath -Append -# Creating C:\temp folder -New-Item -ItemType Directory -Path $tempPath -Force | Out-Null +try { + Write-Host "Script started at $(Get-Date)" -ForegroundColor Cyan + Write-Host "Log file: $transcriptPath" -ForegroundColor Cyan -# Copy Required Dlls -Write-Host "Downloading Entra Private Network Connector Installer..." -Invoke-WebRequest https://download.msappproxy.net/Subscription/d3c8b69d-6bf7-42be-a529-3fe9c2e70c90/Connector/DownloadConnectorInstaller -OutFile "$tempPath\MicrosoftEntraPrivateNetworkConnectorInstaller.exe" - -# Set the prompt path to C:\temp -Set-Location -Path $tempPath + # Make sure ExecutionPolicy is set to Unrestricted + try { + Set-ExecutionPolicy UnRestricted -Force -Scope Process + Write-Host "Execution policy set successfully" -ForegroundColor Green + } + catch { + Write-Warning "Could not set execution policy: $_" + Write-Host "Continuing anyway..." -ForegroundColor Yellow + } -# Quiet Registration of the Connector. This step will provide the required Module for acquiring the token. -# At the end of this step, you should see 2 folders under C:\Program Files. 1) Microsoft Entra private network connector 2) Microsoft Entra private network connector updater -# These folders contains the required modules needed for getting the token. -Write-Host "Installing connector (quiet mode)..." -Start-Process -FilePath ".\MicrosoftEntraPrivateNetworkConnectorInstaller.exe" -ArgumentList "REGISTERCONNECTOR=`"false`"", "/q" -Wait + # The script will use a temp folder on C Drive. First it will remove the folder and create a new folder to ensure its empty. + $tempPath = "C:\temp" + $tokenPath = "C:\token.txt" -# Wait 60 seconds for installation to complete -Write-Host "Waiting for installation to complete..." -Start-Sleep -Seconds 60 + # Check if the folder exists + if (Test-Path -Path $tempPath) { + Write-Host "Existing temp folder found at '$tempPath'. Attempting to remove..." -ForegroundColor Yellow + try { + Remove-Item -Path $tempPath -Recurse -Force -ErrorAction Stop + Write-Host "Temp folder removed successfully" -ForegroundColor Green + } + catch { + Write-Error "Failed to remove existing temp folder '$tempPath'. Please manually delete it and try again. Error: $_" + throw + } + } -$folderPath = "C:\Program Files\Microsoft Entra private network connector\Modules\MicrosoftEntraPrivateNetworkConnectorPSModule" + # Creating C:\temp folder + try { + New-Item -ItemType Directory -Path $tempPath -Force -ErrorAction Stop | Out-Null + Write-Host "Created temp folder: $tempPath" -ForegroundColor Green + } + catch { + Write-Error "Failed to create temp folder '$tempPath'. Error: $_" + throw + } -# Check if the Module exists -if (Test-Path -Path $folderPath) { - Write-Host "The Module is successfully made available at path: $folderPath" + # Copy Required Dlls + Write-Host "Downloading Entra Private Network Connector Installer..." -ForegroundColor Cyan + $installerUrl = "https://download.msappproxy.net/Subscription/d3c8b69d-6bf7-42be-a529-3fe9c2e70c90/Connector/DownloadConnectorInstaller" + $installerPath = "$tempPath\MicrosoftEntraPrivateNetworkConnectorInstaller.exe" - # Set the prompt path to C:\Program Files\Microsoft Entra private network connector\Modules\MicrosoftEntraPrivateNetworkConnectorPSModule - Set-Location -Path "C:\Program Files\Microsoft Entra private network connector\Modules\MicrosoftEntraPrivateNetworkConnectorPSModule" + try { + Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath -ErrorAction Stop + + if (-not (Test-Path -Path $installerPath)) { + throw "Installer file was not downloaded successfully" + } + + $fileSize = (Get-Item $installerPath).Length + if ($fileSize -lt 1MB) { + throw "Downloaded file seems too small ($fileSize bytes). Download may have failed." + } + + Write-Host "Installer downloaded successfully ($([Math]::Round($fileSize/1MB, 2)) MB)" -ForegroundColor Green + } + catch { + Write-Error "Failed to download installer from '$installerUrl'. Error: $_" + throw + } + + # Set the prompt path to C:\temp + try { + Set-Location -Path $tempPath -ErrorAction Stop + Write-Host "Changed directory to: $tempPath" -ForegroundColor Green + } + catch { + Write-Error "Failed to change directory to '$tempPath'. Error: $_" + throw + } - # Import Module - Import-Module ..\MicrosoftEntraPrivateNetworkConnectorPSModule -ErrorAction Stop + # Quiet Registration of the Connector. This step will provide the required Module for acquiring the token. + # At the end of this step, you should see 2 folders under C:\Program Files. 1) Microsoft Entra private network connector 2) Microsoft Entra private network connector updater + # These folders contains the required modules needed for getting the token. + Write-Host "Installing connector (quiet mode)..." -ForegroundColor Cyan + + try { + $installProcess = Start-Process -FilePath $installerPath -ArgumentList "REGISTERCONNECTOR=`"false`"", "/q" -Wait -PassThru -ErrorAction Stop + + if ($installProcess.ExitCode -ne 0) { + Write-Warning "Installer returned exit code: $($installProcess.ExitCode)" + } + else { + Write-Host "Installer completed successfully" -ForegroundColor Green + } + } + catch { + Write-Error "Failed to run installer. Error: $_" + throw + } - # Load MSAL - Add-Type -Path .\Microsoft.Identity.Client.dll + # Wait 60 seconds for installation to complete + Write-Host "Waiting for installation to complete..." -ForegroundColor Cyan + Start-Sleep -Seconds 60 - # The AAD authentication endpoint uri - $authority = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" + $folderPath = "C:\Program Files\Microsoft Entra private network connector\Modules\MicrosoftEntraPrivateNetworkConnectorPSModule" - # The application ID of the connector in AAD. Use the Connector AppId below - $connectorAppId = "55747057-9b5d-4bd4-b387-abf52a8bd489" + # Check if the Module exists + if (Test-Path -Path $folderPath) { + Write-Host "The Module is successfully made available at path: $folderPath" -ForegroundColor Green + + # Set the prompt path to C:\Program Files\Microsoft Entra private network connector\Modules\MicrosoftEntraPrivateNetworkConnectorPSModule + try { + Set-Location -Path $folderPath -ErrorAction Stop + Write-Host "Changed directory to module path" -ForegroundColor Green + } + catch { + Write-Error "Failed to change directory to '$folderPath'. Error: $_" + throw + } - # The AppIdUri of the registration service in AAD - $registrationServiceAppIdUri = "https://proxy.cloudwebappproxy.net/registerapp/user_impersonation" + # Import Module + try { + Import-Module ..\MicrosoftEntraPrivateNetworkConnectorPSModule -ErrorAction Stop + Write-Host "Module imported successfully" -ForegroundColor Green + } + catch { + Write-Error "Failed to import module. Error: $_" + throw + } - # Define the resources and scopes you want to call - $scopes = New-Object System.Collections.ObjectModel.Collection["string"] - $scopes.Add($registrationServiceAppIdUri) + # Load MSAL + $msalPath = ".\Microsoft.Identity.Client.dll" + try { + if (-not (Test-Path -Path $msalPath)) { + throw "MSAL library not found at: $msalPath" + } + Add-Type -Path $msalPath -ErrorAction Stop + Write-Host "MSAL library loaded successfully" -ForegroundColor Green + } + catch { + Write-Error "Failed to load MSAL library. Error: $_" + throw + } - $app = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($connectorAppId).WithAuthority($authority).WithDefaultRedirectUri().Build() + # The AAD authentication endpoint uri + $authority = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" - [Microsoft.Identity.Client.IAccount] $account = $null + # The application ID of the connector in AAD. Use the Connector AppId below + $connectorAppId = "55747057-9b5d-4bd4-b387-abf52a8bd489" - # Acquiring the token - Write-Host "Acquiring authentication token (interactive login required)..." - $authResult = $null - $authResult = $app.AcquireTokenInteractive($scopes).WithAccount($account).ExecuteAsync().ConfigureAwait($false).GetAwaiter().GetResult() + # The AppIdUri of the registration service in AAD + $registrationServiceAppIdUri = "https://proxy.cloudwebappproxy.net/registerapp/user_impersonation" - # Check AuthN result - If (($authResult) -and ($authResult.AccessToken) -and ($authResult.TenantId)) { - $token = $authResult.AccessToken - $tenantId = $authResult.TenantId - - $accessToken = $token + # Define the resources and scopes you want to call + $scopes = New-Object System.Collections.ObjectModel.Collection["string"] + $scopes.Add($registrationServiceAppIdUri) - New-Item -ItemType File -Path $tokenPath -Force | Out-Null - Set-Content -Path $tokenPath -Value "$accessToken" - - Write-Host "Token successfully acquired and saved to $tokenPath" + try { + $app = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($connectorAppId).WithAuthority($authority).WithDefaultRedirectUri().Build() + Write-Host "MSAL application created successfully" -ForegroundColor Green + } + catch { + Write-Error "Failed to create MSAL application. Error: $_" + throw + } - # Set the prompt path to C: - Set-Location -Path "C:\" + [Microsoft.Identity.Client.IAccount] $account = $null - # Uninstall the Connector from your machine. - # You can do so programmatically (below) or manually by double clicking C:\temp\MicrosoftEntraPrivateNetworkConnectorInstaller.exe and choose Uninstall. - # Note that if the Connector service is not uninstalled properly, next iteration can fail on this machine. - Write-Host "Uninstalling connector..." - Start-Process -FilePath "$tempPath\MicrosoftEntraPrivateNetworkConnectorInstaller.exe" -ArgumentList "/uninstall", "/quiet" -Wait + # Acquiring the token + Write-Host "Acquiring authentication token (interactive login required)..." -ForegroundColor Cyan + Write-Host "A browser window will open for authentication. Please complete the login process." -ForegroundColor Yellow + + $authResult = $null + try { + $authResult = $app.AcquireTokenInteractive($scopes).WithAccount($account).ExecuteAsync().ConfigureAwait($false).GetAwaiter().GetResult() + Write-Host "Authentication completed successfully" -ForegroundColor Green + } + catch { + Write-Error "Failed to acquire authentication token. User may have cancelled or authentication failed. Error: $_" + throw + } - # Wait 60 seconds - Write-Host "Waiting for uninstallation to complete..." - Start-Sleep -Seconds 60 + # Check AuthN result + If (($authResult) -and ($authResult.AccessToken) -and ($authResult.TenantId)) { + $token = $authResult.AccessToken + $tenantId = $authResult.TenantId + + $accessToken = $token - # Delete the related files - Write-Host "Cleaning up files..." - if (Test-Path -Path $tempPath) { try { - Remove-Item -Path $tempPath -Recurse -Force - } catch { - Write-Warning "Could not fully remove '$tempPath': $_" + New-Item -ItemType File -Path $tokenPath -Force -ErrorAction Stop | Out-Null + Set-Content -Path $tokenPath -Value "$accessToken" -ErrorAction Stop + Write-Host "Token successfully acquired and saved to $tokenPath" -ForegroundColor Green } - } - if (Test-Path -Path "C:\Program Files\Microsoft Entra private network connector") { + catch { + Write-Error "Failed to save token to '$tokenPath'. Error: $_" + throw + } + + # Set the prompt path to C: try { - Remove-Item -Path "C:\Program Files\Microsoft Entra private network connector" -Recurse -Force - } catch { - Write-Warning "Could not fully remove 'Microsoft Entra private network connector' folder: $_" + Set-Location -Path "C:\" -ErrorAction Stop } - } - if (Test-Path -Path "C:\Program Files\Microsoft Entra private network connector updater") { + catch { + Write-Warning "Could not change directory to C:\. Error: $_" + } + + # Uninstall the Connector from your machine. + # You can do so programmatically (below) or manually by double clicking C:\temp\MicrosoftEntraPrivateNetworkConnectorInstaller.exe and choose Uninstall. + # Note that if the Connector service is not uninstalled properly, next iteration can fail on this machine. + Write-Host "Uninstalling connector..." -ForegroundColor Cyan + try { - Remove-Item -Path "C:\Program Files\Microsoft Entra private network connector updater" -Recurse -Force - } catch { - Write-Warning "Could not fully remove 'Microsoft Entra private network connector updater' folder: $_" + if (Test-Path -Path $installerPath) { + $uninstallProcess = Start-Process -FilePath $installerPath -ArgumentList "/uninstall", "/quiet" -Wait -PassThru -ErrorAction Stop + + if ($uninstallProcess.ExitCode -ne 0) { + Write-Warning "Uninstaller returned exit code: $($uninstallProcess.ExitCode)" + } + else { + Write-Host "Uninstaller completed successfully" -ForegroundColor Green + } + } + else { + Write-Warning "Installer not found at '$installerPath'. Cannot run uninstaller." + } + } + catch { + Write-Warning "Failed to run uninstaller. Error: $_" + Write-Host "You may need to manually uninstall the connector." -ForegroundColor Yellow + } + + # Wait 60 seconds + Write-Host "Waiting for uninstallation to complete..." -ForegroundColor Cyan + Start-Sleep -Seconds 60 + + # Delete the related files + Write-Host "Cleaning up files..." -ForegroundColor Cyan + + $foldersToClean = @( + $tempPath, + "C:\Program Files\Microsoft Entra private network connector", + "C:\Program Files\Microsoft Entra private network connector updater" + ) + + foreach ($folder in $foldersToClean) { + if (Test-Path -Path $folder) { + try { + Remove-Item -Path $folder -Recurse -Force -ErrorAction Stop + Write-Host "Successfully removed: $folder" -ForegroundColor Green + } + catch { + Write-Warning "Could not fully remove '$folder': $_" + } + } } - } - Write-Output "Access Token that you acquired is available in $tokenPath." - Write-Output "Please ensure no additional spaces are introduced when copying token to marketplace input form. Introducing spaces can change the token and can cause failures" + Write-Host "`n========================================" -ForegroundColor Green + Write-Host "SUCCESS!" -ForegroundColor Green + Write-Host "========================================" -ForegroundColor Green + Write-Output "Access Token that you acquired is available in $tokenPath." + Write-Output "Please ensure no additional spaces are introduced when copying token to marketplace input form. Introducing spaces can change the token and can cause failures" + Write-Host "========================================`n" -ForegroundColor Green + } + else { + Write-Error "Authentication failed: result, access token, or tenant ID was null. No token has been saved. Please re-run the script and complete the interactive login." + Set-Location -Path "C:\" -ErrorAction SilentlyContinue + throw "Authentication failed" + } } else { - Write-Error "Authentication failed: result, access token, or tenant ID was null. No token has been saved. Please re-run the script and complete the interactive login." - Set-Location -Path "C:\" - return + Write-Error "The required module is not made available at path: $folderPath" + Write-Host "This could be related to left over state from previous installation of connector on this machine." -ForegroundColor Yellow + Write-Host "You can try to go to c:\temp\ and double click the MicrosoftEntraPrivateNetworkConnectorInstaller.exe file. Click Uninstall if visible. This can clean the state." -ForegroundColor Yellow + Write-Host "If you don't have .exe file, you can download it from https://download.msappproxy.net/Subscription/d3c8b69d-6bf7-42be-a529-3fe9c2e70c90/Connector/DownloadConnectorInstaller and double click it to Uninstall" -ForegroundColor Yellow + Write-Host "Try Again after the state is clean" -ForegroundColor Yellow + throw "Module not found at expected path" + } +} +catch { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "SCRIPT FAILED" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Error "An error occurred: $_" + Write-Host "========================================`n" -ForegroundColor Red + + # Attempt cleanup on error + Write-Host "Attempting cleanup..." -ForegroundColor Yellow + Set-Location -Path "C:\" -ErrorAction SilentlyContinue + + $foldersToCleanOnError = @( + $tempPath, + "C:\Program Files\Microsoft Entra private network connector", + "C:\Program Files\Microsoft Entra private network connector updater" + ) + + foreach ($folder in $foldersToCleanOnError) { + if (Test-Path -Path $folder) { + try { + Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue + Write-Host "Cleaned up: $folder" -ForegroundColor Green + } + catch { + Write-Warning "Could not clean up '$folder'. You may need to manually remove it." + } + } } + + throw } -else { - Write-Host "The required module is not made available at path: $folderPath" - Write-Host "This could be related to left over state from previous installation of connector on this machine." - Write-Host "You can try to go to c:\temp\ and double click the MicrosoftEntraPrivateNetworkConnectorInstaller.exe file. Click Uninstall if visible. This can clean the state." - Write-Host "If you don't have .exe file, you can download it from https://download.msappproxy.net/Subscription/d3c8b69d-6bf7-42be-a529-3fe9c2e70c90/Connector/DownloadConnectorInstaller and double click it to Uninstall" - Write-Host "Try Again after the state is clean" - return +finally { + Stop-Transcript + Write-Host "Log file saved to: $transcriptPath" -ForegroundColor Cyan } ``` From 88a776c73ae0150475c627634b9aa0460667f94c Mon Sep 17 00:00:00 2001 From: Michael Morten Sonne | Microsoft MVP <49366751+michaelmsonne@users.noreply.github.com> Date: Thu, 18 Jun 2026 08:46:46 +0200 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../scripts/powershell-get-token.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/global-secure-access/scripts/powershell-get-token.md b/docs/global-secure-access/scripts/powershell-get-token.md index 7614ee57cf3..f2bba274a68 100644 --- a/docs/global-secure-access/scripts/powershell-get-token.md +++ b/docs/global-secure-access/scripts/powershell-get-token.md @@ -365,15 +365,17 @@ catch { "C:\Program Files\Microsoft Entra private network connector updater" ) - foreach ($folder in $foldersToCleanOnError) { - if (Test-Path -Path $folder) { - try { - Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue - Write-Host "Cleaned up: $folder" -ForegroundColor Green - } - catch { - Write-Warning "Could not clean up '$folder'. You may need to manually remove it." - } +foreach ($folder in $foldersToCleanOnError) { + if ($folder -and (Test-Path -LiteralPath $folder)) { + try { + Remove-Item -LiteralPath $folder -Recurse -Force -ErrorAction Stop + Write-Host "Cleaned up: $folder" -ForegroundColor Green + } + catch { + Write-Warning "Could not clean up '$folder'. You may need to manually remove it. Error: $_" + } + } +} } }