diff --git a/doc/devdocs/settingsv2/dsc-configure.md b/doc/devdocs/settingsv2/dsc-configure.md index b70315f2f5..88950872a8 100644 --- a/doc/devdocs/settingsv2/dsc-configure.md +++ b/doc/devdocs/settingsv2/dsc-configure.md @@ -47,7 +47,7 @@ PowerToys.Settings.exe set FancyZones.FancyzonesEditorHotkey "Shift+Ctrl+Alt+F" # How DSC is implemented -We use `PowerToys.Settings.DSC.Schema.Generator` to generate the bulk of `PowerToysConfigure.psm1` file. It also uses dotnet reflection capabilities to inspect `PowerToys.Settings.UI.Lib.dll` assembly and generate properties for the modules we have. The actual generation is done as a `PowerToys.Settings.DSC.Schema.Generator.csproj` post-build action. +We use `PowerToys.Settings.DSC.Schema.Generator` to generate the bulk of `PowerToysConfigure.psm1` and `PowerToysConfigure.psd1` files. It also uses dotnet reflection capabilities to inspect `PowerToys.Settings.UI.Lib.dll` assembly and generate properties for the modules we have. The actual generation is done as a `PowerToys.Settings.DSC.Schema.Generator.csproj` post-build action. # Debugging DSC resources @@ -62,7 +62,7 @@ After that, start a new `pwsh` session and `cd` to `src\dsc\Microsoft.PowerToys. $env:PSModulePath += ";$pwd" ``` -Now build `PowerToys.sln` and **move** `src\dsc\Microsoft.PowerToys.Configure\Microsoft.PowerToys.Configure.psd1` temporarily to `src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\0.0.1\` folder, so it's located alongside with the generated `Microsoft.PowerToys.Configure.psm1`. +You should have the generated `Microsoft.PowerToys.Configure.psm1` and `Microsoft.PowerToys.Configure.psd1` files inside the `src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\0.0.1\` folder. This will allow DSC to discover our DSC Resource module. See [PSModulePath](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_psmodulepath?view=powershell-7.4#long-description) for more info. diff --git a/installer/PowerToysSetup/Core.wxs b/installer/PowerToysSetup/Core.wxs index d49b24357a..ad86a0b70f 100644 --- a/installer/PowerToysSetup/Core.wxs +++ b/installer/PowerToysSetup/Core.wxs @@ -59,7 +59,7 @@ Type="integer" Value="1" KeyPath="yes"/> - + @@ -79,7 +79,7 @@ - + diff --git a/src/dsc/Microsoft.PowerToys.Configure/Microsoft.PowerToys.Configure.psd1 b/src/dsc/Microsoft.PowerToys.Configure/Microsoft.PowerToys.Configure.psd1 deleted file mode 100644 index 40682245b8..0000000000 --- a/src/dsc/Microsoft.PowerToys.Configure/Microsoft.PowerToys.Configure.psd1 +++ /dev/null @@ -1,83 +0,0 @@ -# -# Module manifest for module 'Microsoft.PowerToys.Configure' -# -# Generated by: Microsoft Corporation -# -# Generated on: 20.11.2023 -# - -@{ - -# Script module or binary module file associated with this manifest. -RootModule = 'Microsoft.PowerToys.Configure.psm1' - -# Version number of this module. -ModuleVersion = '0.0.1' - -# ID used to uniquely identify this module -GUID = '778ed7a1-489d-4dc9-b0f2-2da3b1fe14cb' - -# Author of this module -Author = 'Microsoft Corporation' - -# Company or vendor of this module -CompanyName = 'Microsoft' - -# Copyright statement for this module -Copyright = '(c) Microsoft Corporation. All rights reserved.' - -# Description of the functionality provided by this module -Description = 'The module enables settings configuration for an installed PowerToys application.' - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = '*' - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = @() - -# Variables to export from this module -VariablesToExport = @() - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = @() - -# DSC resources to export from this module -DscResourcesToExport = @( - 'PowerToysConfigure' -) - -# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. -PrivateData = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - # Tags = @() - - # A URL to the license for this module. - # LicenseUri = '' - - # A URL to the main website for this project. - # ProjectUri = '' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - # ReleaseNotes = '' - - # Prerelease string of this module - # Prerelease = '' - - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - # RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - -} # End of PrivateData hashtable - -} - diff --git a/src/dsc/PowerToys.Settings.DSC.Schema.Generator/DSCGeneration.cs b/src/dsc/PowerToys.Settings.DSC.Schema.Generator/DSCGeneration.cs index 0ea72e5a95..877aec1e00 100644 --- a/src/dsc/PowerToys.Settings.DSC.Schema.Generator/DSCGeneration.cs +++ b/src/dsc/PowerToys.Settings.DSC.Schema.Generator/DSCGeneration.cs @@ -188,7 +188,6 @@ class {{module.Name}} { } } - """; } @@ -223,8 +222,9 @@ class {{module.Name}} { var enumsBlock = string.Join(DoubleNewLine, enumsToEmit.Select(EmitEnumDefinition)); var version = interop.CommonManaged.GetProductVersion().Replace("v", string.Empty); + var outputResult = string.Empty; - return $$""" + outputResult += $$""" #region enums enum PowerToysConfigureEnsure { Absent @@ -244,8 +244,13 @@ class {{module.Name}} { [bool] $Debug = $false {{modulesResourcePropertiesBlock}} + + """; + +#if DEBUG + // Only output PowerToysSettings local build for debug builds. No need to expose release build locations. + outputResult += $$""" [string] GetPowerToysSettingsPath() { - # Obtain PowerToys install location if ($this.Debug -eq $true) { $SettingsExePath = "{{debugSettingsPath}}" } else { @@ -253,7 +258,6 @@ class {{module.Name}} { if ($installation) { $SettingsExePath = Join-Path (Join-Path $installation.InstallLocation WinUI3Apps) PowerToys.Settings.exe - # Handle spaces in the path $SettingsExePath = "`"$SettingsExePath`"" } else { throw "PowerToys installation wasn't found." @@ -263,6 +267,27 @@ class {{module.Name}} { return $SettingsExePath } + """; +#else + outputResult += $$""" + [string] GetPowerToysSettingsPath() { + $installation = Get-CimInstance Win32_Product | Where-Object {$_.Name -eq "PowerToys (Preview)" -and $_.Version -eq "{{version}}"} + + if ($installation) { + $SettingsExePath = Join-Path (Join-Path $installation.InstallLocation WinUI3Apps) PowerToys.Settings.exe + $SettingsExePath = "`"$SettingsExePath`"" + } else { + throw "PowerToys installation wasn't found." + } + + return $SettingsExePath + } + + """; +#endif + + outputResult += $$""" + [PowerToysConfigure] Get() { $CurrentState = [PowerToysConfigure]::new() $SettingsExePath = $this.GetPowerToysSettingsPath() @@ -337,15 +362,15 @@ class {{module.Name}} { } # Stop any running PowerToys instances - Stop-Process -Name "PowerToys.Settings" -PassThru | Wait-Process - $PowerToysProcessStopped = Stop-Process -Name "PowerToys" -PassThru + Stop-Process -Name "PowerToys.Settings" -Force -PassThru | Wait-Process + $PowerToysProcessStopped = Stop-Process -Name "PowerToys" -Force -PassThru $PowerToysProcessStopped | Wait-Process foreach ($change in $ChangesToApply) { Start-Process -FilePath $SettingsExePath -Wait -Args "$change" } - # If the PowerToys was stopped, restart it. + # If the PowerToys process was stopped, restart it. if ($PowerToysProcessStopped -ne $null) { Start-Process -FilePath $SettingsExePath } @@ -353,5 +378,100 @@ class {{module.Name}} { } #endregion DscResources """; + + return outputResult; + } + + public static string EmitManifestFileContents() + { + var version = interop.CommonManaged.GetProductVersion().Replace("v", string.Empty); + var generatedDate = DateTime.Now.ToString("dd.MM.yyyy", CultureInfo.InvariantCulture); + + return $$""" + # + # Module manifest for module 'Microsoft.PowerToys.Configure' + # + # Generated by: Microsoft Corporation + # + # Generated on: {{generatedDate}} + # + + @{ + + # Script module or binary module file associated with this manifest. + RootModule = 'Microsoft.PowerToys.Configure.psm1' + + # Version number of this module. + ModuleVersion = '{{version}}' + + # ID used to uniquely identify this module + GUID = '778ed7a1-489d-4dc9-b0f2-2da3b1fe14cb' + + # Author of this module + Author = 'Microsoft Corporation' + + # Company or vendor of this module + CompanyName = 'Microsoft' + + # Copyright statement for this module + Copyright = '(c) Microsoft Corporation. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'The module enables settings configuration for an installed PowerToys application.' + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = '*' + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = @() + + # Variables to export from this module + VariablesToExport = @() + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @() + + # DSC resources to export from this module + DscResourcesToExport = @( + 'PowerToysConfigure' + ) + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + } + + + """; } } diff --git a/src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj b/src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj index e13717e8f8..5264f2aafb 100644 --- a/src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj +++ b/src/dsc/PowerToys.Settings.DSC.Schema.Generator/PowerToys.Settings.DSC.Schema.Generator.csproj @@ -50,12 +50,13 @@ "$(ProjectDir)..\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(Version)\Microsoft.PowerToys.Configure.psm1" + "$(ProjectDir)..\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(Version)\Microsoft.PowerToys.Configure.psd1" - + diff --git a/src/dsc/PowerToys.Settings.DSC.Schema.Generator/Program.cs b/src/dsc/PowerToys.Settings.DSC.Schema.Generator/Program.cs index 43042f8e69..dc1ac49a63 100644 --- a/src/dsc/PowerToys.Settings.DSC.Schema.Generator/Program.cs +++ b/src/dsc/PowerToys.Settings.DSC.Schema.Generator/Program.cs @@ -13,21 +13,35 @@ internal sealed class Program { public static int Main(string[] args) { - if (args.Length != 2) + if (args.Length < 2) { - Console.WriteLine("Usage: Generator.exe "); + Console.WriteLine("Usage: Generator.exe "); return 1; } var dllPath = args[0]; - var outputPath = args[1]; + var moduleOutputPath = args[1]; + var manifestOutputPath = string.Empty; - bool documentationMode = Path.GetExtension(outputPath) == ".md"; - bool sampleMode = Path.GetExtension(outputPath) == ".yaml"; + bool documentationMode = Path.GetExtension(moduleOutputPath) == ".md"; + bool sampleMode = Path.GetExtension(moduleOutputPath) == ".yaml"; + + if (!documentationMode && !sampleMode) + { + if (args.Length < 3) + { + Console.WriteLine("Usage: Generator.exe "); + return 1; + } + else + { + manifestOutputPath = args[2]; + } + } try { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + Directory.CreateDirectory(Path.GetDirectoryName(moduleOutputPath)); var assembly = Assembly.LoadFrom(dllPath); var moduleSettings = Introspection.ParseModuleSettings(assembly); @@ -46,11 +60,13 @@ internal sealed class Program } else { + var manifestFileContents = DSCGeneration.EmitManifestFileContents(); + File.WriteAllText(manifestOutputPath, manifestFileContents); var debugSettingsPath = Path.Combine(Directory.GetParent(dllPath).FullName, "PowerToys.Settings.exe"); outputFileContents = DSCGeneration.EmitModuleFileContents(moduleSettings, generalSettings, debugSettingsPath); } - File.WriteAllText(outputPath, outputFileContents); + File.WriteAllText(moduleOutputPath, outputFileContents); } catch (Exception ex) {