From 353cfc943c232d36c072ee28008089cdd302a373 Mon Sep 17 00:00:00 2001 From: Gijs Reijn Date: Wed, 15 Jan 2025 08:39:05 +0100 Subject: [PATCH] New class AppsForWebsites --- .../AppsForWebsites.md | 38 +++++ .../OfflineMap.md | 38 ----- .../Microsoft.Windows.Setting.Apps.psd1 | 6 +- .../Microsoft.Windows.Setting.Apps.psm1 | 143 ++++++++++++++++++ 4 files changed, 185 insertions(+), 40 deletions(-) create mode 100644 resources/Help/Microsoft.Windows.Setting.Apps/AppsForWebsites.md delete mode 100644 resources/Help/Microsoft.Windows.Setting.Apps/OfflineMap.md diff --git a/resources/Help/Microsoft.Windows.Setting.Apps/AppsForWebsites.md b/resources/Help/Microsoft.Windows.Setting.Apps/AppsForWebsites.md new file mode 100644 index 0000000..5e1ca10 --- /dev/null +++ b/resources/Help/Microsoft.Windows.Setting.Apps/AppsForWebsites.md @@ -0,0 +1,38 @@ +--- +external help file: Microsoft.Windows.Setting.Apps.psm1-Help.xml +Module Name: Microsoft.Windows.Setting.Apps +ms.date: 01/10/2025 +online version: +schema: 2.0.0 +title: AppsForWebsites +--- + +# AppsForWebsites + +## SYNOPSIS + +The `AppsForWebsites` DSC Resource allows you to manage application associations for websites on Windows. + +## DESCRIPTION + +The `AppsForWebsites` DSC Resource allows you to manage application associations for websites on Windows. + +## PARAMETERS + +| **Parameter** | **Attribute** | **DataType** | **Description** | **Allowed Values** | +| ------------- | -------------- | ------------ | ------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| `LinkUri` | Key, Mandatory | String | The link URI. | Any valid URI that is associated with an URI handler | +| `Exist` | Optional | Boolean | Indicates whether the application association should be turned on or off. Default is `True` | `True` or `False` | + +## EXAMPLES + +### EXAMPLE 1 - Turn off Adobe Acrobat to open links in the app + +```powershell +Invoke-DscResource -ModuleName Microsoft.Windows.Setting.Apps -Name AppsForWebsites -Method Set -Property @{ + LinkUri = 'acrobat.adobe.com' + Exist = $false +} + +# This example ensures that the application association for 'acrobat.adobe.com' is turned off. +``` diff --git a/resources/Help/Microsoft.Windows.Setting.Apps/OfflineMap.md b/resources/Help/Microsoft.Windows.Setting.Apps/OfflineMap.md deleted file mode 100644 index 68dfb63..0000000 --- a/resources/Help/Microsoft.Windows.Setting.Apps/OfflineMap.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -external help file: Microsoft.Windows.Setting.Apps.psm1-Help.xml -Module Name: Microsoft.Windows.Setting.Apps -ms.date: 01/10/2025 -online version: -schema: 2.0.0 -title: OfflineMap ---- - -# OfflineMap - -## SYNOPSIS - -The `OfflineMap` DSC Resource allows you to manage offline maps on Windows. - -## DESCRIPTION - -The `OfflineMap` DSC Resource allows you to manage offline maps on Windows. - -## PARAMETERS - -| **Parameter** | **Attribute** | **DataType** | **Description** | **Allowed Values** | -| -------------------- | -------------- | ------------ | ----------------------------------------------------------------------------------------------------- | --------------------- | -| `OfflineMap` | Key, Mandatory | String | The name of the offline map. | Any valid map address located from Settings -> Apps -> Offline maps | -| `Exist` | Optional | Boolean | Indicates whether the offline map should exist. Defaults to `True` | `True` or `False` | - -## EXAMPLES - -### EXAMPLE 1 - Install map for France offline - -```powershell -Invoke-DscResource -ModuleName Microsoft.Windows.Setting.Apps -Name OfflineMap -Method Set -Property @{ - DownloadMap = 'France'; - Exist = $true; -} - -# This example ensures that the offline map of France exists on your local machine. -``` diff --git a/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psd1 b/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psd1 index e0e1a81..11161bb 100644 --- a/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psd1 +++ b/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psd1 @@ -11,14 +11,16 @@ PowerShellVersion = '7.4' DscResourcesToExport = @( 'AdvancedAppSettings', - 'AppExecutionAliases' + 'AppExecutionAliases', + 'AppsForWebsites' ) PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. Tags = @( 'PSDscResource_AdvancedAppSettings', - 'PSDscResource_AppExecutionAliases' + 'PSDscResource_AppExecutionAliases', + 'PSDscResource_AppsForWebsites' ) # A URL to the license for this module. diff --git a/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psm1 b/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psm1 index 6344acb..1397624 100644 --- a/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psm1 +++ b/resources/Microsoft.Windows.Setting.Apps/Microsoft.Windows.Setting.Apps.psm1 @@ -2,6 +2,8 @@ if ([string]::IsNullOrEmpty($env:TestRegistryPath)) { $global:ExplorerPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer' $global:CdpPath = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\CDP\' $global:ArchiveAppPath = ('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\InstallService\Stubification\{0}\' -f ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value) + $global:AppUriHandlerPath = 'Registry::HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Extensions\windows.appUriHandler\' + $global:AppUrlAssociationsPath = 'HKCU:\Software\Microsoft\Windows\Shell\Associations\AppUrlAssociations\' } else { $global:ExplorerPath = $global:CdpPath = $global:ArchiveAppPath = $env:TestRegistryPath @@ -162,6 +164,57 @@ function Set-AppExecutionAlias { } } } + +function New-RandomHash { + param ( + [int]$length = 12 + ) + + $bytes = New-Object byte[] $length + [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes) + $hash = [Convert]::ToBase64String($bytes) + + return $hash.Substring(0, $length) +} + +function Set-AppUrlAssociations { + param ( + [Parameter(Mandatory)] + [string]$LinkUri, + + [Parameter()] + [switch] $Exist + ) + + $protocolHandlerId = Get-ChildItem -Path "$global:AppUriHandlerPath\$LinkUri" | Select-Object -ExpandProperty PSChildName + $userChoicePath = Join-Path $global:AppUrlAssociationsPath $LinkUri $protocolHandlerId 'UserChoice' + + $pathCreate = $false + if (-not (Test-Path $userChoicePath -ErrorAction SilentlyContinue)) { + New-Item -Path $userChoicePath -Force | Out-Null + + # If the key was just created, set enabled + $pathCreate = $true + } + + if ($Exist.IsPresent) { + if ($pathCreate) { + New-ItemProperty -Path $userChoicePath -Name 'Enabled' -Value 1 -PropertyType DWord | Out-Null + New-ItemProperty -Path $userChoicePath -Name 'Hash' -Value (New-RandomHash) -PropertyType String | Out-Null + } else { + Set-ItemProperty -Path $userChoicePath -Name 'Enabled' -Value 1 + Set-ItemProperty -Path $userChoicePath -Name 'Hash' -Value (New-RandomHash) + } + } else { + if ($pathCreate) { + New-ItemProperty -Path $userChoicePath -Name 'Enabled' -Value 0 -PropertyType DWord | Out-Null + New-ItemProperty -Path $userChoicePath -Name 'Hash' -Value (New-RandomHash) -PropertyType String | Out-Null + } else { + Set-ItemProperty -Path $userChoicePath -Name 'Enabled' -Value 0 + Set-ItemProperty -Path $userChoicePath -Name 'Hash' -Value (New-RandomHash) + } + } +} #endregion Functions #region Classes @@ -338,4 +391,94 @@ class AppExecutionAliases { } } } + +<# +.SYNOPSIS + The `AppsForWebsites` DSC Resource allows you to manage application associations for websites on Windows. + +.PARAMETER LinkUri + The link URI. This is a key property. + +.PARAMETER Exist + Indicates whether the application association should be turned on or off. Default is true. + +.EXAMPLE + PS C:\> Invoke-DscResource -ModuleName Microsoft.Windows.Setting.Apps -Name AppsForWebsites -Method Set -Property @{ + LinkUri = 'acrobat.adobe.com' + Exist = $false + } + + This example ensures that the application association for 'acrobat.adobe.com' is turned off. +#> +[DscResource()] +class AppsForWebsites { + [DscProperty(Key, Mandatory)] + [string] $LinkUri + + [DscProperty()] + [bool] $Exist = $true + + AppsForWebsites () { + } + + AppsForWebsites ([string] $LinkUri) { + $this.LinkUri = $LinkUri + $this.Exist = [AppsForWebsites]::TestAppUrlAssociations($LinkUri) + } + + [AppsForWebsites] Get() { + if ([String]::IsNullOrWhiteSpace($this.LinkUri)) { + throw 'A value must be provided for AppsForWebsites::LinkUri' + } + + if (-not ([AppsForWebsites]::TestAppUriHandler($this.LinkUri))) { + throw [System.Configuration.ConfigurationException]::new("The AppUriHandler for '{0}' does not exist. Please install the application installer." -f $this.LinkUri) + } + + $currentState = [AppsForWebsites]::new($this.LinkUri) + return $currentState + } + + [bool] Test() { + $currentState = $this.Get() + + if ($this.Exist -ne $currentState.Exist) { + return $false + } + + return $true + } + + [void] Set() { + if (-not ($this.Test())) { + Set-AppUrlAssociations -LinkUri $this.LinkUri -Exist:$this.Exist + } + } + + #region AppsForWebsites helper functions + static [bool] TestAppUriHandler ([string] $LinkUri) { + $appUriHandler = Get-ChildItem -Path $global:AppUriHandlerPath | Where-Object { $_.PSChildName -eq $LinkUri } + + return ($null -ne $appUriHandler) + } + + static [bool] TestAppUrlAssociations ([string] $LinkUri) { + $association = Get-ChildItem -Path $global:AppUrlAssociationsPath | Where-Object { $_.PSChildName -eq $LinkUri } + + if ($null -ne $association) { + $protocolHandlerId = Get-ChildItem -Path "$global:AppUriHandlerPath\$LinkUri" | Select-Object -ExpandProperty PSChildName + + $userChoicePath = Join-Path $global:AppUrlAssociationsPath $LinkUri $protocolHandlerId 'UserChoice' + + $enabledValue = 0 + if (Test-Path -Path $userChoicePath -ErrorAction SilentlyContinue) { + $enabledValue = Get-ItemPropertyValue -Path $userChoicePath -Name 'Enabled' -ErrorAction SilentlyContinue + } + + return ($enabledValue -eq 1) + } + + return $true # If the key does not exist, the default value is true. + } +} #endregion Classes