Public/Geolocation/Request-LocationPermission.ps1


function Request-LocationPermission {
  <#
.SYNOPSIS
    Requests location access permission from the user for Wi-Fi-related functions.
 
.DESCRIPTION
    The `Request-LocationPermission` function checks whether the script has permission to access
    the device's location data. If permission is not granted, it prompts the user to enable location
    access via the Windows privacy settings. If the user agrees, the function opens the location
    privacy settings window. The function waits for the user to grant permission and handles timeouts.
 
    The function also includes a silent mode (`-Silent` switch), which bypasses the user prompt
    and immediately returns the result if the permission is already granted.
 
.PARAMETER Silent
    Optional. If specified, the function will not prompt the user for permission and will return
    the current permission status immediately. If permission is already granted, it returns the status.
 
.EXAMPLE
    Request-LocationPermission
    Requests location access from the user. If denied, the function will terminate.
 
.EXAMPLE
    Request-LocationPermission -Silent
    Checks if location access is granted without asking the user and returns the result.
 
.NOTES
    - The function retries for 30 seconds to detect if the user grants permission.
    - If access is not granted within the timeout period, an error is displayed.
#>

  [outputType([Windows.Devices.Geolocation.GeolocationAccessStatus])]
  param(
    [Switch]$Silent
  )
  $Type = ([Windows.Devices.Geolocation.GeolocationAccessStatus])
  $AsyncOp = ([Windows.Devices.Geolocation.Geolocator]::RequestAccessAsync())
  $Result = Await -WinRtTask $AsyncOp -ResultType $Type

  # 1. Already have access? Then finish immediately.
  if ($Result -eq [Windows.Devices.Geolocation.GeolocationAccessStatus]::Allowed -or $Silent) {
    return $Result
  }

  # 2. No access: Ask the user
  Write-Host "`n[!] Location access needed for this module." -ForegroundColor Yellow
  $msg = "PowerShell needs location access for WiFi functions.`n`nWould you like to open privacy settings now?"
  #$shell = New-Object -ComObject WScript.Shell

  # 4 = Yes/No buttons, 32 = Question icon, 10 = Seconds timeout
  #$response = $shell.Popup($msg, 10, "Location Access Required", 4 + 32)
  $Response = [System.Windows.MessageBox]::Show($msg, "Location Access Required", [System.Windows.MessageBoxButton]::YesNo, [System.Windows.MessageBoxImage]::Question)
  #$choice = Read-Host "Do you want to open the Windows settings to change this? (y/n)"
  if ($response -ne [System.Windows.MessageBoxResult]::Yes) {
    # USER SAYS NO -> Stop the function here
    Write-Warning "User denied access. Function terminated."
    return $Result # Returns 'Denied' to the caller
  }

  # 3. User says YES -> Open settings and start the loop
  Start-Process "ms-settings:privacy-location" #AllowDesktopApps"

  Write-Host "`n[!] ACTION REQUIRED IN THE OPENED WINDOW:" -ForegroundColor Yellow
  Write-Host ">>> Scroll Down And Allow Desktop Apps Access To The Location <<<" -ForegroundColor Cyan -BackgroundColor Black
  Write-Host ">>> Check that the switch on top is also turned on <<<`n" -ForegroundColor Red
  Write-Host "Waiting for access (press CTRL+C to exit)..." -NoNewline

  $MaxTries = 30 # Stop after 30 seconds if nothing happens (timeout)

  while ($Result -ne [Windows.Devices.Geolocation.GeolocationAccessStatus]::Allowed -and $MaxTries -gt 0) {
    Write-Host "." -NoNewline
    Start-Sleep -Seconds 1
    # note: $AsyncOp can become dirty if it's passed as [ref]
    $AsyncOp = ([Windows.Devices.Geolocation.Geolocator]::RequestAccessAsync())
    $Result = AwaitWithCancel -WinRtTask $AsyncOp -ResultType $Type
    $MaxTries--
  }
  if ($Result -ne [Windows.Devices.Geolocation.GeolocationAccessStatus]::Allowed) {
    Write-Error "`nTime-out: access blocked"
  } else {
    Write-Host "`nAccess allowed! Let's continue ..." -ForegroundColor Green
  }
  return $Result
}