mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-23 19:49:17 +08:00
[DSC]Improve module generation for versioned release install (#32196)
* [DSC]Generate psd1 file to include version * Don't expose build paths on release builds * Stop-Process with -Force to stop first run process
This commit is contained in:
parent
7b89482b94
commit
a24ffb3168
@ -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.
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Microsoft.PowerToys.Configure.psd1" Id="PTConf.psd1" />
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version)\Microsoft.PowerToys.Configure.psd1" Id="PTConf.psd1" />
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version)\Microsoft.PowerToys.Configure.psm1" Id="PTConf.psm1" />
|
||||
<RemoveFolder Id="RemoveThisFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemovePowerToysDscVerFolder" Directory="PowerToysDscVerFolder" On="uninstall" />
|
||||
@ -79,7 +79,7 @@
|
||||
<Directory Id="PowerToysDscFolder" Name="Microsoft.PowerToys.Configure">
|
||||
<Directory Id="PowerToysDscVerFolder" Name="$(var.Version)">
|
||||
<Component Id="PowerToysDSC" Win64="yes" Guid="C52AECA0-DA73-49B8-BB49-31EF6640FF1F">
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Microsoft.PowerToys.Configure.psd1" Id="PTConf.psd1" />
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version)\Microsoft.PowerToys.Configure.psd1" Id="PTConf.psd1" />
|
||||
<File Source="$(var.RepoDir)\src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(var.Version)\Microsoft.PowerToys.Configure.psm1" Id="PTConf.psm1" />
|
||||
</Component>
|
||||
</Directory>
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
||||
""";
|
||||
}
|
||||
}
|
||||
|
@ -50,12 +50,13 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<GeneratedDSCModule>"$(ProjectDir)..\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(Version)\Microsoft.PowerToys.Configure.psm1"</GeneratedDSCModule>
|
||||
<GeneratedDSCManifest>"$(ProjectDir)..\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\$(Version)\Microsoft.PowerToys.Configure.psd1"</GeneratedDSCManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- The following sections assume that the machine we're building on is always x64. That means we won't be able to run/inspect arm64 executables, therefore we must always execute x64 generator. -->
|
||||
|
||||
<Target Name="PostBuildAction" AfterTargets="Build" Outputs="$(GeneratedDSCModule)" Condition="'$(Platform)'!='ARM64'">
|
||||
<Exec Command=""$(OutDir)$(AssemblyName).exe" "$(SolutionDir)x64\$(Configuration)\WinUI3Apps\PowerToys.Settings.UI.Lib.dll" $(GeneratedDSCModule)" />
|
||||
<Exec Command=""$(OutDir)$(AssemblyName).exe" "$(SolutionDir)x64\$(Configuration)\WinUI3Apps\PowerToys.Settings.UI.Lib.dll" $(GeneratedDSCModule) $(GeneratedDSCManifest)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(Platform)'=='ARM64'">
|
||||
|
@ -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 <PowerToys.Settings.UI.Lib.dll path> <output path>");
|
||||
Console.WriteLine("Usage: Generator.exe <PowerToys.Settings.UI.Lib.dll path> <module output path> <manifest output path>");
|
||||
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 <PowerToys.Settings.UI.Lib.dll path> <module output path> <manifest output path>");
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user