Compare commits

..

1 Commits

Author SHA1 Message Date
Shawn Yuan (from Dev Box)
73903ec4fe Fixed AP custom hotkey issue
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-12-15 11:51:54 +08:00
51 changed files with 645 additions and 3036 deletions

View File

@@ -111,7 +111,6 @@ AUTORADIOBUTTON
Autorun
AUTOTICKS
AUTOUPDATE
autopf
AValid
AWAYMODE
azcliversion
@@ -268,8 +267,6 @@ CONFIGW
CONFLICTINGMODIFIERKEY
CONFLICTINGMODIFIERSHORTCUT
CONOUT
Contoso
coreclr
constexpr
contentdialog
contentfiles
@@ -754,7 +751,6 @@ IFACEMETHOD
IFACEMETHODIMP
ifd
IGNOREUNKNOWN
ignoreversion
IGo
iid
IIM
@@ -781,7 +777,6 @@ INITDIALOG
INITGUID
INITTOLOGFONTSTRUCT
INLINEPREFIX
Inno
inlines
Inno
INPC
@@ -816,7 +811,6 @@ IPTC
irow
irprops
isbi
iscc
isfinite
iss
issecret
@@ -1449,7 +1443,6 @@ RECTDESTINATION
rectp
RECTSOURCE
recyclebin
recursesubdirs
Redist
Reencode
REFCLSID
@@ -1801,7 +1794,6 @@ TILEDWINDOW
TILLSON
timedate
timediff
timestamped
timeunion
timeutil
TITLEBARINFO

View File

@@ -1,7 +1,7 @@
Param(
# Using the default value of 1.7 for winAppSdkVersionNumber and useExperimentalVersion as false
[Parameter(Mandatory=$False,Position=1)]
[string]$winAppSdkVersionNumber = "1.8",
[string]$winAppSdkVersionNumber = "1.7",
# When the pipeline calls the PS1 file, the passed parameters are converted to string type
[Parameter(Mandatory=$False,Position=2)]
@@ -16,7 +16,32 @@ Param(
[string]$sourceLink = "https://microsoft.pkgs.visualstudio.com/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json"
)
function Update-NugetConfig {
param (
[string]$filePath = [System.IO.Path]::Combine($rootPath, "nuget.config")
)
Write-Host "Updating nuget.config file"
[xml]$xml = Get-Content -Path $filePath
# Add localpackages source into nuget.config
$packageSourcesNode = $xml.configuration.packageSources
$addNode = $xml.CreateElement("add")
$addNode.SetAttribute("key", "localpackages")
$addNode.SetAttribute("value", "localpackages")
$packageSourcesNode.AppendChild($addNode) | Out-Null
# Remove <packageSourceMapping> tag and its content
$packageSourceMappingNode = $xml.configuration.packageSourceMapping
if ($packageSourceMappingNode) {
$xml.configuration.RemoveChild($packageSourceMappingNode) | Out-Null
}
# print nuget.config after modification
$xml.OuterXml
# Save the modified nuget.config file
$xml.Save($filePath)
}
function Read-FileWithEncoding {
param (
@@ -46,132 +71,6 @@ function Write-FileWithEncoding {
$writer.Close()
}
function Add-NuGetSourceAndMapping {
param (
[xml]$Xml,
[string]$Key,
[string]$Value,
[string[]]$Patterns
)
# Ensure packageSources exists
if (-not $Xml.configuration.packageSources) {
$Xml.configuration.AppendChild($Xml.CreateElement("packageSources")) | Out-Null
}
$sources = $Xml.configuration.packageSources
# Add/Update Source
$sourceNode = $sources.SelectSingleNode("add[@key='$Key']")
if (-not $sourceNode) {
$sourceNode = $Xml.CreateElement("add")
$sourceNode.SetAttribute("key", $Key)
$sources.AppendChild($sourceNode) | Out-Null
}
$sourceNode.SetAttribute("value", $Value)
# Ensure packageSourceMapping exists
if (-not $Xml.configuration.packageSourceMapping) {
$Xml.configuration.AppendChild($Xml.CreateElement("packageSourceMapping")) | Out-Null
}
$mapping = $Xml.configuration.packageSourceMapping
# Remove invalid packageSource nodes (missing key or empty key)
$invalidNodes = $mapping.SelectNodes("packageSource[not(@key) or @key='']")
if ($invalidNodes) {
foreach ($node in $invalidNodes) {
$mapping.RemoveChild($node) | Out-Null
}
}
# Add/Update Mapping Source
$mappingSource = $mapping.SelectSingleNode("packageSource[@key='$Key']")
if (-not $mappingSource) {
$mappingSource = $Xml.CreateElement("packageSource")
$mappingSource.SetAttribute("key", $Key)
# Insert at top for priority
if ($mapping.HasChildNodes) {
$mapping.InsertBefore($mappingSource, $mapping.FirstChild) | Out-Null
} else {
$mapping.AppendChild($mappingSource) | Out-Null
}
}
# Double check and force attribute
if (-not $mappingSource.HasAttribute("key")) {
$mappingSource.SetAttribute("key", $Key)
}
# Update Patterns
# RemoveAll() removes all child nodes AND attributes, so we must re-set the key afterwards
$mappingSource.RemoveAll()
$mappingSource.SetAttribute("key", $Key)
foreach ($pattern in $Patterns) {
$pkg = $Xml.CreateElement("package")
$pkg.SetAttribute("pattern", $pattern)
$mappingSource.AppendChild($pkg) | Out-Null
}
}
function Resolve-WinAppSdkSplitDependencies {
Write-Host "Version $WinAppSDKVersion detected. Resolving split dependencies..."
$installDir = Join-Path $rootPath "localpackages\output"
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
# Create a temporary nuget.config to avoid interference from the repo's config
$tempConfig = Join-Path $env:TEMP "nuget_$(Get-Random).config"
Set-Content -Path $tempConfig -Value "<?xml version='1.0' encoding='utf-8'?><configuration><packageSources><clear /><add key='TempSource' value='$sourceLink' /></packageSources></configuration>"
try {
# Extract BuildTools version from Directory.Packages.props to ensure we have the required version
$dirPackagesProps = Join-Path $rootPath "Directory.Packages.props"
if (Test-Path $dirPackagesProps) {
$propsContent = Get-Content $dirPackagesProps -Raw
if ($propsContent -match '<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="([^"]+)"') {
$buildToolsVersion = $Matches[1]
Write-Host "Downloading Microsoft.Windows.SDK.BuildTools version $buildToolsVersion..."
$nugetArgsBuildTools = "install Microsoft.Windows.SDK.BuildTools -Version $buildToolsVersion -ConfigFile $tempConfig -OutputDirectory $installDir -NonInteractive -NoCache"
Invoke-Expression "nuget $nugetArgsBuildTools" | Out-Null
}
}
# Download package to inspect nuspec and keep it for the build
$nugetArgs = "install Microsoft.WindowsAppSDK -Version $WinAppSDKVersion -ConfigFile $tempConfig -OutputDirectory $installDir -NonInteractive -NoCache"
Invoke-Expression "nuget $nugetArgs" | Out-Null
# Parse dependencies from the installed folders
# Folder structure is typically {PackageId}.{Version}
$directories = Get-ChildItem -Path $installDir -Directory
$allLocalPackages = @()
foreach ($dir in $directories) {
# Match any package pattern: PackageId.Version
if ($dir.Name -match "^(.+?)\.(\d+\..*)$") {
$pkgId = $Matches[1]
$pkgVer = $Matches[2]
$allLocalPackages += $pkgId
$packageVersions[$pkgId] = $pkgVer
Write-Host "Found dependency: $pkgId = $pkgVer"
}
}
# Update repo's nuget.config to use localpackages
$nugetConfig = Join-Path $rootPath "nuget.config"
$configData = Read-FileWithEncoding -Path $nugetConfig
[xml]$xml = $configData.Content
Add-NuGetSourceAndMapping -Xml $xml -Key "localpackages" -Value $installDir -Patterns $allLocalPackages
$xml.Save($nugetConfig)
Write-Host "Updated nuget.config with localpackages mapping."
} catch {
Write-Warning "Failed to resolve dependencies: $_"
} finally {
Remove-Item $tempConfig -Force -ErrorAction SilentlyContinue
}
}
# Execute nuget list and capture the output
if ($useExperimentalVersion) {
# The nuget list for experimental versions will cost more time
@@ -213,36 +112,56 @@ if ($latestVersion) {
exit 1
}
# Resolve dependencies for 1.8+
$packageVersions = @{ "Microsoft.WindowsAppSDK" = $WinAppSDKVersion }
Resolve-WinAppSdkSplitDependencies
# Update packages.config files
Get-ChildItem -Path $rootPath -Recurse packages.config | ForEach-Object {
$file = Read-FileWithEncoding -Path $_.FullName
$content = $file.Content
if ($content -match 'package id="Microsoft.WindowsAppSDK"') {
$newVersionString = 'package id="Microsoft.WindowsAppSDK" version="' + $WinAppSDKVersion + '"'
$oldVersionString = 'package id="Microsoft.WindowsAppSDK" version="[-.0-9a-zA-Z]*"'
$content = $content -replace $oldVersionString, $newVersionString
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
Write-Host "Modified " $_.FullName
}
}
# Update Directory.Packages.props file
Get-ChildItem -Path $rootPath -Recurse "Directory.Packages.props" | ForEach-Object {
$file = Read-FileWithEncoding -Path $_.FullName
$content = $file.Content
$isModified = $false
foreach ($pkgId in $packageVersions.Keys) {
$ver = $packageVersions[$pkgId]
# Escape dots in package ID for regex
$pkgIdRegex = $pkgId -replace '\.', '\.'
$newVersionString = "<PackageVersion Include=""$pkgId"" Version=""$ver"" />"
$oldVersionString = "<PackageVersion Include=""$pkgIdRegex"" Version=""[-.0-9a-zA-Z]*"" />"
if ($content -match "<PackageVersion Include=""$pkgIdRegex""") {
# Update existing package
if ($content -notmatch [regex]::Escape($newVersionString)) {
$content = $content -replace $oldVersionString, $newVersionString
$isModified = $true
}
}
}
if ($isModified) {
if ($content -match '<PackageVersion Include="Microsoft.WindowsAppSDK"') {
$newVersionString = '<PackageVersion Include="Microsoft.WindowsAppSDK" Version="' + $WinAppSDKVersion + '" />'
$oldVersionString = '<PackageVersion Include="Microsoft.WindowsAppSDK" Version="[-.0-9a-zA-Z]*" />'
$content = $content -replace $oldVersionString, $newVersionString
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
Write-Host "Modified " $_.FullName
}
}
# Update .vcxproj files
Get-ChildItem -Path $rootPath -Recurse *.vcxproj | ForEach-Object {
$file = Read-FileWithEncoding -Path $_.FullName
$content = $file.Content
if ($content -match '\\Microsoft.WindowsAppSDK.') {
$newVersionString = '\Microsoft.WindowsAppSDK.' + $WinAppSDKVersion
$oldVersionString = '\\Microsoft.WindowsAppSDK.(?=[-.0-9a-zA-Z]*\d)[-.0-9a-zA-Z]*' #positive lookahead for at least a digit
$content = $content -replace $oldVersionString, $newVersionString
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
Write-Host "Modified " $_.FullName
}
}
# Update .csproj files
Get-ChildItem -Path $rootPath -Recurse *.csproj | ForEach-Object {
$file = Read-FileWithEncoding -Path $_.FullName
$content = $file.Content
if ($content -match 'PackageReference Include="Microsoft.WindowsAppSDK"') {
$newVersionString = 'PackageReference Include="Microsoft.WindowsAppSDK" Version="'+ $WinAppSDKVersion + '"'
$oldVersionString = 'PackageReference Include="Microsoft.WindowsAppSDK" Version="[-.0-9a-zA-Z]*"'
$content = $content -replace $oldVersionString, $newVersionString
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
Write-Host "Modified " $_.FullName
}
}
Update-NugetConfig

View File

@@ -19,7 +19,7 @@ parameters:
- name: enableMsBuildCaching
type: boolean
displayName: "Enable MSBuild Caching"
default: false
default: true
- name: runTests
type: boolean
displayName: "Run Tests"
@@ -33,7 +33,7 @@ parameters:
default: true
- name: winAppSDKVersionNumber
type: string
default: 1.8
default: 1.7
- name: useExperimentalVersion
type: boolean
default: false

View File

@@ -19,20 +19,48 @@ steps:
-useExperimentalVersion $${{ parameters.useExperimentalVersion }}
-rootPath "$(build.sourcesdirectory)"
# - task: NuGetCommand@2
# displayName: 'Restore NuGet packages (slnx)'
# inputs:
# command: 'restore'
# feedsToUse: 'config'
# nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
# restoreSolution: '$(build.sourcesdirectory)\**\*.slnx'
# includeNuGetOrg: false
- script: echo $(WinAppSDKVersion)
displayName: 'Display WinAppSDK Version Found'
- task: DotNetCoreCLI@2
displayName: 'Restore NuGet packages (dotnet)'
- task: DownloadPipelineArtifact@2
displayName: 'Download WindowsAppSDK'
inputs:
buildType: 'specific'
project: '55e8140e-57ac-4e5f-8f9c-c7c15b51929d'
definition: '104083'
buildVersionToDownload: 'latestFromBranch'
branchName: 'refs/heads/release/${{ parameters.versionNumber }}-stable'
artifactName: 'WindowsAppSDK_Nuget_And_MSIX'
targetPath: '$(Build.SourcesDirectory)\localpackages'
- script: dir $(Build.SourcesDirectory)\localpackages\NugetPackages
displayName: 'List downloaded packages'
- task: NuGetCommand@2
displayName: 'Install WindowsAppSDK'
inputs:
command: 'custom'
arguments: >
install "Microsoft.WindowsAppSDK"
-Source "$(Build.SourcesDirectory)\localpackages\NugetPackages"
-Version "$(WinAppSDKVersion)"
-OutputDirectory "$(Build.SourcesDirectory)\localpackages\output"
-FallbackSource "https://microsoft.pkgs.visualstudio.com/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json"
- task: NuGetCommand@2
displayName: 'Restore NuGet packages'
inputs:
command: 'restore'
projects: '$(build.sourcesdirectory)\**\*.slnx'
feedsToUse: 'config'
nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
workingDirectory: '$(build.sourcesdirectory)'
restoreSolution: '$(build.sourcesdirectory)\**\*.sln'
includeNuGetOrg: false
- task: NuGetCommand@2
displayName: 'Restore NuGet packages (slnx)'
inputs:
command: 'restore'
feedsToUse: 'config'
nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
restoreSolution: '$(build.sourcesdirectory)\**\*.slnx'
includeNuGetOrg: false

View File

@@ -42,11 +42,6 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<!-- Make angle-bracket includes external and turn off code analysis for them -->
<TreatAngleIncludeAsExternal>true</TreatAngleIncludeAsExternal>
<ExternalWarningLevel>TurnOffAllWarnings</ExternalWarningLevel>
<DisableAnalyzeExternal>true</DisableAnalyzeExternal>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@@ -116,11 +111,13 @@
</PropertyGroup>
<!-- Debug/Release props -->
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)'=='Debug'"
Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)'=='Release'"
Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>

View File

@@ -8,20 +8,4 @@
<PropertyGroup Label="ManifestToolOverride">
<ManifestTool Condition="Exists('$(WindowsSdkDir)bin\x64\mt.exe')">$(WindowsSdkDir)bin\x64\mt.exe</ManifestTool>
</PropertyGroup>
<!-- Auto-restore NuGet for native vcxproj (PackageReference) when building inside VS -->
<Target Name="EnsureNuGetRestoreForVcxproj" BeforeTargets="PrepareForBuild" Condition="
'$(BuildingInsideVisualStudio)' == 'true'
and '$(DesignTimeBuild)' != 'true'
and '$(RestoreInProgress)' != 'true'
and '$(MSBuildProjectExtension)' == '.vcxproj'
and '$(RestoreProjectStyle)' == 'PackageReference'
and '$(MSBuildProjectExtensionsPath)' != ''
and !Exists('$(MSBuildProjectExtensionsPath)project.assets.json')
">
<Message Importance="normal" Text="NuGet assets missing for $(MSBuildProjectName); running Restore...; IntDir=$(IntDir); BaseIntermediateOutputPath=$(BaseIntermediateOutputPath)" />
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Restore" Properties="RestoreInProgress=true" BuildInParallel="false" />
</Target>
</Project>

View File

@@ -7,8 +7,6 @@
<PackageVersion Include="AdaptiveCards.ObjectModel.WinUI3" Version="2.0.0-beta" />
<PackageVersion Include="AdaptiveCards.Rendering.WinUI3" Version="2.1.0-beta" />
<PackageVersion Include="AdaptiveCards.Templating" Version="2.0.5" />
<PackageVersion Include="boost" Version="1.87.0" TargetFramework="native" />
<PackageVersion Include="boost_regex-vc143" Version="1.87.0" TargetFramework="native" />
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" Version="0.1.251101-build.2372" />
<PackageVersion Include="Microsoft.Bot.AdaptiveExpressions.Core" Version="4.23.0" />
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
@@ -72,12 +70,10 @@
This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail.
-->
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.231216.1"/>
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.251104000" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.39" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.251106002" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.37" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
@@ -116,7 +112,6 @@
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
<PackageVersion Include="System.Management" Version="9.0.10" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Numerics.Tensors" Version="9.0.11" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Runtime.Caching" Version="9.0.10" />

View File

@@ -144,7 +144,7 @@ public sealed class AIServiceBatchIntegrationTests
switch (format)
{
case PasteFormats.CustomTextTransformation:
var transformResult = await services.CustomActionTransformService.TransformAsync(batchTestInput.Prompt, batchTestInput.Clipboard, null, CancellationToken.None, progress);
var transformResult = await services.CustomActionTransformService.TransformTextAsync(batchTestInput.Prompt, batchTestInput.Clipboard, CancellationToken.None, progress);
return DataPackageHelpers.CreateFromText(transformResult.Content ?? string.Empty);
case PasteFormats.KernelQuery:

View File

@@ -225,24 +225,6 @@ internal static class DataPackageHelpers
internal static async Task<string> GetHtmlContentAsync(this DataPackageView dataPackageView) =>
dataPackageView.Contains(StandardDataFormats.Html) ? await dataPackageView.GetHtmlFormatAsync() : string.Empty;
internal static async Task<byte[]> GetImageAsPngBytesAsync(this DataPackageView dataPackageView)
{
var bitmap = await dataPackageView.GetImageContentAsync();
if (bitmap == null)
{
return null;
}
using var pngStream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, pngStream);
encoder.SetSoftwareBitmap(bitmap);
await encoder.FlushAsync();
using var memoryStream = new MemoryStream();
await pngStream.AsStreamForRead().CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
internal static async Task<SoftwareBitmap> GetImageContentAsync(this DataPackageView dataPackageView)
{
using var stream = await dataPackageView.GetImageStreamAsync();

View File

@@ -166,8 +166,5 @@ namespace AdvancedPaste.Helpers
[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern HResult AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, [In][Out] ref uint pcchOut);
[DllImport("user32.dll", SetLastError = true)]
internal static extern uint GetClipboardSequenceNumber();
}
}

View File

@@ -46,7 +46,7 @@ public enum PasteFormats
CanPreview = true,
SupportedClipboardFormats = ClipboardFormat.Image,
IPCKey = AdvancedPasteAdditionalActions.PropertyNames.ImageToText,
KernelFunctionDescription = "Takes an image from the clipboard and extracts text using OCR. This function is intended only for explicit text extraction or OCR requests.")]
KernelFunctionDescription = "Takes an image in the clipboard and extracts all text from it using OCR.")]
ImageToText,
[PasteFormatMetadata(
@@ -118,8 +118,8 @@ public enum PasteFormats
IconGlyph = "\uE945",
RequiresAIService = true,
CanPreview = true,
SupportedClipboardFormats = ClipboardFormat.Text | ClipboardFormat.Image,
KernelFunctionDescription = "Takes user instructions and applies them to the current clipboard content (text or image). Use this function for image analysis, description, or transformation tasks beyond simple OCR.",
SupportedClipboardFormats = ClipboardFormat.Text,
KernelFunctionDescription = "Takes input instructions and transforms clipboard text (not TXT files) with these input instructions, putting the result back on the clipboard. This uses AI to accomplish the task.",
RequiresPrompt = true)]
CustomTextTransformation,
}

View File

@@ -40,15 +40,15 @@ namespace AdvancedPaste.Services.CustomActions
this.userSettings = userSettings;
}
public async Task<CustomActionTransformResult> TransformAsync(string prompt, string inputText, byte[] imageBytes, CancellationToken cancellationToken, IProgress<double> progress)
public async Task<CustomActionTransformResult> TransformTextAsync(string prompt, string inputText, CancellationToken cancellationToken, IProgress<double> progress)
{
var pasteConfig = userSettings?.PasteAIConfiguration;
var providerConfig = BuildProviderConfig(pasteConfig);
return await TransformAsync(prompt, inputText, imageBytes, providerConfig, cancellationToken, progress);
return await TransformAsync(prompt, inputText, providerConfig, cancellationToken, progress);
}
private async Task<CustomActionTransformResult> TransformAsync(string prompt, string inputText, byte[] imageBytes, PasteAIConfig providerConfig, CancellationToken cancellationToken, IProgress<double> progress)
private async Task<CustomActionTransformResult> TransformAsync(string prompt, string inputText, PasteAIConfig providerConfig, CancellationToken cancellationToken, IProgress<double> progress)
{
ArgumentNullException.ThrowIfNull(providerConfig);
@@ -57,9 +57,9 @@ namespace AdvancedPaste.Services.CustomActions
return new CustomActionTransformResult(string.Empty, AIServiceUsage.None);
}
if (string.IsNullOrWhiteSpace(inputText) && imageBytes is null)
if (string.IsNullOrWhiteSpace(inputText))
{
Logger.LogWarning("Clipboard has no usable data");
Logger.LogWarning("Clipboard has no usable text data");
return new CustomActionTransformResult(string.Empty, AIServiceUsage.None);
}
@@ -80,8 +80,6 @@ namespace AdvancedPaste.Services.CustomActions
{
Prompt = prompt,
InputText = inputText,
ImageBytes = imageBytes,
ImageMimeType = imageBytes != null ? "image/png" : null,
SystemPrompt = systemPrompt,
};

View File

@@ -12,6 +12,6 @@ namespace AdvancedPaste.Services.CustomActions
{
public interface ICustomActionTransformService
{
Task<CustomActionTransformResult> TransformAsync(string prompt, string inputText, byte[] imageBytes, CancellationToken cancellationToken, IProgress<double> progress);
Task<CustomActionTransformResult> TransformTextAsync(string prompt, string inputText, CancellationToken cancellationToken, IProgress<double> progress);
}
}

View File

@@ -12,10 +12,6 @@ namespace AdvancedPaste.Services.CustomActions
public string InputText { get; init; }
public byte[] ImageBytes { get; init; }
public string ImageMimeType { get; init; }
public string SystemPrompt { get; init; }
public AIServiceUsage Usage { get; set; } = AIServiceUsage.None;

View File

@@ -64,13 +64,21 @@ namespace AdvancedPaste.Services.CustomActions
var prompt = request.Prompt;
var inputText = request.InputText;
var imageBytes = request.ImageBytes;
if (string.IsNullOrWhiteSpace(prompt) || (string.IsNullOrWhiteSpace(inputText) && imageBytes is null))
if (string.IsNullOrWhiteSpace(prompt) || string.IsNullOrWhiteSpace(inputText))
{
throw new ArgumentException("Prompt and input content must be provided", nameof(request));
throw new ArgumentException("Prompt and input text must be provided", nameof(request));
}
var userMessageContent = $"""
User instructions:
{prompt}
Clipboard Content:
{inputText}
Output:
""";
var executionSettings = CreateExecutionSettings();
var kernel = CreateKernel();
var modelId = _config.Model;
@@ -94,32 +102,7 @@ namespace AdvancedPaste.Services.CustomActions
var chatHistory = new ChatHistory();
chatHistory.AddSystemMessage(systemPrompt);
if (imageBytes != null)
{
var collection = new ChatMessageContentItemCollection();
if (!string.IsNullOrWhiteSpace(inputText))
{
collection.Add(new TextContent($"Clipboard Content:\n{inputText}"));
}
collection.Add(new ImageContent(imageBytes, request.ImageMimeType ?? "image/png"));
collection.Add(new TextContent($"User instructions:\n{prompt}\n\nOutput:"));
chatHistory.AddUserMessage(collection);
}
else
{
var userMessageContent = $"""
User instructions:
{prompt}
Clipboard Content:
{inputText}
Output:
""";
chatHistory.AddUserMessage(userMessageContent);
}
chatHistory.AddUserMessage(userMessageContent);
var response = await chatService.GetChatMessageContentAsync(chatHistory, executionSettings, kernel, cancellationToken);
chatHistory.Add(response);

View File

@@ -67,36 +67,12 @@ public abstract class KernelServiceBase(
LogResult(cacheUsed, isSavedQuery, kernel.GetOrAddActionChain(), usage);
var outputPackage = kernel.GetDataPackage();
var hasUsableData = await outputPackage.GetView().HasUsableDataAsync();
if (kernel.GetLastError() is Exception ex)
{
// If we have an error, but the AI provided a final text response, we can ignore the error (likely a tool failure that the AI handled).
// However, if we have usable data (e.g. from a successful tool call before the error?), we might want to keep it?
// In the case of ImageToText failure, outputPackage is empty (new DataPackage), hasUsableData is false.
// So we check if there is a valid response in the chat history.
var lastMessage = chatHistory.LastOrDefault();
bool hasAssistantResponse = lastMessage != null && lastMessage.Role == AuthorRole.Assistant && !string.IsNullOrEmpty(lastMessage.Content);
if (!hasAssistantResponse && !hasUsableData)
{
throw ex;
}
// If we have a response or data, we log the error but proceed.
Logger.LogWarning($"Kernel operation encountered an error but proceeded with available response/data: {ex.Message}");
throw ex;
}
if (!hasUsableData)
{
var lastMessage = chatHistory.LastOrDefault();
if (lastMessage != null && lastMessage.Role == AuthorRole.Assistant && !string.IsNullOrEmpty(lastMessage.Content))
{
outputPackage = DataPackageHelpers.CreateFromText(lastMessage.Content);
kernel.SetDataPackage(outputPackage);
}
}
var outputPackage = kernel.GetDataPackage();
if (!(await outputPackage.GetView().HasUsableDataAsync()))
{
@@ -172,21 +148,7 @@ public abstract class KernelServiceBase(
var systemPrompt = string.IsNullOrWhiteSpace(runtimeConfig.SystemPrompt) ? DefaultSystemPrompt : runtimeConfig.SystemPrompt;
chatHistory.AddSystemMessage(systemPrompt);
chatHistory.AddSystemMessage($"Available clipboard formats: {await kernel.GetDataFormatsAsync()}");
var imageBytes = await kernel.GetDataPackageView().GetImageAsPngBytesAsync();
if (imageBytes != null)
{
var collection = new ChatMessageContentItemCollection
{
new TextContent(prompt),
new ImageContent(imageBytes, "image/png"),
};
chatHistory.AddUserMessage(collection);
}
else
{
chatHistory.AddUserMessage(prompt);
}
chatHistory.AddUserMessage(prompt);
if (ShouldModerateAdvancedAI())
{
@@ -340,16 +302,8 @@ public abstract class KernelServiceBase(
new ActionChainItem(PasteFormats.CustomTextTransformation, Arguments: new() { { PromptParameterName, fixedPrompt } }),
async dataPackageView =>
{
var imageBytes = await dataPackageView.GetImageAsPngBytesAsync();
var input = await dataPackageView.GetTextOrHtmlTextAsync();
if (string.IsNullOrEmpty(input) && imageBytes == null)
{
// If we have no text and no image, try to get text via OCR or throw if nothing exists
input = await dataPackageView.GetClipboardTextOrThrowAsync(kernel.GetCancellationToken());
}
var result = await _customActionTransformService.TransformAsync(fixedPrompt, input, imageBytes, kernel.GetCancellationToken(), kernel.GetProgress());
var input = await dataPackageView.GetClipboardTextOrThrowAsync(kernel.GetCancellationToken());
var result = await _customActionTransformService.TransformTextAsync(fixedPrompt, input, kernel.GetCancellationToken(), kernel.GetProgress());
return DataPackageHelpers.CreateFromText(result?.Content ?? string.Empty);
});
@@ -359,22 +313,15 @@ public abstract class KernelServiceBase(
new ActionChainItem(format, Arguments: new() { { PromptParameterName, prompt } }),
async dataPackageView =>
{
var imageBytes = await dataPackageView.GetImageAsPngBytesAsync();
var input = await dataPackageView.GetTextOrHtmlTextAsync();
if (string.IsNullOrEmpty(input) && imageBytes == null)
{
input = await dataPackageView.GetClipboardTextOrThrowAsync(kernel.GetCancellationToken());
}
string output = await GetPromptBasedOutput(format, prompt, input, imageBytes, kernel.GetCancellationToken(), kernel.GetProgress());
var input = await dataPackageView.GetClipboardTextOrThrowAsync(kernel.GetCancellationToken());
string output = await GetPromptBasedOutput(format, prompt, input, kernel.GetCancellationToken(), kernel.GetProgress());
return DataPackageHelpers.CreateFromText(output);
});
private async Task<string> GetPromptBasedOutput(PasteFormats format, string prompt, string input, byte[] imageBytes, CancellationToken cancellationToken, IProgress<double> progress) =>
private async Task<string> GetPromptBasedOutput(PasteFormats format, string prompt, string input, CancellationToken cancellationToken, IProgress<double> progress) =>
format switch
{
PasteFormats.CustomTextTransformation => (await _customActionTransformService.TransformAsync(prompt, input, imageBytes, cancellationToken, progress))?.Content ?? string.Empty,
PasteFormats.CustomTextTransformation => (await _customActionTransformService.TransformTextAsync(prompt, input, cancellationToken, progress))?.Content ?? string.Empty,
_ => throw new ArgumentException($"Unsupported format {format} for prompt transform", nameof(format)),
};

View File

@@ -37,7 +37,7 @@ public sealed class PasteFormatExecutor(IKernelService kernelService, ICustomAct
pasteFormat.Format switch
{
PasteFormats.KernelQuery => await _kernelService.TransformClipboardAsync(pasteFormat.Prompt, clipboardData, pasteFormat.IsSavedQuery, cancellationToken, progress),
PasteFormats.CustomTextTransformation => DataPackageHelpers.CreateFromText((await _customActionTransformService.TransformAsync(pasteFormat.Prompt, await clipboardData.GetTextOrHtmlTextAsync(), await clipboardData.GetImageAsPngBytesAsync(), cancellationToken, progress))?.Content ?? string.Empty),
PasteFormats.CustomTextTransformation => DataPackageHelpers.CreateFromText((await _customActionTransformService.TransformTextAsync(pasteFormat.Prompt, await clipboardData.GetClipboardTextOrThrowAsync(cancellationToken), cancellationToken, progress))?.Content ?? string.Empty),
_ => await TransformHelpers.TransformAsync(format, clipboardData, cancellationToken, progress),
});
}

View File

@@ -45,7 +45,6 @@ namespace AdvancedPaste.ViewModels
private CancellationTokenSource _pasteActionCancellationTokenSource;
private string _currentClipboardHistoryId;
private uint _lastClipboardSequenceNumber;
private DateTimeOffset? _currentClipboardTimestamp;
private ClipboardFormat _lastClipboardFormats = ClipboardFormat.None;
private bool _clipboardHistoryUnavailableLogged;
@@ -456,7 +455,6 @@ namespace AdvancedPaste.ViewModels
{
ResetClipboardPreview();
_currentClipboardHistoryId = null;
_lastClipboardSequenceNumber = 0;
_currentClipboardTimestamp = null;
_lastClipboardFormats = ClipboardFormat.None;
return;
@@ -479,13 +477,6 @@ namespace AdvancedPaste.ViewModels
{
bool clipboardChanged = formatsChanged;
var currentSequenceNumber = NativeMethods.GetClipboardSequenceNumber();
if (_lastClipboardSequenceNumber != currentSequenceNumber)
{
clipboardChanged = true;
_lastClipboardSequenceNumber = currentSequenceNumber;
}
if (Clipboard.IsHistoryEnabled())
{
try

View File

@@ -1,16 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -33,11 +31,6 @@
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.ImplementationLibrary" GeneratePathProperty="true" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -45,6 +38,7 @@
<DesktopCompatible>true</DesktopCompatible>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
@@ -124,6 +118,9 @@
<WarnAsError>true</WarnAsError>
</Midl>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\Display\Display.vcxproj">
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
@@ -145,5 +142,42 @@
<ResourceCompile Include="PowerToys.MeasureToolCore.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -73,13 +73,6 @@
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
<ProjectReference Include="..\MeasureToolCore\PowerToys.MeasureToolCore.vcxproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<BuildProject>true</BuildProject>
</ProjectReference>
<CsWinRTInputs Include="$(OutputPath)\PowerToys.MeasureToolCore.winmd" />
<None Include="$(OutputPath)\PowerToys.MeasureToolCore.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<ProjectReference Include="..\MeasureToolCore\PowerToys.MeasureToolCore.vcxproj" />
</ItemGroup>
</Project>

View File

@@ -1,16 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{e94fd11c-0591-456f-899f-efc0ca548336}</ProjectGuid>
@@ -23,12 +20,9 @@
<WindowsAppSdkBootstrapInitialize>false</WindowsAppSdkBootstrapInitialize>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<WindowsAppSDKVerifyTransitiveDependencies>false</WindowsAppSDKVerifyTransitiveDependencies>
<!-- Force NuGet to treat this project strictly as packages.config style -->
<RestoreProjectStyle>packages.config</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true"/>
<PackageReference Include="Microsoft.WindowsAppSDK.Foundation" GeneratePathProperty="true"/>
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true"/>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -133,18 +127,18 @@
<ItemGroup>
<ResourceCompile Include="FindMyMouse.rc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<!-- Deduplicate WindowsAppRuntimeAutoInitializer.cpp (added twice via transitive imports causing LNK4042). Remove all then add exactly once. -->
<Target Name="FixWinAppSDKAutoInitializer" BeforeTargets="ClCompile" AfterTargets="WindowsAppRuntimeAutoInitializer">
<ItemGroup>
<!-- Remove ALL injected versions of the file -->
<ClCompile Remove="@(ClCompile)" Condition="'%(Filename)' == 'WindowsAppRuntimeAutoInitializer'" />
<!-- Add ONE copy back manually -->
<ClCompile Include="$(PkgMicrosoft_WindowsAppSDK_Foundation)\include\WindowsAppRuntimeAutoInitializer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
</Target>
<ItemGroup Condition="'$(PkgMicrosoft_WindowsAppSDK)'!=''">
<!-- Remove any transitive inclusion first -->
<ClCompile Remove="$(PkgMicrosoft_WindowsAppSDK)\include\WindowsAppRuntimeAutoInitializer.cpp" />
<!-- Re-add once, but disable PCH because the SDK file doesn't include our pch.h -->
<ClCompile Include="$(PkgMicrosoft_WindowsAppSDK)\include\WindowsAppRuntimeAutoInitializer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Target Name="RemoveManagedWebView2CoreFromNativeOutDir" AfterTargets="Build">
<ItemGroup>
<_ToDelete Include="$(OutDir)Microsoft.Web.WebView2.Core.dll" />
@@ -154,4 +148,38 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Web.WebView2.1.0.2903.40\\build\\native\\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Web.WebView2.1.0.2903.40\\build\\native\\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
</packages>

View File

@@ -6,12 +6,12 @@
<!-- For MVVM Toolkit Partial Properties/AOT support -->
<LangVersion>preview</LangVersion>
<OutputPath>..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal\</OutputPath>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>$(RootNamespace).pri</ProjectPriFileName>
<!-- Disable SA1313 for Primary Constructor fields conflict https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/instance-constructors#primary-constructors -->
<NoWarn>SA1313;</NoWarn>
@@ -42,5 +42,5 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
@@ -8,19 +8,13 @@
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap3 rescap">
<!-- FOR PUBLISHING TO MICROSOFT STORE -->
<!-- When you're ready to publish your extension to Microsoft Store,you'll need to
change the values in the Identity & Properties tags below
Name = replace with Microsoft Store's Package/Identity/Name
Publisher = replace with Microsoft Store's Package/Identity/Publisher
DisplayName = replace with the reserved name from Partner Center
PublisherDisplayName = replace with Microsoft Store's Package/Properties/PublisherDisplayName
Logo = Confirm that this image exist at the path
-->
<Identity
Name="TemplateCmdPalExtension"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="0.0.1.0" />
<!-- When you're ready to publish your extension, you'll need to change the
Publisher= to match your own identity -->
<Properties>
<DisplayName>TemplateDisplayName</DisplayName>
<PublisherDisplayName>A Lone Developer</PublisherDisplayName>

View File

@@ -1,129 +0,0 @@
# Publication Setup
This folder contains tools to help you prepare your CmdPal extension for publication to the Microsoft Store and WinGet.
## Files and Folders in this Directory
### Scripts
- **`one-time-store-publishing-setup.ps1`** - Configure your project for Microsoft Store publishing (run once)
- **`build-msix-bundles.ps1`** - Build MSIX packages and create bundles for Store submission
- **`one-time-winget-publishing-setup.ps1`** - Configure your project for WinGet publishing (run once)
### Resource Folders
- **`microsoft-store-resources/`** - Contains files used for Microsoft Store publishing:
- `bundle_mapping.txt` - Auto-generated file that maps MSIX files for bundle creation
- **`winget-resources/`** - Contains templates and scripts for WinGet publishing:
- `build-exe.ps1` - Script to build standalone EXE installer
- `setup-template.iss` - Inno Setup installer template
- `release-extension.yml` - GitHub Actions workflow template (moved to `.github/workflows/` during setup)
- `Backups/` - Backup copies of configuration files (created during setup)
## Microsoft Store Quick Start
1. Open PowerShell and navigate to the Publication folder:
```powershell
cd <YourProject>\Publication
```
2. Run the one-time setup script:
```powershell
.\one-time-store-publishing-setup.ps1
```
3. Follow the prompts to enter your Microsoft Store information from Partner Center:
- Package Identity Name
- Publisher Certificate
- Display Name
- Publisher Display Name
The script will update your `Package.appxmanifest` with Store-specific values.
4. Once configured, build your bundle:
```powershell
.\build-msix-bundles.ps1
```
This script will:
- Build x64 and ARM64 MSIX packages
- Automatically update `microsoft-store-resources\bundle_mapping.txt` with correct paths
- Create a combined MSIX bundle
- Display the bundle location when complete
5. Upload the resulting `.msixbundle` file from `microsoft-store-resources\` to Partner Center
## Troubleshooting
### makeappx.exe not found
The build script requires the Windows SDK. Install it via:
- Visual Studio Installer (Individual Components → Windows SDK)
- [Standalone Windows SDK](https://developer.microsoft.com/windows/downloads/windows-sdk/)
### Build errors
Ensure you have:
- .NET 9.0 SDK installed
- Windows SDK 10.0.26100.0 or compatible version
- No other instances of Visual Studio building the project
### Bundle creation fails
Check that:
- Both x64 and ARM64 builds completed successfully
- `microsoft-store-resources\bundle_mapping.txt` paths are correct (auto-updated by script)
- No file locks on the MSIX files
## WinGet Quick Start
1. Open PowerShell and navigate to the Publication folder:
```powershell
cd <YourProject>\Publication
```
2. Run the one-time setup script:
```powershell
.\one-time-winget-publishing-setup.ps1
```
3. Follow the prompts to enter:
- GitHub Repository URL (where releases will be published)
- Developer/Publisher Name
The script will:
- Configure `winget-resources\build-exe.ps1` with your extension details
- Configure `winget-resources\setup-template.iss` with your extension information
- Move `release-extension.yml` to `.github\workflows\` in your repository root
4. Commit and push changes to GitHub:
```powershell
git add .
git commit -m "Configure extension for WinGet publishing"
git push
```
5. Trigger the GitHub Action to build and release:
```powershell
gh workflow run release-extension.yml --ref main -f "release_notes=**First Release of <ExtensionName> Extension for Command Palette**
The inaugural release of the <ExtensionName> for Command Palette..."
```
Or create a release manually through the GitHub web interface.
## Additional Resources
- [Command Palette Extension Publishing Documentation](https://learn.microsoft.com/en-us/windows/powertoys/command-palette/publish-extension)
- [Microsoft Store Publishing Guide](https://learn.microsoft.com/windows/apps/publish/)

View File

@@ -1,570 +0,0 @@
# Build MSIX Bundles Script for CmdPal Extension
# This script automates the process of building MSIX packages for x64 and ARM64 architectures
# and creating an MSIX bundle for distribution
# Version: 1.0
#Requires -Version 5.1
# Enable strict mode for better error detection
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " CmdPal Extension MSIX Builder" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
# Determine project root (parent of Publication folder)
$projectRoot = Split-Path -Parent $PSScriptRoot
$projectName = Split-Path -Leaf $projectRoot
Write-Host "Project Configuration:" -ForegroundColor Yellow
Write-Host " Project Root: $projectRoot" -ForegroundColor Gray
Write-Host " Project Name: $projectName" -ForegroundColor Gray
Write-Host ""
# Verify we're in the right location
$csprojPath = Join-Path $projectRoot "$projectName.csproj"
$manifestPath = Join-Path $projectRoot "Package.appxmanifest"
if (-not (Test-Path $csprojPath)) {
Write-Host "ERROR: Could not find .csproj file at: $csprojPath" -ForegroundColor Red
Write-Host ""
Write-Host "This script must be run from the Publication folder within your project." -ForegroundColor Yellow
Write-Host "Expected structure:" -ForegroundColor Gray
Write-Host " <ProjectRoot>\" -ForegroundColor Gray
Write-Host " <ProjectName>.csproj" -ForegroundColor Gray
Write-Host " Publication\" -ForegroundColor Gray
Write-Host " build-msix-bundles.ps1 (this script)" -ForegroundColor Gray
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not (Test-Path $manifestPath)) {
Write-Host "ERROR: Could not find Package.appxmanifest at: $manifestPath" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [OK] Project files validated" -ForegroundColor Green
Write-Host ""
# Extract version from Package.appxmanifest
Write-Host "Reading package information..." -ForegroundColor Cyan
try {
[xml]$manifest = Get-Content $manifestPath -ErrorAction Stop
$packageName = $manifest.Package.Identity.Name
$packageVersion = $manifest.Package.Identity.Version
Write-Host " Package Name: $packageName" -ForegroundColor White
Write-Host " Version: $packageVersion" -ForegroundColor White
Write-Host ""
}
catch {
Write-Host "ERROR: Could not read Package.appxmanifest: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# Ask user what to build
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Build Options" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "What would you like to build?" -ForegroundColor Yellow
Write-Host ""
Write-Host " [1] x64 MSIX only" -ForegroundColor White
Write-Host " [2] ARM64 MSIX only" -ForegroundColor White
Write-Host " [3] Complete Bundle (x64 + ARM64 + Bundle file)" -ForegroundColor White
Write-Host ""
Write-Host "Enter your choice (1-3): " -ForegroundColor Yellow -NoNewline
$buildChoice = Read-Host
Write-Host ""
# Validate choice
if ($buildChoice -notmatch '^[1-3]$') {
Write-Host "ERROR: Invalid choice. Please enter 1, 2, or 3." -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# Determine what to build
$buildX64 = $false
$buildARM64 = $false
$createBundle = $false
switch ($buildChoice) {
"1" {
$buildX64 = $true
Write-Host "Building: x64 MSIX only" -ForegroundColor Cyan
}
"2" {
$buildARM64 = $true
Write-Host "Building: ARM64 MSIX only" -ForegroundColor Cyan
}
"3" {
$buildX64 = $true
$buildARM64 = $true
$createBundle = $true
Write-Host "Building: Complete Bundle (x64 + ARM64 + Bundle)" -ForegroundColor Cyan
}
}
Write-Host ""
# Clean previous builds (optional)
Write-Host "Do you want to clean previous builds? (Y/N): " -ForegroundColor Yellow -NoNewline
$cleanBuilds = Read-Host
if ($cleanBuilds -match '^[Yy]') {
Write-Host ""
Write-Host "Cleaning previous builds..." -ForegroundColor Cyan
$appPackagesPath = Join-Path $projectRoot "AppPackages"
if (Test-Path $appPackagesPath) {
try {
Remove-Item $appPackagesPath -Recurse -Force -ErrorAction Stop
Write-Host " [OK] Cleaned AppPackages folder" -ForegroundColor Green
}
catch {
Write-Host " [WARNING] Could not clean AppPackages: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
# Clean old bundles in microsoft-store-resources folder
$microsoftStoreResourcesPath = Join-Path $PSScriptRoot "microsoft-store-resources"
if (Test-Path $microsoftStoreResourcesPath) {
$oldBundles = Get-ChildItem $microsoftStoreResourcesPath -Filter "*.msixbundle" -ErrorAction SilentlyContinue
if ($oldBundles) {
foreach ($bundle in $oldBundles) {
try {
Remove-Item $bundle.FullName -Force -ErrorAction Stop
Write-Host " [OK] Removed old bundle: $($bundle.Name)" -ForegroundColor Green
}
catch {
Write-Host " [WARNING] Could not remove $($bundle.Name): $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
}
Write-Host ""
}
else {
Write-Host ""
}
# Track built files for summary
$builtFiles = @()
$x64Msix = $null
$arm64Msix = $null
# Build x64 MSIX (if requested)
if ($buildX64) {
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Building x64 MSIX Package" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Running: dotnet build (x64)..." -ForegroundColor Yellow
Write-Host "This may take a few seconds" -ForegroundColor Yellow
Write-Host ""
Push-Location $projectRoot
try {
$buildOutput = & dotnet build --configuration Release -p:GenerateAppxPackageOnBuild=true -p:Platform=x64 -p:AppxPackageDir="AppPackages\x64\" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "ERROR: x64 build failed with exit code $LASTEXITCODE" -ForegroundColor Red
Write-Host ""
Write-Host "Build output:" -ForegroundColor Gray
$buildOutput | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
Pop-Location
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [SUCCESS] x64 build completed" -ForegroundColor Green
Write-Host ""
}
catch {
Write-Host ""
Write-Host "ERROR: x64 build failed: $($_.Exception.Message)" -ForegroundColor Red
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
finally {
Pop-Location
}
}
# Build ARM64 MSIX (if requested)
if ($buildARM64) {
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Building ARM64 MSIX Package" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Running: dotnet build (ARM64)..." -ForegroundColor Yellow
Write-Host "This may take a few seconds" -ForegroundColor Yellow
Write-Host ""
Push-Location $projectRoot
try {
$buildOutput = & dotnet build --configuration Release -p:GenerateAppxPackageOnBuild=true -p:Platform=ARM64 -p:AppxPackageDir="AppPackages\ARM64\" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "ERROR: ARM64 build failed with exit code $LASTEXITCODE" -ForegroundColor Red
Write-Host ""
Write-Host "Build output:" -ForegroundColor Gray
$buildOutput | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
Pop-Location
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [SUCCESS] ARM64 build completed" -ForegroundColor Green
Write-Host ""
}
catch {
Write-Host ""
Write-Host "ERROR: ARM64 build failed: $($_.Exception.Message)" -ForegroundColor Red
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
finally {
Pop-Location
}
}
# Locate MSIX files (if bundle creation is needed or for summary)
if ($createBundle -or $buildX64 -or $buildARM64) {
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Locating MSIX Files" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Push-Location $projectRoot
try {
$msixFiles = Get-ChildItem "AppPackages" -Recurse -Filter "*.msix" -ErrorAction SilentlyContinue
if (-not $msixFiles) {
# Try alternate location
Write-Host " MSIX files not found in AppPackages, checking bin folder..." -ForegroundColor Yellow
$msixFiles = Get-ChildItem "bin" -Recurse -Filter "*.msix" -ErrorAction SilentlyContinue
}
if ($buildX64 -and $buildARM64 -and $createBundle -and (-not $msixFiles -or $msixFiles.Count -lt 2)) {
Write-Host "ERROR: Could not find both x64 and ARM64 MSIX files" -ForegroundColor Red
Write-Host ""
Write-Host "Expected files:" -ForegroundColor Gray
Write-Host " - ${packageName}_${packageVersion}_x64.msix" -ForegroundColor Gray
Write-Host " - ${packageName}_${packageVersion}_arm64.msix" -ForegroundColor Gray
Write-Host ""
if ($msixFiles) {
Write-Host "Found files:" -ForegroundColor Yellow
$msixFiles | ForEach-Object { Write-Host " - $($_.FullName)" -ForegroundColor Gray }
Write-Host ""
}
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if ($msixFiles) {
Write-Host " Found MSIX files:" -ForegroundColor Green
$msixFiles | ForEach-Object {
$relativePath = $_.FullName -replace [regex]::Escape($projectRoot + "\"), ""
Write-Host " [OK] $relativePath" -ForegroundColor White
}
Write-Host ""
}
# Find specific x64 and ARM64 files
if ($buildX64) {
$x64Msix = $msixFiles | Where-Object { $_.Name -match "_x64\.msix$" } | Select-Object -First 1
if ($x64Msix) {
$builtFiles += $x64Msix.FullName
}
}
if ($buildARM64) {
$arm64Msix = $msixFiles | Where-Object { $_.Name -match "_arm64\.msix$" } | Select-Object -First 1
if ($arm64Msix) {
$builtFiles += $arm64Msix.FullName
}
}
# Validate files for bundle creation
if ($createBundle) {
if (-not $x64Msix) {
Write-Host "ERROR: Could not find x64 MSIX file" -ForegroundColor Red
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not $arm64Msix) {
Write-Host "ERROR: Could not find ARM64 MSIX file" -ForegroundColor Red
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
}
}
finally {
Pop-Location
}
}
# Create bundle (if requested)
if ($createBundle) {
# Update bundle_mapping.txt
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Updating bundle_mapping.txt" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
$microsoftStoreResourcesPath = Join-Path $PSScriptRoot "microsoft-store-resources"
$bundleMappingPath = Join-Path $microsoftStoreResourcesPath "bundle_mapping.txt"
# Ensure microsoft-store-resources directory exists
if (-not (Test-Path $microsoftStoreResourcesPath)) {
Write-Host " Creating microsoft-store-resources folder..." -ForegroundColor Yellow
try {
New-Item -Path $microsoftStoreResourcesPath -ItemType Directory -Force | Out-Null
Write-Host " [OK] Folder created" -ForegroundColor Green
}
catch {
Write-Host " [ERROR] Could not create folder: $($_.Exception.Message)" -ForegroundColor Red
}
}
# Get relative paths from project root
$x64RelativePath = $x64Msix.FullName -replace [regex]::Escape($projectRoot + "\"), ""
$arm64RelativePath = $arm64Msix.FullName -replace [regex]::Escape($projectRoot + "\"), ""
# Create bundle mapping content
$line1 = "`"$x64RelativePath`" `"$($x64Msix.Name)`""
$line2 = "`"$arm64RelativePath`" `"$($arm64Msix.Name)`""
$bundleMappingContent = "[Files]`r`n$line1`r`n$line2"
try {
Set-Content -Path $bundleMappingPath -Value $bundleMappingContent -NoNewline -ErrorAction Stop
Write-Host " [SUCCESS] bundle_mapping.txt updated" -ForegroundColor Green
Write-Host ""
Write-Host " Content:" -ForegroundColor Gray
Write-Host " [Files]" -ForegroundColor DarkGray
Write-Host (' "' + $x64RelativePath + '" "' + $x64Msix.Name + '"') -ForegroundColor DarkGray
Write-Host (' "' + $arm64RelativePath + '" "' + $arm64Msix.Name + '"') -ForegroundColor DarkGray
Write-Host ""
}
catch {
Write-Host " [ERROR] Could not update bundle_mapping.txt: $($_.Exception.Message)" -ForegroundColor Red
Write-Host " Continuing with bundle creation..." -ForegroundColor Yellow
Write-Host ""
}
# Find makeappx.exe
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Creating MSIX Bundle" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Locating makeappx.exe..." -ForegroundColor Yellow
$arch = switch ($env:PROCESSOR_ARCHITECTURE) {
"AMD64" { "x64" }
"x86" { "x86" }
"ARM64" { "arm64" }
default { "x64" }
}
Write-Host " Detected architecture: $arch" -ForegroundColor Gray
$makeappxPath = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\$arch\makeappx.exe" -ErrorAction SilentlyContinue |
Sort-Object Name -Descending |
Select-Object -First 1
if (-not $makeappxPath) {
Write-Host ""
Write-Host "ERROR: makeappx.exe not found" -ForegroundColor Red
Write-Host ""
Write-Host "makeappx.exe is part of the Windows SDK." -ForegroundColor Yellow
Write-Host "Please install the Windows SDK from:" -ForegroundColor Yellow
Write-Host " https://developer.microsoft.com/windows/downloads/windows-sdk/" -ForegroundColor Cyan
Write-Host ""
Write-Host "Or ensure the Windows SDK is installed with Visual Studio." -ForegroundColor Yellow
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [OK] Found: $($makeappxPath.FullName)" -ForegroundColor Green
Write-Host ""
# Create bundle
$bundleFileName = "${packageName}_${packageVersion}_Bundle.msixbundle"
$bundleOutputPath = Join-Path $microsoftStoreResourcesPath $bundleFileName
Write-Host "Creating bundle: $bundleFileName" -ForegroundColor Yellow
Write-Host ""
Push-Location $projectRoot
try {
# Use absolute path to bundle_mapping.txt
$bundleMappingAbsolute = Join-Path $microsoftStoreResourcesPath "bundle_mapping.txt"
# Verify the mapping file exists
if (-not (Test-Path $bundleMappingAbsolute)) {
Write-Host "ERROR: bundle_mapping.txt not found at: $bundleMappingAbsolute" -ForegroundColor Red
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
$makeappxArgs = @(
"bundle",
"/v",
"/f", "`"$bundleMappingAbsolute`"",
"/p", "`"$bundleOutputPath`""
)
Write-Host " Running: makeappx bundle /v /f `"$bundleMappingAbsolute`" /p `"$bundleOutputPath`"" -ForegroundColor Gray
Write-Host ""
# Run makeappx with proper quoting
$bundleOutput = & $makeappxPath.FullName bundle /v /f $bundleMappingAbsolute /p $bundleOutputPath 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host ""
Write-Host "ERROR: Bundle creation failed with exit code $LASTEXITCODE" -ForegroundColor Red
Write-Host ""
Write-Host "Output:" -ForegroundColor Gray
$bundleOutput | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
Write-Host ""
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [SUCCESS] Bundle created" -ForegroundColor Green
Write-Host ""
}
catch {
Write-Host ""
Write-Host "ERROR: Bundle creation failed: $($_.Exception.Message)" -ForegroundColor Red
Pop-Location
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
finally {
Pop-Location
}
# Verify bundle was created
if (-not (Test-Path $bundleOutputPath)) {
Write-Host "ERROR: Bundle file was not created at expected location" -ForegroundColor Red
Write-Host " Expected: $bundleOutputPath" -ForegroundColor Gray
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# Add bundle to built files
$builtFiles += $bundleOutputPath
}
# Final Summary
Write-Host "================================================================" -ForegroundColor Green
Write-Host " BUILD COMPLETED SUCCESSFULLY!" -ForegroundColor Green
Write-Host "================================================================" -ForegroundColor Green
Write-Host ""
# Display what was built
if ($buildChoice -eq "1") {
Write-Host "Built: x64 MSIX Package" -ForegroundColor Cyan
}
elseif ($buildChoice -eq "2") {
Write-Host "Built: ARM64 MSIX Package" -ForegroundColor Cyan
}
elseif ($buildChoice -eq "3") {
Write-Host "Built: Complete Bundle (x64 + ARM64 + Bundle file)" -ForegroundColor Cyan
}
Write-Host ""
Write-Host "Package Information:" -ForegroundColor Yellow
Write-Host " Name: $packageName" -ForegroundColor White
Write-Host " Version: $packageVersion" -ForegroundColor White
Write-Host ""
# Display built files
Write-Host "Built Files:" -ForegroundColor Yellow
if ($x64Msix) {
$x64Size = "{0:N2} MB" -f ((Get-Item $x64Msix.FullName).Length / 1MB)
Write-Host " [x64 MSIX]" -ForegroundColor Cyan
Write-Host " Location: $($x64Msix.FullName)" -ForegroundColor White
Write-Host " Size: $x64Size" -ForegroundColor White
Write-Host ""
}
if ($arm64Msix) {
$arm64Size = "{0:N2} MB" -f ((Get-Item $arm64Msix.FullName).Length / 1MB)
Write-Host " [ARM64 MSIX]" -ForegroundColor Cyan
Write-Host " Location: $($arm64Msix.FullName)" -ForegroundColor White
Write-Host " Size: $arm64Size" -ForegroundColor White
Write-Host ""
}
if ($createBundle -and (Test-Path $bundleOutputPath)) {
$bundleSize = "{0:N2} MB" -f ((Get-Item $bundleOutputPath).Length / 1MB)
Write-Host " [MSIX Bundle]" -ForegroundColor Cyan
Write-Host " Location: $bundleOutputPath" -ForegroundColor White
Write-Host " Size: $bundleSize" -ForegroundColor White
Write-Host ""
}
Write-Host "================================================================" -ForegroundColor Green
Write-Host ""
# Display appropriate next steps based on what was built
Write-Host "Next Steps:" -ForegroundColor Cyan
if ($createBundle) {
Write-Host " 1. Test the bundle by installing it locally" -ForegroundColor Gray
Write-Host " 2. Upload the bundle to Microsoft Store Partner Center" -ForegroundColor Gray
Write-Host " 3. Or distribute via other channels" -ForegroundColor Gray
}
else {
Write-Host " 1. Test the MSIX package by installing it locally" -ForegroundColor Gray
if ($buildX64) {
Write-Host " 2. Build ARM64 package (option 2) or complete bundle (option 3)" -ForegroundColor Gray
}
else {
Write-Host " 2. Build x64 package (option 1) or complete bundle (option 3)" -ForegroundColor Gray
}
Write-Host " 3. Or distribute this individual package" -ForegroundColor Gray
}
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

View File

@@ -1,3 +0,0 @@
[Files]
"AppPackages\x64\TemplateCmdPalExtension_0.0.1.0_x64_Test\TemplateCmdPalExtension_0.0.1.0_x64.msix" "TemplateCmdPalExtension_0.0.1.0_x64.msix"
"AppPackages\ARM64\TemplateCmdPalExtension_0.0.1.0_arm64_Test\TemplateCmdPalExtension_0.0.1.0_arm64.msix" "TemplateCmdPalExtension_0.0.1.0_arm64.msix"

View File

@@ -1,829 +0,0 @@
# One-Time Publication Setup Script for CmdPal Extension
# This script collects Microsoft Store publication information and updates project files
# Version: 1.1
#Requires -Version 5.1
# Enable strict mode for better error detection
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Microsoft Store Publication Setup" -ForegroundColor Cyan
Write-Host " CmdPal Extension Publisher" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
# Path to the project files
$projectRoot = Split-Path -Parent $PSScriptRoot
$csprojPath = Join-Path $projectRoot "TemplateCmdPalExtension.csproj"
$manifestPath = Join-Path $projectRoot "Package.appxmanifest"
Write-Host "Validating project structure..." -ForegroundColor Cyan
Write-Host " Project Root: $projectRoot" -ForegroundColor Gray
# Verify files exist with detailed error messages
if (-not (Test-Path $csprojPath)) {
Write-Host ""
Write-Host "ERROR: Could not find .csproj file" -ForegroundColor Red
Write-Host " Expected location: $csprojPath" -ForegroundColor Gray
Write-Host ""
Write-Host "This script must be run from the Publication folder within your project." -ForegroundColor Yellow
Write-Host "Please navigate to: <YourProject>\Publication\" -ForegroundColor Yellow
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not (Test-Path $manifestPath)) {
Write-Host ""
Write-Host "ERROR: Could not find Package.appxmanifest file" -ForegroundColor Red
Write-Host " Expected location: $manifestPath" -ForegroundColor Gray
Write-Host ""
Write-Host "Your project structure may be incomplete or corrupted." -ForegroundColor Yellow
Write-Host "Please ensure Package.appxmanifest exists in your project root." -ForegroundColor Yellow
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [OK] .csproj file found" -ForegroundColor Green
Write-Host " [OK] Package.appxmanifest file found" -ForegroundColor Green
Write-Host ""
# Create backup directory if it doesn't exist
$backupDir = Join-Path $projectRoot "Publication\Backups"
if (-not (Test-Path $backupDir)) {
try {
New-Item -Path $backupDir -ItemType Directory -Force | Out-Null
Write-Host "Created backup directory: $backupDir" -ForegroundColor Gray
}
catch {
Write-Host "WARNING: Could not create backup directory. Proceeding without backups." -ForegroundColor Yellow
$backupDir = $null
}
}
# Create timestamped backups
if ($backupDir) {
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
try {
Copy-Item $csprojPath -Destination (Join-Path $backupDir "TemplateCmdPalExtension.csproj.$timestamp.bak") -Force
Copy-Item $manifestPath -Destination (Join-Path $backupDir "Package.appxmanifest.$timestamp.bak") -Force
Write-Host "Backup created: $timestamp" -ForegroundColor Gray
Write-Host ""
}
catch {
Write-Host "WARNING: Could not create backup files. Proceeding anyway." -ForegroundColor Yellow
Write-Host ""
}
}
Write-Host "This script will collect information needed to publish your extension" -ForegroundColor White
Write-Host "to the Microsoft Store. You can find this information in your" -ForegroundColor White
Write-Host "Microsoft Partner Center account." -ForegroundColor White
Write-Host ""
Write-Host "IMPORTANT: Have your Partner Center information ready before proceeding." -ForegroundColor Yellow
Write-Host " - Package Identity Name" -ForegroundColor Gray
Write-Host " - Publisher Certificate Name" -ForegroundColor Gray
Write-Host " - Reserved App Name" -ForegroundColor Gray
Write-Host " - Publisher Display Name" -ForegroundColor Gray
Write-Host ""
Write-Host "TIP: You can find this in Partner Center > Product Management > Product Identity" -ForegroundColor Cyan
Write-Host ""
# Prompt to continue
Write-Host "Do you want to continue? (Y/N): " -ForegroundColor Yellow -NoNewline
$continue = Read-Host
if ($continue -notmatch '^[Yy]') {
Write-Host ""
Write-Host "Setup cancelled by user." -ForegroundColor Yellow
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 0
}
Write-Host ""
# Function to validate package identity name format
function Test-PackageIdentityName {
param([string]$name)
# Package identity name rules:
# - Between 3 and 50 characters
# - Can contain: letters, numbers, periods, hyphens
# - Cannot start/end with period
# - Cannot have consecutive periods
if ([string]::IsNullOrWhiteSpace($name)) { return $false }
if ($name.Length -lt 3 -or $name.Length -gt 50) { return $false }
if ($name -match '^\.|\.$|\.\.') { return $false }
if ($name -notmatch '^[a-zA-Z0-9.-]+$') { return $false }
return $true
}
# Function to validate publisher certificate format
function Test-PublisherFormat {
param([string]$publisher)
if ([string]::IsNullOrWhiteSpace($publisher)) { return $false }
# Should start with CN= and follow distinguished name format
if ($publisher -notmatch '^CN=.+') { return $false }
# Check for valid characters in DN
if ($publisher -match '[<>]') { return $false }
return $true
}
# Function to validate display name
function Test-DisplayName {
param([string]$name)
if ([string]::IsNullOrWhiteSpace($name)) { return $false }
# Display name should be reasonable length and not contain control characters
if ($name.Length -lt 1 -or $name.Length -gt 256) { return $false }
if ($name -match '[\x00-\x1F\x7F]') { return $false }
return $true
}
# Collect Microsoft Store Package Identity Name
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 1: Package Identity Name" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Enter Microsoft Store Package/Identity/Name:" -ForegroundColor Yellow
Write-Host " Location: Partner Center > Product Identity > Package/Identity/Name" -ForegroundColor Gray
Write-Host ""
Write-Host " Format Requirements:" -ForegroundColor Gray
Write-Host " - 3-50 characters" -ForegroundColor DarkGray
Write-Host " - Letters, numbers, periods, hyphens only" -ForegroundColor DarkGray
Write-Host " - Cannot start/end with period or have consecutive periods" -ForegroundColor DarkGray
Write-Host ""
Write-Host " Example: Publisher.MyAwesomeExtension" -ForegroundColor DarkGray
Write-Host ""
$packageIdentityName = ""
$maxAttempts = 3
$attempt = 0
do {
$attempt++
Write-Host "Package Identity Name" -NoNewline -ForegroundColor Yellow
if ($attempt -gt 1) {
Write-Host " (Attempt $attempt of $maxAttempts)" -NoNewline -ForegroundColor Red
}
Write-Host ": " -NoNewline -ForegroundColor Yellow
$packageIdentityName = Read-Host
if ([string]::IsNullOrWhiteSpace($packageIdentityName)) {
Write-Host " [ERROR] Package Identity Name cannot be empty." -ForegroundColor Red
Write-Host ""
}
elseif (-not (Test-PackageIdentityName $packageIdentityName)) {
Write-Host " [ERROR] Invalid Package Identity Name format." -ForegroundColor Red
Write-Host " Please ensure it meets the format requirements listed above." -ForegroundColor Yellow
Write-Host ""
}
else {
Write-Host " [OK] Package Identity Name accepted: $packageIdentityName" -ForegroundColor Green
Write-Host ""
break
}
if ($attempt -ge $maxAttempts) {
Write-Host ""
Write-Host "Maximum attempts reached. Please verify your Partner Center information and try again." -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
} while ($true)
# Collect Microsoft Store Package Identity Publisher
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 2: Publisher Certificate" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Enter Microsoft Store Package/Identity/Publisher:" -ForegroundColor Yellow
Write-Host " Location: Partner Center > Product Identity > Package/Identity/Publisher" -ForegroundColor Gray
Write-Host ""
Write-Host " Format Requirements:" -ForegroundColor Gray
Write-Host " - Must start with 'CN=' (Certificate Name)" -ForegroundColor DarkGray
Write-Host " - This is the publisher certificate distinguished name" -ForegroundColor DarkGray
Write-Host ""
Write-Host " Example: CN=12345678-1234-1234-1234-123456789012" -ForegroundColor DarkGray
Write-Host " Example: CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" -ForegroundColor DarkGray
Write-Host ""
$packageIdentityPublisher = ""
$attempt = 0
do {
$attempt++
Write-Host "Publisher Certificate" -NoNewline -ForegroundColor Yellow
if ($attempt -gt 1) {
Write-Host " (Attempt $attempt of $maxAttempts)" -NoNewline -ForegroundColor Red
}
Write-Host ": " -NoNewline -ForegroundColor Yellow
$packageIdentityPublisher = Read-Host
if ([string]::IsNullOrWhiteSpace($packageIdentityPublisher)) {
Write-Host " [ERROR] Publisher cannot be empty." -ForegroundColor Red
Write-Host ""
}
elseif (-not (Test-PublisherFormat $packageIdentityPublisher)) {
if ($packageIdentityPublisher -notmatch '^CN=') {
Write-Host " [ERROR] Publisher must start with 'CN='." -ForegroundColor Red
Write-Host " Copy the entire string from Partner Center, including 'CN='." -ForegroundColor Yellow
}
else {
Write-Host " [ERROR] Invalid publisher format." -ForegroundColor Red
Write-Host " Please ensure you copied the complete certificate name from Partner Center." -ForegroundColor Yellow
}
Write-Host ""
}
else {
Write-Host " [OK] Publisher certificate accepted" -ForegroundColor Green
Write-Host ""
break
}
if ($attempt -ge $maxAttempts) {
Write-Host ""
Write-Host "Maximum attempts reached. Please verify your Partner Center information and try again." -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
} while ($true)
# Collect Reserved Display Name
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 3: Display Name" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Enter the reserved Display Name from Partner Center:" -ForegroundColor Yellow
Write-Host " Location: Partner Center > Product Management > Store Listing" -ForegroundColor Gray
Write-Host ""
Write-Host " This is the app name visible to users in the Microsoft Store." -ForegroundColor Gray
Write-Host " It must match EXACTLY what you reserved in Partner Center." -ForegroundColor Gray
Write-Host ""
Write-Host " Example: My Awesome CmdPal Extension" -ForegroundColor DarkGray
Write-Host ""
$displayName = ""
$attempt = 0
do {
$attempt++
Write-Host "Display Name" -NoNewline -ForegroundColor Yellow
if ($attempt -gt 1) {
Write-Host " (Attempt $attempt of $maxAttempts)" -NoNewline -ForegroundColor Red
}
Write-Host ": " -NoNewline -ForegroundColor Yellow
$displayName = Read-Host
if ([string]::IsNullOrWhiteSpace($displayName)) {
Write-Host " [ERROR] Display Name cannot be empty." -ForegroundColor Red
Write-Host ""
}
elseif (-not (Test-DisplayName $displayName)) {
Write-Host " [ERROR] Invalid Display Name." -ForegroundColor Red
Write-Host " Display name must be 1-256 characters and cannot contain control characters." -ForegroundColor Yellow
Write-Host ""
}
else {
Write-Host " [OK] Display Name accepted: $displayName" -ForegroundColor Green
Write-Host ""
break
}
if ($attempt -ge $maxAttempts) {
Write-Host ""
Write-Host "Maximum attempts reached. Please try again with valid information." -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
} while ($true)
# Collect Publisher Display Name
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 4: Publisher Display Name" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Enter Microsoft Store Package/Properties/PublisherDisplayName:" -ForegroundColor Yellow
Write-Host " Location: Partner Center > Product Identity > Package/Properties" -ForegroundColor Gray
Write-Host ""
Write-Host " This is your company or developer name shown to users." -ForegroundColor Gray
Write-Host ""
Write-Host " Example: Contoso Software Inc." -ForegroundColor DarkGray
Write-Host " Example: Jessica Cha" -ForegroundColor DarkGray
Write-Host ""
$publisherDisplayName = ""
$attempt = 0
do {
$attempt++
Write-Host "Publisher Display Name" -NoNewline -ForegroundColor Yellow
if ($attempt -gt 1) {
Write-Host " (Attempt $attempt of $maxAttempts)" -NoNewline -ForegroundColor Red
}
Write-Host ": " -NoNewline -ForegroundColor Yellow
$publisherDisplayName = Read-Host
if ([string]::IsNullOrWhiteSpace($publisherDisplayName)) {
Write-Host " [ERROR] Publisher Display Name cannot be empty." -ForegroundColor Red
Write-Host ""
}
elseif (-not (Test-DisplayName $publisherDisplayName)) {
Write-Host " [ERROR] Invalid Publisher Display Name." -ForegroundColor Red
Write-Host " Publisher name must be 1-256 characters and cannot contain control characters." -ForegroundColor Yellow
Write-Host ""
}
else {
Write-Host " [OK] Publisher Display Name accepted: $publisherDisplayName" -ForegroundColor Green
Write-Host ""
break
}
if ($attempt -ge $maxAttempts) {
Write-Host ""
Write-Host "Maximum attempts reached. Please try again with valid information." -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
} while ($true)
# Check for required assets
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 5: Validating Required Assets" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Checking for Microsoft Store required asset images..." -ForegroundColor Yellow
Write-Host ""
$assetsPath = Join-Path $projectRoot "Assets"
# Check if Assets folder exists
if (-not (Test-Path $assetsPath)) {
Write-Host " [ERROR] Assets folder not found at: $assetsPath" -ForegroundColor Red
Write-Host ""
Write-Host " Please create the Assets folder and add the required images." -ForegroundColor Yellow
Write-Host " Press any key to continue anyway (you'll need to add assets later)..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Write-Host ""
}
$requiredAssets = @(
@{ Name = "StoreLogo.png"; Size = "50x50"; Description = "Store logo for listings" },
@{ Name = "Square150x150Logo.scale-200.png"; Size = "300x300"; Description = "Medium tile" },
@{ Name = "Square44x44Logo.scale-200.png"; Size = "88x88"; Description = "App list icon" },
@{ Name = "Wide310x150Logo.scale-200.png"; Size = "620x300"; Description = "Wide tile" },
@{ Name = "SplashScreen.scale-200.png"; Size = "1240x600"; Description = "Splash screen" },
@{ Name = "StoreLogo.scale-100.png"; Size = "50x50"; Description = "Store logo (100% scale)" }
)
$missingAssets = @()
$foundAssets = @()
Write-Host " Asset Validation Results:" -ForegroundColor Cyan
Write-Host " " -NoNewline
Write-Host ("{0,-45} {1,-15} {2}" -f "File", "Size", "Status") -ForegroundColor Gray
Write-Host " " -NoNewline
Write-Host ("{0,-45} {1,-15} {2}" -f "----", "----", "------") -ForegroundColor DarkGray
foreach ($asset in $requiredAssets) {
$assetPath = Join-Path $assetsPath $asset.Name
$statusPrefix = " "
if (Test-Path $assetPath) {
try {
$fileInfo = Get-Item $assetPath
$fileSize = "{0:N2} KB" -f ($fileInfo.Length / 1KB)
Write-Host " " -NoNewline
Write-Host ("{0,-45} {1,-15} " -f $asset.Name, $asset.Size) -NoNewline -ForegroundColor White
Write-Host "[OK]" -ForegroundColor Green
$foundAssets += $asset.Name
}
catch {
Write-Host " " -NoNewline
Write-Host ("{0,-45} {1,-15} " -f $asset.Name, $asset.Size) -NoNewline -ForegroundColor White
Write-Host "[WARNING]" -ForegroundColor Yellow
Write-Host " (File exists but couldn't read properties)" -ForegroundColor DarkGray
$foundAssets += $asset.Name
}
}
else {
Write-Host " " -NoNewline
Write-Host ("{0,-45} {1,-15} " -f $asset.Name, $asset.Size) -NoNewline -ForegroundColor White
Write-Host "[MISSING]" -ForegroundColor Red
Write-Host " ($($asset.Description))" -ForegroundColor DarkGray
$missingAssets += $asset
}
}
Write-Host ""
Write-Host " Summary: " -NoNewline -ForegroundColor Cyan
Write-Host "$($foundAssets.Count) of $($requiredAssets.Count) assets found" -ForegroundColor White
# Auto-fix: Copy StoreLogo.scale-100.png to StoreLogo.png if needed
$storeLogoPath = Join-Path $assetsPath "StoreLogo.png"
$storeLogoScaledPath = Join-Path $assetsPath "StoreLogo.scale-100.png"
if (-not (Test-Path $storeLogoPath) -and (Test-Path $storeLogoScaledPath)) {
Write-Host ""
Write-Host " [AUTO-FIX] Creating StoreLogo.png from StoreLogo.scale-100.png..." -ForegroundColor Cyan
try {
Copy-Item $storeLogoScaledPath -Destination $storeLogoPath -Force -ErrorAction Stop
Write-Host " [SUCCESS] StoreLogo.png created successfully" -ForegroundColor Green
# Update the missing/found counts
$missingAssets = $missingAssets | Where-Object { $_.Name -ne "StoreLogo.png" }
if ($foundAssets -notcontains "StoreLogo.png") {
$foundAssets += "StoreLogo.png"
}
}
catch {
Write-Host " [ERROR] Could not copy file: $($_.Exception.Message)" -ForegroundColor Red
}
}
if ($missingAssets.Count -gt 0) {
Write-Host ""
Write-Host " [WARNING] $($missingAssets.Count) asset(s) missing" -ForegroundColor Yellow
Write-Host ""
Write-Host " The Microsoft Store requires specific image assets for your app listing." -ForegroundColor Gray
Write-Host " You'll need to add these before you can publish." -ForegroundColor Gray
Write-Host ""
Write-Host " TIP: Use the Windows App SDK project templates or design tools to create" -ForegroundColor Cyan
Write-Host " properly sized assets. Each image must be exactly the size specified." -ForegroundColor Cyan
Write-Host ""
}
else {
Write-Host " [OK] All required assets are present!" -ForegroundColor Green
Write-Host ""
}
Write-Host ""
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Updating Project Files..." -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "The script will now update your project files with the information you provided." -ForegroundColor White
Write-Host "Original files have been backed up in the Publication\Backups folder." -ForegroundColor Gray
Write-Host ""
# Update Package.appxmanifest
Write-Host "[1/2] Updating Package.appxmanifest..." -ForegroundColor Cyan
try {
$manifestContent = Get-Content $manifestPath -Raw -ErrorAction Stop
}
catch {
Write-Host " [ERROR] Could not read Package.appxmanifest: $($_.Exception.Message)" -ForegroundColor Red
Write-Host " The file may be locked by another process." -ForegroundColor Yellow
Write-Host " Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# Backup original content
$manifestBackup = $manifestContent
$manifestUpdateCount = 0
# Update Identity element (Name and Publisher)
Write-Host " Updating Identity Name..." -NoNewline -ForegroundColor Gray
$identityNamePattern = '(?<=<Identity\s+Name=")[^"]*'
if ($manifestContent -match $identityNamePattern) {
$oldValue = $Matches[0]
$identityNameUpdated = $manifestContent -replace $identityNamePattern, $packageIdentityName
if ($identityNameUpdated -ne $manifestContent) {
$manifestContent = $identityNameUpdated
$manifestUpdateCount++
Write-Host " [OK]" -ForegroundColor Green
Write-Host " Changed from: '$oldValue'" -ForegroundColor DarkGray
Write-Host " Changed to: '$packageIdentityName'" -ForegroundColor DarkGray
}
else {
Write-Host " [NO CHANGE]" -ForegroundColor Yellow
}
}
else {
Write-Host " [WARNING] Could not find Identity Name attribute" -ForegroundColor Yellow
}
Write-Host " Updating Publisher..." -NoNewline -ForegroundColor Gray
$publisherPattern = '(?<=Publisher=")[^"]*(?=")'
if ($manifestContent -match $publisherPattern) {
$oldValue = $Matches[0]
$identityPublisherUpdated = $manifestContent -replace $publisherPattern, $packageIdentityPublisher
if ($identityPublisherUpdated -ne $manifestContent) {
$manifestContent = $identityPublisherUpdated
$manifestUpdateCount++
Write-Host " [OK]" -ForegroundColor Green
Write-Host " Changed from: '$oldValue'" -ForegroundColor DarkGray
Write-Host " Changed to: '$packageIdentityPublisher'" -ForegroundColor DarkGray
}
else {
Write-Host " [NO CHANGE]" -ForegroundColor Yellow
}
}
else {
Write-Host " [WARNING] Could not find Publisher attribute" -ForegroundColor Yellow
}
# Update Properties (DisplayName and PublisherDisplayName)
Write-Host " Updating Display Name..." -NoNewline -ForegroundColor Gray
$displayNamePattern = '(?<=<DisplayName>)[^<]*(?=</DisplayName>)'
if ($manifestContent -match $displayNamePattern) {
$oldValue = $Matches[0]
$displayNameUpdated = $manifestContent -replace $displayNamePattern, $displayName
if ($displayNameUpdated -ne $manifestContent) {
$manifestContent = $displayNameUpdated
$manifestUpdateCount++
Write-Host " [OK]" -ForegroundColor Green
Write-Host " Changed from: '$oldValue'" -ForegroundColor DarkGray
Write-Host " Changed to: '$displayName'" -ForegroundColor DarkGray
}
else {
Write-Host " [NO CHANGE]" -ForegroundColor Yellow
}
}
else {
Write-Host " [WARNING] Could not find DisplayName element" -ForegroundColor Yellow
}
Write-Host " Updating Publisher Display Name..." -NoNewline -ForegroundColor Gray
$publisherDisplayNamePattern = '(?<=<PublisherDisplayName>)[^<]*(?=</PublisherDisplayName>)'
if ($manifestContent -match $publisherDisplayNamePattern) {
$oldValue = $Matches[0]
$publisherDisplayNameUpdated = $manifestContent -replace $publisherDisplayNamePattern, $publisherDisplayName
if ($publisherDisplayNameUpdated -ne $manifestContent) {
$manifestContent = $publisherDisplayNameUpdated
$manifestUpdateCount++
Write-Host " [OK]" -ForegroundColor Green
Write-Host " Changed from: '$oldValue'" -ForegroundColor DarkGray
Write-Host " Changed to: '$publisherDisplayName'" -ForegroundColor DarkGray
}
else {
Write-Host " [NO CHANGE]" -ForegroundColor Yellow
}
}
else {
Write-Host " [WARNING] Could not find PublisherDisplayName element" -ForegroundColor Yellow
}
# Also update the VisualElements DisplayName
Write-Host " Updating VisualElements Display Name..." -NoNewline -ForegroundColor Gray
$visualElementsPattern = '(?<=<uap:VisualElements[^>]*DisplayName=")[^"]*'
if ($manifestContent -match $visualElementsPattern) {
$oldValue = $Matches[0]
if ($oldValue -ne $displayName) {
$visualElementsUpdated = $manifestContent -replace $visualElementsPattern, $displayName
if ($visualElementsUpdated -ne $manifestContent) {
$manifestContent = $visualElementsUpdated
$manifestUpdateCount++
Write-Host " [OK]" -ForegroundColor Green
}
else {
Write-Host " [NO CHANGE]" -ForegroundColor Yellow
}
}
else {
Write-Host " [ALREADY SET]" -ForegroundColor Green
}
}
else {
Write-Host " [SKIP]" -ForegroundColor Gray
}
# Write the updated manifest
if ($manifestContent -ne $manifestBackup) {
try {
Set-Content -Path $manifestPath -Value $manifestContent -NoNewline -ErrorAction Stop
Write-Host ""
Write-Host " [SUCCESS] Package.appxmanifest updated ($manifestUpdateCount changes)" -ForegroundColor Green
}
catch {
Write-Host ""
Write-Host " [ERROR] Could not write to Package.appxmanifest: $($_.Exception.Message)" -ForegroundColor Red
Write-Host " The file may be read-only or locked by another process." -ForegroundColor Yellow
Write-Host " Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
}
else {
Write-Host ""
Write-Host " [INFO] No changes were needed for Package.appxmanifest" -ForegroundColor Cyan
}
Write-Host ""
# Update .csproj file
Write-Host "[2/2] Updating TemplateCmdPalExtension.csproj..." -ForegroundColor Cyan
try {
$csprojContent = Get-Content $csprojPath -Raw -ErrorAction Stop
}
catch {
Write-Host " [ERROR] Could not read .csproj file: $($_.Exception.Message)" -ForegroundColor Red
Write-Host " The file may be locked by another process." -ForegroundColor Yellow
Write-Host " Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# Backup original content
$csprojBackup = $csprojContent
$csprojUpdateCount = 0
# Check if Store properties are commented or uncommented
Write-Host " Checking Store property configuration..." -NoNewline -ForegroundColor Gray
$storePropsCommentedPattern = '<!--\s*<AppxPackageIdentityName>YOUR_PACKAGE_IDENTITY_NAME_HERE</AppxPackageIdentityName>\s*<AppxPackagePublisher>YOUR_PACKAGE_IDENTITY_PUBLISHER_HERE</AppxPackagePublisher>\s*<AppxPackageVersion>[^<]*</AppxPackageVersion>\s*-->'
if ($csprojContent -match $storePropsCommentedPattern) {
Write-Host " [COMMENTED]" -ForegroundColor Yellow
Write-Host " Uncommenting and updating Store properties..." -ForegroundColor Gray
# Uncomment and update the Store-specific properties
$replacement = "<AppxPackageIdentityName>$packageIdentityName</AppxPackageIdentityName>`n <AppxPackagePublisher>$packageIdentityPublisher</AppxPackagePublisher>`n <AppxPackageVersion>0.0.1.0</AppxPackageVersion>"
$csprojContent = $csprojContent -replace $storePropsCommentedPattern, $replacement
$csprojUpdateCount++
Write-Host " [OK] Store properties uncommented and updated" -ForegroundColor Green
}
else {
Write-Host " [UNCOMMENTED]" -ForegroundColor Green
Write-Host " Updating existing Store property values..." -ForegroundColor Gray
# Try updating already-uncommented properties
$identityNamePattern = '(?<=<AppxPackageIdentityName>)[^<]*(?=</AppxPackageIdentityName>)'
if ($csprojContent -match $identityNamePattern) {
$oldValue = $Matches[0]
if ($oldValue -ne $packageIdentityName) {
$csprojContent = $csprojContent -replace $identityNamePattern, $packageIdentityName
$csprojUpdateCount++
Write-Host " Updated AppxPackageIdentityName" -ForegroundColor Green
}
}
$publisherPattern = '(?<=<AppxPackagePublisher>)[^<]*(?=</AppxPackagePublisher>)'
if ($csprojContent -match $publisherPattern) {
$oldValue = $Matches[0]
if ($oldValue -ne $packageIdentityPublisher) {
$csprojContent = $csprojContent -replace $publisherPattern, $packageIdentityPublisher
$csprojUpdateCount++
Write-Host " Updated AppxPackagePublisher" -ForegroundColor Green
}
}
}
# Uncomment the PrepareAssets Target section (using (?s) for multi-line matching)
Write-Host " Checking PrepareAssets Target..." -NoNewline -ForegroundColor Gray
$targetPattern = '(?s)<!--\s*(<Target Name="PrepareAssets".*?</Target>)\s*-->'
if ($csprojContent -match $targetPattern) {
Write-Host " [COMMENTED]" -ForegroundColor Yellow
Write-Host " Uncommenting PrepareAssets Target..." -ForegroundColor Gray
$targetReplacement = '$1'
$targetUpdated = $csprojContent -replace $targetPattern, $targetReplacement
if ($targetUpdated -ne $csprojContent) {
$csprojContent = $targetUpdated
$csprojUpdateCount++
Write-Host " [OK] PrepareAssets Target uncommented" -ForegroundColor Green
}
else {
Write-Host " [WARNING] Could not uncomment PrepareAssets Target" -ForegroundColor Yellow
}
}
else {
Write-Host " [ALREADY UNCOMMENTED]" -ForegroundColor Green
}
# Write the updated csproj
if ($csprojContent -ne $csprojBackup) {
try {
Set-Content -Path $csprojPath -Value $csprojContent -NoNewline -ErrorAction Stop
Write-Host ""
Write-Host " [SUCCESS] TemplateCmdPalExtension.csproj updated ($csprojUpdateCount changes)" -ForegroundColor Green
}
catch {
Write-Host ""
Write-Host " [ERROR] Could not write to .csproj file: $($_.Exception.Message)" -ForegroundColor Red
Write-Host " The file may be read-only or locked by another process." -ForegroundColor Yellow
Write-Host " Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
}
else {
Write-Host ""
Write-Host " [INFO] No changes were needed for TemplateCmdPalExtension.csproj" -ForegroundColor Cyan
}
Write-Host ""
# Display summary
Write-Host "=================================================================" -ForegroundColor Cyan
Write-Host " CONFIGURATION SUMMARY" -ForegroundColor White
Write-Host "=================================================================" -ForegroundColor Cyan
Write-Host " Package Identity Name:" -ForegroundColor Gray
Write-Host " $packageIdentityName" -ForegroundColor White
Write-Host ""
Write-Host " Publisher:" -ForegroundColor Gray
# Truncate publisher if too long
$publisherDisplay = if ($packageIdentityPublisher.Length -gt 80) {
$packageIdentityPublisher.Substring(0, 77) + "..."
} else {
$packageIdentityPublisher
}
Write-Host " $publisherDisplay" -ForegroundColor White
Write-Host ""
Write-Host " Display Name:" -ForegroundColor Gray
Write-Host " $displayName" -ForegroundColor White
Write-Host ""
Write-Host " Publisher Display Name:" -ForegroundColor Gray
Write-Host " $publisherDisplayName" -ForegroundColor White
Write-Host "=================================================================" -ForegroundColor Cyan
Write-Host ""
# Display modified files
Write-Host "Modified Files:" -ForegroundColor Yellow
$manifestRelative = $manifestPath -replace [regex]::Escape($projectRoot), "."
$csprojRelative = $csprojPath -replace [regex]::Escape($projectRoot), "."
Write-Host "$manifestRelative" -ForegroundColor Green
Write-Host "$csprojRelative" -ForegroundColor Green
Write-Host ""
if ($backupDir) {
Write-Host "Backup Location:" -ForegroundColor Yellow
$backupRelative = $backupDir -replace [regex]::Escape($projectRoot), "."
Write-Host " $backupRelative" -ForegroundColor Gray
Write-Host ""
}
# Asset status
if ($missingAssets.Count -gt 0) {
Write-Host "=================================================================" -ForegroundColor Red
Write-Host " ACTION REQUIRED: Missing Assets" -ForegroundColor Yellow
Write-Host "=================================================================" -ForegroundColor Red
Write-Host " $($missingAssets.Count) required asset(s) are missing. Add them before publishing:" -ForegroundColor White
Write-Host ""
foreach ($asset in $missingAssets) {
Write-Host " * $($asset.Name) ($($asset.Size))" -ForegroundColor White
}
Write-Host "=================================================================" -ForegroundColor Red
Write-Host ""
Write-Host "Asset Creation Tips:" -ForegroundColor Cyan
Write-Host " * Use PNG format with transparency where appropriate" -ForegroundColor Gray
Write-Host " * Follow Microsoft Store asset guidelines" -ForegroundColor Gray
Write-Host " * Reference: https://learn.microsoft.com/windows/apps/design/style/app-icons-and-logos" -ForegroundColor DarkCyan
Write-Host ""
}
else {
Write-Host " [OK] All required assets are present" -ForegroundColor Green
Write-Host ""
}
# Final success message with conditional messaging
Write-Host "=================================================================" -ForegroundColor Green
if ($missingAssets.Count -gt 0) {
Write-Host " Setup Complete - Action Required" -ForegroundColor Yellow
Write-Host "=================================================================" -ForegroundColor Yellow
Write-Host ""
Write-Host " Your project has been configured for Microsoft Store publishing." -ForegroundColor White
Write-Host " However, you need to add $($missingAssets.Count) missing asset(s) before publishing." -ForegroundColor Yellow
}
else {
Write-Host " Setup Completed Successfully!" -ForegroundColor Green
Write-Host "=================================================================" -ForegroundColor Green
Write-Host ""
Write-Host " Your extension is ready for Microsoft Store publishing!" -ForegroundColor White
Write-Host " All configuration and assets are in place." -ForegroundColor Green
}
Write-Host ""
Write-Host "Next Steps:" -ForegroundColor Cyan
Write-Host " 1. Build MSIX bundles by running:" -ForegroundColor Gray
Write-Host " .\build-msix-bundles.ps1" -ForegroundColor White
Write-Host ""
Write-Host " 2. Upload the bundle to Microsoft Store Partner Center" -ForegroundColor Gray
Write-Host " (Located in Publication\ folder after build)" -ForegroundColor DarkGray
Write-Host ""
Write-Host " 3. Follow submission instructions at:" -ForegroundColor Gray
Write-Host " https://learn.microsoft.com/windows/powertoys/command-palette/publish-extension" -ForegroundColor DarkCyan
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

View File

@@ -1,512 +0,0 @@
# One-Time WinGet Publication Setup Script for CmdPal Extension
# This script collects information and updates files needed for WinGet publication via EXE installer
# Version: 1.0
#Requires -Version 5.1
# Enable strict mode for better error detection
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " WinGet Publication Setup (EXE Installer)" -ForegroundColor Cyan
Write-Host " CmdPal Extension Publisher" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
# Path to the project files
$publicationRoot = $PSScriptRoot
$projectRoot = Split-Path -Parent $publicationRoot
$projectName = Split-Path -Leaf $projectRoot
$wingetResourcesPath = Join-Path $PSScriptRoot "winget-resources"
Write-Host "Validating project structure..." -ForegroundColor Cyan
Write-Host " Publication Root: $publicationRoot" -ForegroundColor Gray
Write-Host " Project Root: $projectRoot" -ForegroundColor Gray
Write-Host " Project Name: $projectName" -ForegroundColor Gray
Write-Host ""
# Verify required files exist
$csprojPath = Join-Path $projectRoot "$projectName.csproj"
$manifestPath = Join-Path $projectRoot "Package.appxmanifest"
$extensionCsPath = Join-Path $projectRoot "$projectName.cs"
$buildExePath = Join-Path $wingetResourcesPath "build-exe.ps1"
$setupTemplatePath = Join-Path $wingetResourcesPath "setup-template.iss"
$releaseYmlPath = Join-Path $wingetResourcesPath "release-extension.yml"
if (-not (Test-Path $csprojPath)) {
Write-Host "ERROR: Could not find .csproj file at: $csprojPath" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not (Test-Path $manifestPath)) {
Write-Host "ERROR: Could not find Package.appxmanifest at: $manifestPath" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not (Test-Path $buildExePath)) {
Write-Host "ERROR: Could not find build-exe.ps1 at: $buildExePath" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not (Test-Path $setupTemplatePath)) {
Write-Host "ERROR: Could not find setup-template.iss at: $setupTemplatePath" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
if (-not (Test-Path $releaseYmlPath)) {
Write-Host "ERROR: Could not find release-extension.yml at: $releaseYmlPath" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host " [OK] All required files found" -ForegroundColor Green
Write-Host ""
# Create backup directory
$backupDir = Join-Path $wingetResourcesPath "Backups"
if (-not (Test-Path $backupDir)) {
try {
New-Item -Path $backupDir -ItemType Directory -Force | Out-Null
Write-Host "Created backup directory: $backupDir" -ForegroundColor Gray
}
catch {
Write-Host "WARNING: Could not create backup directory. Proceeding without backups." -ForegroundColor Yellow
$backupDir = $null
}
}
# Create timestamped backups
if ($backupDir) {
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
try {
Copy-Item $buildExePath -Destination (Join-Path $backupDir "build-exe.ps1.$timestamp.bak") -Force
Copy-Item $setupTemplatePath -Destination (Join-Path $backupDir "setup-template.iss.$timestamp.bak") -Force
Copy-Item $releaseYmlPath -Destination (Join-Path $backupDir "release-extension.yml.$timestamp.bak") -Force
Write-Host "Backups created: $timestamp" -ForegroundColor Gray
Write-Host ""
}
catch {
Write-Host "WARNING: Could not create backup files. Proceeding anyway." -ForegroundColor Yellow
Write-Host ""
}
}
# Read existing project information
Write-Host "Reading project information..." -ForegroundColor Cyan
try {
[xml]$manifest = Get-Content $manifestPath -ErrorAction Stop
$packageName = $manifest.Package.Identity.Name
$packageVersion = $manifest.Package.Identity.Version
$displayName = $manifest.Package.Properties.DisplayName
$publisherDisplayName = $manifest.Package.Properties.PublisherDisplayName
Write-Host " Current Package Name: $packageName" -ForegroundColor White
Write-Host " Current Version: $packageVersion" -ForegroundColor White
Write-Host " Current Display Name: $displayName" -ForegroundColor White
Write-Host " Current Publisher: $publisherDisplayName" -ForegroundColor White
Write-Host ""
}
catch {
Write-Host "ERROR: Could not read Package.appxmanifest: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
# Extract GUID/CLSID from extension class
Write-Host "Reading extension GUID..." -ForegroundColor Cyan
try {
$extensionCsContent = Get-Content $extensionCsPath -Raw -ErrorAction Stop
if ($extensionCsContent -match '\[Guid\("([A-F0-9-]+)"\)\]') {
$extensionGuid = $Matches[1]
Write-Host " Extension GUID: $extensionGuid" -ForegroundColor White
Write-Host ""
}
else {
Write-Host "ERROR: Could not find GUID in $projectName.cs" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
}
catch {
Write-Host "ERROR: Could not read $projectName.cs: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
Write-Host "This script will configure your extension for WinGet publication using EXE installer." -ForegroundColor White
Write-Host ""
Write-Host "The following information will be collected:" -ForegroundColor White
Write-Host " - GitHub Repository URL (for releases)" -ForegroundColor Gray
Write-Host " - Developer/Publisher Name" -ForegroundColor Gray
Write-Host ""
Write-Host "The script will update:" -ForegroundColor Yellow
Write-Host " - build-exe.ps1 (build script)" -ForegroundColor Gray
Write-Host " - setup-template.iss (Inno Setup installer script)" -ForegroundColor Gray
Write-Host " - release-extension.yml (GitHub Actions workflow)" -ForegroundColor Gray
Write-Host ""
# Function to validate URL
function Test-GitHubUrl {
param([string]$url)
if ([string]::IsNullOrWhiteSpace($url)) { return $false }
if ($url -notmatch '^https://github\.com/[a-zA-Z0-9_-]+/[a-zA-Z0-9_.-]+/?$') { return $false }
return $true
}
# Function to validate developer name
function Test-DeveloperName {
param([string]$name)
if ([string]::IsNullOrWhiteSpace($name)) { return $false }
if ($name.Length -lt 1 -or $name.Length -gt 256) { return $false }
return $true
}
# Prompt to continue
Write-Host "Do you want to continue? (Y/N): " -ForegroundColor Yellow -NoNewline
$continue = Read-Host
if ($continue -notmatch '^[Yy]') {
Write-Host ""
Write-Host "Setup cancelled by user." -ForegroundColor Yellow
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 0
}
Write-Host ""
# Collect GitHub Repository URL
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 1: GitHub Repository URL" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Enter your GitHub repository URL:" -ForegroundColor Yellow
Write-Host " This is where your extension's releases will be published." -ForegroundColor Gray
Write-Host ""
Write-Host " Format: https://github.com/username/repository" -ForegroundColor DarkGray
Write-Host " Example: https://github.com/johndoe/MyAwesomeExtension" -ForegroundColor DarkGray
Write-Host ""
$githubRepoUrl = ""
$maxAttempts = 3
$attempt = 0
do {
$attempt++
Write-Host "GitHub Repository URL" -NoNewline -ForegroundColor Yellow
if ($attempt -gt 1) {
Write-Host " (Attempt $attempt of $maxAttempts)" -NoNewline -ForegroundColor Red
}
Write-Host ": " -NoNewline -ForegroundColor Yellow
$githubRepoUrl = Read-Host
if ([string]::IsNullOrWhiteSpace($githubRepoUrl)) {
Write-Host " [ERROR] GitHub Repository URL cannot be empty." -ForegroundColor Red
Write-Host ""
}
elseif (-not (Test-GitHubUrl $githubRepoUrl)) {
Write-Host " [ERROR] Invalid GitHub URL format." -ForegroundColor Red
Write-Host " Please use format: https://github.com/username/repository" -ForegroundColor Yellow
Write-Host ""
}
else {
Write-Host " [OK] GitHub Repository URL accepted: $githubRepoUrl" -ForegroundColor Green
Write-Host ""
break
}
if ($attempt -ge $maxAttempts) {
Write-Host ""
Write-Host "Maximum attempts reached. Please try again with a valid GitHub URL." -ForegroundColor Red
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
exit 1
}
} while ($true)
# Collect Developer Name
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Step 2: Developer/Publisher Name" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Enter your developer or publisher name:" -ForegroundColor Yellow
Write-Host " This will appear in the EXE installer as the publisher." -ForegroundColor Gray
Write-Host ""
Write-Host " IMPORTANT: If you published to Microsoft Store, this should match" -ForegroundColor Yellow
Write-Host " the PublisherDisplayName from your Store configuration." -ForegroundColor Yellow
Write-Host ""
Write-Host " Example: John Doe" -ForegroundColor DarkGray
Write-Host " Example: Contoso Software" -ForegroundColor DarkGray
Write-Host ""
Write-Host " Current value from manifest: $publisherDisplayName" -ForegroundColor Cyan
Write-Host ""
$developerName = ""
$attempt = 0
do {
$attempt++
Write-Host "Developer Name" -NoNewline -ForegroundColor Yellow
if ($attempt -gt 1) {
Write-Host " (Attempt $attempt of $maxAttempts)" -NoNewline -ForegroundColor Red
}
Write-Host " [press Enter to use default]: " -NoNewline -ForegroundColor Yellow
$input = Read-Host
if ([string]::IsNullOrWhiteSpace($input)) {
$developerName = $publisherDisplayName
Write-Host " [OK] Using default: $developerName" -ForegroundColor Green
Write-Host ""
break
}
elseif (-not (Test-DeveloperName $input)) {
Write-Host " [ERROR] Invalid developer name." -ForegroundColor Red
Write-Host ""
}
else {
$developerName = $input
Write-Host " [OK] Developer name accepted: $developerName" -ForegroundColor Green
Write-Host ""
break
}
if ($attempt -ge $maxAttempts) {
Write-Host ""
Write-Host "Maximum attempts reached. Using default: $publisherDisplayName" -ForegroundColor Yellow
$developerName = $publisherDisplayName
Write-Host ""
break
}
} while ($true)
# Update files
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Updating Configuration Files..." -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
# Update build-exe.ps1
Write-Host "[1/3] Updating build-exe.ps1..." -ForegroundColor Cyan
try {
$buildExeContent = Get-Content $buildExePath -Raw -ErrorAction Stop
# Update ExtensionName default value
$buildExeContent = $buildExeContent -replace '\[string\]\$ExtensionName = "UPDATE"', "[string]`$ExtensionName = `"$projectName`""
# Update Version default value
$buildExeContent = $buildExeContent -replace '\[string\]\$Version = "UPDATE"', "[string]`$Version = `"$packageVersion`""
Set-Content -Path $buildExePath -Value $buildExeContent -NoNewline -ErrorAction Stop
Write-Host " [SUCCESS] build-exe.ps1 updated" -ForegroundColor Green
Write-Host ""
}
catch {
Write-Host " [ERROR] Could not update build-exe.ps1: $($_.Exception.Message)" -ForegroundColor Red
Write-Host ""
}
# Update setup-template.iss
Write-Host "[2/3] Updating setup-template.iss..." -ForegroundColor Cyan
try {
$setupTemplateContent = Get-Content $setupTemplatePath -Raw -ErrorAction Stop
# Update version
$setupTemplateContent = $setupTemplateContent -replace '#define AppVersion ".*"', "#define AppVersion `"$packageVersion`""
# Update AppId GUID
$setupTemplateContent = $setupTemplateContent -replace 'AppId=\{\{GUID-HERE\}\}', "AppId={{$extensionGuid}}"
# Update AppName (DISPLAY_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'AppName=DISPLAY_NAME', "AppName=$displayName"
# Update AppPublisher (DEVELOPER_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'AppPublisher=DEVELOPER_NAME', "AppPublisher=$developerName"
# Update DefaultDirName (EXTENSION_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'DefaultDirName=\{autopf\}\\EXTENSION_NAME', "DefaultDirName={autopf}\$projectName"
# Update OutputBaseFilename (EXTENSION_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'OutputBaseFilename=EXTENSION_NAME-Setup', "OutputBaseFilename=$projectName-Setup"
# Update Icon name (DISPLAY_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'Name: "\{group\}\\DISPLAY_NAME"', "Name: `"{group}\$displayName`""
# Update Icon filename (EXTENSION_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'Filename: "\{app\}\\EXTENSION_NAME\.exe"', "Filename: `"{app}\$projectName.exe`""
# Update Registry CLSID entries
$setupTemplateContent = $setupTemplateContent -replace 'CLSID\\CLSID-HERE', "CLSID\{{$extensionGuid}}"
$setupTemplateContent = $setupTemplateContent -replace '\{\{CLSID-HERE\}\}', "{{$extensionGuid}}"
# Update Registry ValueData (EXTENSION_NAME)
$setupTemplateContent = $setupTemplateContent -replace 'ValueData: "EXTENSION_NAME"', "ValueData: `"$projectName`""
# Update LocalServer32 ValueData
$setupTemplateContent = $setupTemplateContent -replace 'ValueData: "\{app\}\\EXTENSION_NAME\.exe', "ValueData: `"{app}\$projectName.exe"
Set-Content -Path $setupTemplatePath -Value $setupTemplateContent -NoNewline -ErrorAction Stop
Write-Host " [SUCCESS] setup-template.iss updated" -ForegroundColor Green
Write-Host ""
}
catch {
Write-Host " [ERROR] Could not update setup-template.iss: $($_.Exception.Message)" -ForegroundColor Red
Write-Host ""
}
# Update release-extension.yml
Write-Host "[3/3] Updating release-extension.yml..." -ForegroundColor Cyan
try {
$releaseYmlContent = Get-Content $releaseYmlPath -Raw -ErrorAction Stop
# Update workflow name
$releaseYmlContent = $releaseYmlContent -replace 'name: CmdPal Extension - Build EXE Installer', "name: $displayName - Build EXE Installer"
# Update environment variables with actual values
$releaseYmlContent = $releaseYmlContent -replace "DISPLAY_NAME: \$\{\{ vars\.DISPLAY_NAME \|\| 'DISPLAY_NAME' \}\}", "DISPLAY_NAME: `${{ vars.DISPLAY_NAME || '$displayName' }}"
$releaseYmlContent = $releaseYmlContent -replace "EXTENSION_NAME: \$\{\{ vars\.EXTENSION_NAME \|\| 'EXTENSION_NAME' \}\}", "EXTENSION_NAME: `${{ vars.EXTENSION_NAME || '$projectName' }}"
$releaseYmlContent = $releaseYmlContent -replace "FOLDER_NAME: \$\{\{ vars\.FOLDER_NAME \|\| 'FOLDER_NAME' \}\}", "FOLDER_NAME: `${{ vars.FOLDER_NAME || '$projectName' }}"
$releaseYmlContent = $releaseYmlContent -replace "GITHUB_REPO_URL: \$\{\{ vars\.GITHUB_REPO_URL \|\| 'GITHUB_REPO_URL' \}\}", "GITHUB_REPO_URL: `${{ vars.GITHUB_REPO_URL || '$githubRepoUrl' }}"
Set-Content -Path $releaseYmlPath -Value $releaseYmlContent -NoNewline -ErrorAction Stop
Write-Host " [SUCCESS] release-extension.yml updated" -ForegroundColor Green
Write-Host ""
}
catch {
Write-Host " [ERROR] Could not update release-extension.yml: $($_.Exception.Message)" -ForegroundColor Red
Write-Host ""
}
# Display summary
Write-Host "================================================================" -ForegroundColor Green
Write-Host " CONFIGURATION SUMMARY" -ForegroundColor White
Write-Host "================================================================" -ForegroundColor Green
Write-Host " Extension Name:" -ForegroundColor Gray
Write-Host " $projectName" -ForegroundColor White
Write-Host ""
Write-Host " Display Name:" -ForegroundColor Gray
Write-Host " $displayName" -ForegroundColor White
Write-Host ""
Write-Host " Version:" -ForegroundColor Gray
Write-Host " $packageVersion" -ForegroundColor White
Write-Host ""
Write-Host " Developer:" -ForegroundColor Gray
Write-Host " $developerName" -ForegroundColor White
Write-Host ""
Write-Host " Extension GUID:" -ForegroundColor Gray
Write-Host " $extensionGuid" -ForegroundColor White
Write-Host ""
Write-Host " GitHub Repository:" -ForegroundColor Gray
Write-Host " $githubRepoUrl" -ForegroundColor White
Write-Host "================================================================" -ForegroundColor Green
Write-Host ""
# Display modified files
Write-Host "Updated Files:" -ForegroundColor Yellow
$buildExeRelative = $buildExePath -replace [regex]::Escape($projectRoot + "\"), ""
$setupTemplateRelative = $setupTemplatePath -replace [regex]::Escape($projectRoot + "\"), ""
$releaseYmlRelative = $releaseYmlPath -replace [regex]::Escape($projectRoot + "\"), ""
Write-Host " [OK] $buildExeRelative" -ForegroundColor Green
Write-Host " [OK] $setupTemplateRelative" -ForegroundColor Green
Write-Host " [OK] $releaseYmlRelative" -ForegroundColor Green
Write-Host ""
if ($backupDir) {
Write-Host "Backup Location:" -ForegroundColor Yellow
$backupRelative = $backupDir -replace [regex]::Escape($projectRoot + "\"), ""
Write-Host " $backupRelative" -ForegroundColor Gray
Write-Host ""
}
# Move files to correct locations
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Moving Files to Correct Locations" -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "The following file will be moved:" -ForegroundColor Yellow
Write-Host " - release-extension.yml → .github/workflows/ (2 levels up)" -ForegroundColor Gray
Write-Host ""
Write-Host "The following files will remain in winget-resources:" -ForegroundColor Yellow
Write-Host " - build-exe.ps1" -ForegroundColor Gray
Write-Host " - setup-template.iss" -ForegroundColor Gray
Write-Host ""
# Calculate destination paths
# From: TemplateCmdPalExtension/Publication/winget-resources/
# release-extension.yml → TemplateCmdPalExtension/.github/workflows/ (2 levels up from Publication)
# GitHub workflows directory (2 levels up from Publication)
$solutionRoot = Split-Path -Parent $projectRoot
$githubWorkflowsDir = Join-Path $solutionRoot ".github\workflows"
$releaseYmlDestination = Join-Path $githubWorkflowsDir "release-extension.yml"
Write-Host "Destination:" -ForegroundColor Yellow
Write-Host " release-extension.yml → $releaseYmlDestination" -ForegroundColor Gray
Write-Host ""
# Move release-extension.yml
Write-Host "Moving release-extension.yml..." -ForegroundColor Cyan
try {
if (-not (Test-Path $githubWorkflowsDir)) {
Write-Host " Creating .github/workflows directory..." -ForegroundColor Gray
New-Item -Path $githubWorkflowsDir -ItemType Directory -Force | Out-Null
}
if (Test-Path $releaseYmlDestination) {
Write-Host " [WARNING] Destination file exists, overwriting..." -ForegroundColor Yellow
}
Move-Item $releaseYmlPath -Destination $releaseYmlDestination -Force -ErrorAction Stop
Write-Host " [SUCCESS] Moved to: $releaseYmlDestination" -ForegroundColor Green
}
catch {
Write-Host " [ERROR] Could not move release-extension.yml: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host ""
# Verify file was moved
Write-Host "Verifying file..." -ForegroundColor Cyan
if (Test-Path $releaseYmlDestination) {
Write-Host " [OK] release-extension.yml exists at destination" -ForegroundColor Green
}
else {
Write-Host " [ERROR] release-extension.yml NOT found at destination" -ForegroundColor Red
}
Write-Host ""
# Final instructions
Write-Host "================================================================" -ForegroundColor Green
Write-Host " Setup Completed Successfully!" -ForegroundColor Green
Write-Host "================================================================" -ForegroundColor Green
Write-Host ""
Write-Host "Files have been configured:" -ForegroundColor Yellow
Write-Host " Updated (in winget-resources):" -ForegroundColor Cyan
Write-Host " $buildExePath" -ForegroundColor White
Write-Host " $setupTemplatePath" -ForegroundColor White
Write-Host ""
Write-Host " Moved to GitHub workflows:" -ForegroundColor Cyan
Write-Host " $releaseYmlDestination" -ForegroundColor White
Write-Host ""
Write-Host "Next Steps:" -ForegroundColor Cyan
Write-Host " 1. Review the configured files to ensure correctness" -ForegroundColor Gray
Write-Host " 2. Add and commit files and push to Github" -ForegroundColor Gray
Write-Host " 3. Follow instructions at https://learn.microsoft.com//windows/powertoys/command-palette/publish-extension" -ForegroundColor Gray
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

View File

@@ -1,114 +0,0 @@
# TEMPLATE: PowerShell Build Script for Command Palette Extensions
#
# To use this template for a new extension:
# 1. Copy this file to your extension's project folder as "build-exe.ps1"
# 2. Update in param():
# - EXTENSION_NAME with your extension name (e.g., CmdPalMyExtension)
# - VERSION with your extension version (e.g., 0.0.1.0)
param(
[string]$ExtensionName = "UPDATE", # Change to your extension name
[string]$Configuration = "Release",
[string]$Version = "UPDATE", # Change to your version
[string[]]$Platforms = @("x64", "arm64")
)
$ErrorActionPreference = "Stop"
Write-Host "Building $ExtensionName EXE installer..." -ForegroundColor Green
Write-Host "Version: $Version" -ForegroundColor Yellow
Write-Host "Platforms: $($Platforms -join ', ')" -ForegroundColor Yellow
# Get the project directory (two levels up from winget-resources)
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ProjectDir = Split-Path -Parent (Split-Path -Parent $ScriptDir)
$ProjectFile = "$ProjectDir\$ExtensionName.csproj"
Write-Host "Script directory: $ScriptDir" -ForegroundColor Cyan
Write-Host "Project directory: $ProjectDir" -ForegroundColor Cyan
# Clean previous builds
Write-Host "Cleaning previous builds..." -ForegroundColor Yellow
if (Test-Path "$ProjectDir\bin") {
Remove-Item -Path "$ProjectDir\bin" -Recurse -Force -ErrorAction SilentlyContinue
}
if (Test-Path "$ProjectDir\obj") {
Remove-Item -Path "$ProjectDir\obj" -Recurse -Force -ErrorAction SilentlyContinue
}
# Restore packages
Write-Host "Restoring NuGet packages..." -ForegroundColor Yellow
dotnet restore $ProjectFile
# Build for each platform
foreach ($Platform in $Platforms) {
Write-Host "`n=== Building $Platform ===" -ForegroundColor Cyan
# Build and publish
Write-Host "Building and publishing $Platform application..." -ForegroundColor Yellow
dotnet publish $ProjectFile `
--configuration $Configuration `
--runtime "win-$Platform" `
--self-contained true `
--output "$ProjectDir\bin\$Configuration\win-$Platform\publish"
if ($LASTEXITCODE -ne 0) {
Write-Warning "Build failed for $Platform with exit code: $LASTEXITCODE"
continue
}
# Check if files were published
$publishDir = "$ProjectDir\bin\$Configuration\win-$Platform\publish"
$fileCount = (Get-ChildItem -Path $publishDir -Recurse -File).Count
Write-Host "✅ Published $fileCount files to $publishDir" -ForegroundColor Green
# Create platform-specific setup script
Write-Host "Creating installer script for $Platform..." -ForegroundColor Yellow
$setupTemplate = Get-Content "$ScriptDir\setup-template.iss" -Raw
# Update version
$setupScript = $setupTemplate -replace '#define AppVersion ".*"', "#define AppVersion `"$Version`""
# Update output filename to include platform suffix
$setupScript = $setupScript -replace 'OutputBaseFilename=(.*?)\{#AppVersion\}', "OutputBaseFilename=`$1{#AppVersion}-$Platform"
# Update source path for the platform
$setupScript = $setupScript -replace 'Source: "bin\\Release\\win-x64\\publish', "Source: `"bin\Release\win-$Platform\publish"
# Add architecture settings after [Setup] section
if ($Platform -eq "arm64") {
$setupScript = $setupScript -replace '(\[Setup\][^\[]*)(MinVersion=)', "`$1ArchitecturesAllowed=arm64`r`nArchitecturesInstallIn64BitMode=arm64`r`n`$2"
} else {
$setupScript = $setupScript -replace '(\[Setup\][^\[]*)(MinVersion=)', "`$1ArchitecturesAllowed=x64compatible`r`nArchitecturesInstallIn64BitMode=x64compatible`r`n`$2"
}
$setupScript | Out-File -FilePath "$ProjectDir\setup-$Platform.iss" -Encoding UTF8
# Create installer with Inno Setup
Write-Host "Creating $Platform installer with Inno Setup..." -ForegroundColor Yellow
$InnoSetupPath = "${env:ProgramFiles(x86)}\Inno Setup 6\iscc.exe"
if (-not (Test-Path $InnoSetupPath)) {
$InnoSetupPath = "${env:ProgramFiles}\Inno Setup 6\iscc.exe"
}
if (Test-Path $InnoSetupPath) {
& $InnoSetupPath "$ProjectDir\setup-$Platform.iss"
if ($LASTEXITCODE -eq 0) {
$installer = Get-ChildItem "$ProjectDir\bin\$Configuration\installer\*-$Platform.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($installer) {
$sizeMB = [math]::Round($installer.Length / 1MB, 2)
Write-Host "✅ Created $Platform installer: $($installer.Name) ($sizeMB MB)" -ForegroundColor Green
} else {
Write-Warning "Installer file not found for $Platform"
}
} else {
Write-Warning "Inno Setup failed for $Platform with exit code: $LASTEXITCODE"
}
} else {
Write-Warning "Inno Setup not found at expected locations"
}
}
Write-Host "`n🎉 Build completed successfully!" -ForegroundColor Green

View File

@@ -1,127 +0,0 @@
# TEMPLATE: Extension EXE Installer Build and Release Workflow
#
# To use this template for a new extension:
# 1. Copy this file to a new workflow file (e.g., release-extension-exe.yml)
# 2. Update Global constants with your data:
# - GITHUB_REPO_URL with your GitHub repository URL (e.g., https://github.com/yourusername/YourRepository)
# - DISPLAY_NAME with your display name (e.g., My Extension)
# - EXTENSION_NAME with your extension name (e.g., CmdPalMyExtension)
# - FOLDER_NAME with your project folder name (e.g., CmdPalMyExtension)
name: CmdPal Extension - Build EXE Installer
on:
workflow_dispatch:
inputs:
version:
description: 'Version number (leave empty to auto-detect)'
required: false
type: string
release_notes:
description: 'What is new in this version'
required: false
default: 'New release with latest updates and improvements.'
type: string
# Global constants: UPDATE THESE, example; DISPLAY_NAME: ${{ vars.DISPLAY_NAME || 'CmdPal Name' }}
env:
DISPLAY_NAME: ${{ vars.DISPLAY_NAME || 'DISPLAY_NAME' }}
EXTENSION_NAME: ${{ vars.EXTENSION_NAME || 'EXTENSION_NAME' }}
FOLDER_NAME: ${{ vars.FOLDER_NAME || 'FOLDER_NAME' }}
GITHUB_REPO_URL: ${{ vars.GITHUB_REPO_URL || 'GITHUB_REPO_URL' }}
jobs:
build:
runs-on: windows-2022
permissions:
contents: write
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET 9
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install Inno Setup
run: choco install innosetup -y --no-progress
shell: pwsh
- name: Get version from project
id: version
run: |
if ("${{ github.event.inputs.version }}" -ne "") {
$version = "${{ github.event.inputs.version }}"
} else {
$projectFile = "${{ env.FOLDER_NAME }}/${{ env.EXTENSION_NAME }}.csproj"
$xml = [xml](Get-Content $projectFile)
$version = $xml.Project.PropertyGroup.AppxPackageVersion | Select-Object -First 1
if (-not $version) { throw "Version not found in project file" }
}
echo "VERSION=$version" >> $env:GITHUB_OUTPUT
Write-Host "Using version: $version"
shell: pwsh
- name: Build EXE installers (x64 and ARM64)
run: |
Set-Location "${{ env.FOLDER_NAME }}/Publication/winget-resources"
.\build-exe.ps1 -Version "${{ steps.version.outputs.VERSION }}" -Platforms @("x64", "arm64")
shell: pwsh
- name: Upload x64 installer artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.EXTENSION_NAME }}-x64-installer
path: ${{ env.FOLDER_NAME }}/bin/Release/installer/*-x64.exe
if-no-files-found: error
- name: Upload ARM64 installer artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.EXTENSION_NAME }}-arm64-installer
path: ${{ env.FOLDER_NAME }}/bin/Release/installer/*-arm64.exe
if-no-files-found: warn
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.EXTENSION_NAME }}-v${{ steps.version.outputs.VERSION }}
name: "${{ env.DISPLAY_NAME }} v${{ steps.version.outputs.VERSION }}"
body: |
## 🎯 ${{ env.DISPLAY_NAME }} ${{ steps.version.outputs.VERSION }}
## What's New
${{ github.event.inputs.release_notes }}
## 📦 Installation
Download the installer for your system architecture:
- **x64 (Intel/AMD)**: `${{ env.DISPLAY_NAME }}-Setup-${{ steps.version.outputs.VERSION }}-x64.exe`
- **ARM64 (Windows on ARM)**: `${{ env.DISPLAY_NAME }}-Setup-${{ steps.version.outputs.VERSION }}-arm64.exe`
1. Download the appropriate installer from the Assets section below
2. Run the installer with administrator privileges
3. The extension will be registered and available in Command Palette
## 🔗 More Information
Repository: ${{ env.GITHUB_REPO_URL }}
files: ${{ env.FOLDER_NAME }}/bin/Release/installer/*.exe
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build summary
run: |
Write-Host "🎉 ${{ env.DISPLAY_NAME }} Release Complete!" -ForegroundColor Green
Write-Host "Version: ${{ steps.version.outputs.VERSION }}" -ForegroundColor Yellow
Write-Host "📁 Installer uploaded to GitHub Release" -ForegroundColor Green
shell: pwsh

View File

@@ -1,36 +0,0 @@
; TEMPLATE: Inno Setup Script for Command Palette Extensions
;
; To use this template for a new extension:
; 1. Copy this file to your extension's project folder as "setup-template.iss"
; 2. Replace EXTENSION_NAME with your extension name (e.g., CmdPalMyExtension)
; 3. Replace DISPLAY_NAME with your extension's display name (e.g., My Extension)
; 4. Replace DEVELOPER_NAME with your name (e.g., Your Name Here)
; 5. Replace CLSID-HERE with extensions CLSID
; 6. Update the default version to match your project file
#define AppVersion "0.0.1.0"
[Setup]
AppId={{GUID-HERE}}
AppName=DISPLAY_NAME
AppVersion={#AppVersion}
AppPublisher=DEVELOPER_NAME
DefaultDirName={autopf}\EXTENSION_NAME
OutputDir=bin\Release\installer
OutputBaseFilename=EXTENSION_NAME-Setup-{#AppVersion}
Compression=lzma
SolidCompression=yes
MinVersion=10.0.19041
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "bin\Release\win-x64\publish\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
[Icons]
Name: "{group}\DISPLAY_NAME"; Filename: "{app}\EXTENSION_NAME.exe"
[Registry]
Root: HKCU; Subkey: "SOFTWARE\Classes\CLSID\{{CLSID-HERE}}"; ValueData: "EXTENSION_NAME"
Root: HKCU; Subkey: "SOFTWARE\Classes\CLSID\{{CLSID-HERE}}\LocalServer32"; ValueData: "{app}\EXTENSION_NAME.exe -RegisterProcessAsComServer"

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<RootNamespace>TemplateCmdPalExtension</RootNamespace>
@@ -10,58 +10,20 @@
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<EnableMsixTooling>true</EnableMsixTooling>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Content Include="Assets\**\*.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<PropertyGroup>
<!-- FOR PUBLISHING TO WINGET -->
<!-- When you're ready to publish your extension to winget,
comment out PublishProfile and uncomment WindowsPackageType tag to create
OR USE THE GITHUB ACTION TO DO THIS FOR YOU-->
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<!--<WindowsPackageType>None</WindowsPackageType> -->
<!-- FOR PUBLISHING TO MICROSOFT STORE 1 of 2-->
<!-- When you're ready to publish your extension to Microsoft Store, you'll need to change that are below
AppxPackageIdentityName = replace with Microsoft Store's Package/Identity/Name
AppxPackagePublisher = replace with Microsoft Store's Package/Identity/Publisher
-->
<!-- <AppxPackageIdentityName>YOUR_PACKAGE_IDENTITY_NAME_HERE</AppxPackageIdentityName>
<AppxPackagePublisher>YOUR_PACKAGE_IDENTITY_PUBLISHER_HERE</AppxPackagePublisher>
<AppxPackageVersion>0.0.1.0</AppxPackageVersion> -->
</PropertyGroup>
<!-- FOR PUBLISHING TO MICROSOFT STORE 2 of 2-->
<!-- When you're ready to publish your extension to Microsoft Store, uncomment the
Target tag and confirm the images exist -->
<!-- <Target Name="PrepareAssets" BeforeTargets="BeforeBuild">
<Copy SourceFiles="$(MSBuildProjectDirectory)\Assets\Square150x150Logo.scale-200.png"
DestinationFiles="$(MSBuildProjectDirectory)\Assets\Square150x150Logo.png"
SkipUnchangedFiles="true" />
<Copy SourceFiles="$(MSBuildProjectDirectory)\Assets\Square44x44Logo.scale-200.png"
DestinationFiles="$(MSBuildProjectDirectory)\Assets\SmallTile.png"
SkipUnchangedFiles="true" />
<Copy SourceFiles="$(MSBuildProjectDirectory)\Assets\Wide310x150Logo.scale-200.png"
DestinationFiles="$(MSBuildProjectDirectory)\Assets\Wide310x150Logo.png"
SkipUnchangedFiles="true" />
<Copy SourceFiles="$(MSBuildProjectDirectory)\Assets\SplashScreen.scale-200.png"
DestinationFiles="$(MSBuildProjectDirectory)\Assets\SplashScreen.png"
SkipUnchangedFiles="true" />
<Copy SourceFiles="$(MSBuildProjectDirectory)\Assets\Square150x150Logo.scale-200.png"
DestinationFiles="$(MSBuildProjectDirectory)\Assets\LargeTile.png"
SkipUnchangedFiles="true" />
<Copy SourceFiles="$(MSBuildProjectDirectory)\Assets\StoreLogo.scale-100.png"
DestinationFiles="$(MSBuildProjectDirectory)\Assets\StoreLogo.png"
SkipUnchangedFiles="true" />
</Target> -->
<ItemGroup>
<Manifest Include="$(ApplicationManifest)" />

View File

@@ -24,7 +24,7 @@
<ItemGroup>
<!-- Images -->
<Content Include=".\Assets\$(CmdPalAssetSuffix)\**\*">
<Content Include="$(SolutionDir)\src\modules\cmdpal\Microsoft.CmdPal.UI\Assets\$(CmdPalAssetSuffix)\**\*">
<DeploymentContent>true</DeploymentContent>
<Link>Assets\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Content>
@@ -35,10 +35,14 @@
<!-- In the future, when we actually want to support "preview" and "canary",
add a Package-Pre.appxmanifest, etc. -->
<AppxManifest Include="Package.appxmanifest" Condition="'$(CommandPaletteBranding)'=='Release'" />
<AppxManifest Include="Package.appxmanifest" Condition="'$(CommandPaletteBranding)'=='Preview'" />
<AppxManifest Include="Package.appxmanifest" Condition="'$(CommandPaletteBranding)'=='Canary'" />
<AppxManifest Include="Package-Dev.appxmanifest" Condition="'$(CommandPaletteBranding)'=='' or '$(CommandPaletteBranding)'=='Dev'" />
<AppxManifest Include="Package.appxmanifest"
Condition="'$(CommandPaletteBranding)'=='Release'" />
<AppxManifest Include="Package.appxmanifest"
Condition="'$(CommandPaletteBranding)'=='Preview'" />
<AppxManifest Include="Package.appxmanifest"
Condition="'$(CommandPaletteBranding)'=='Canary'" />
<AppxManifest Include="Package-Dev.appxmanifest"
Condition="'$(CommandPaletteBranding)'=='' or '$(CommandPaletteBranding)'=='Dev'" />
</ItemGroup>
</Project>

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<!-- Reset this because the Versioning task might have overwritten it before it knew about OutDir -->
<AppxPackageDir>$(OutputPath)\AppPackages\</AppxPackageDir>
</PropertyGroup>

View File

@@ -15,7 +15,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<LangVersion>preview</LangVersion>
<LangVersion>preview</LangVersion>
<Version>$(CmdPalVersion)</Version>
@@ -23,14 +23,13 @@
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<UseWinRT>true</UseWinRT>
</PropertyGroup>
<!-- For debugging purposes, uncomment this block to enable AOT builds -->
<!--<PropertyGroup>
<!--<PropertyGroup>
<EnableCmdPalAOT>true</EnableCmdPalAOT>
<GeneratePackageLocally>true</GeneratePackageLocally>
</PropertyGroup>-->
</PropertyGroup>-->
<PropertyGroup Condition="'$(EnableCmdPalAOT)' == 'true'">
<SelfContained>true</SelfContained>
@@ -46,7 +45,7 @@
</PropertyGroup>
<PropertyGroup>
<!-- This lets us actually reference types from Microsoft.Terminal.UI and CmdPalKeyboardService -->
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
<CsWinRTIncludes>Microsoft.Terminal.UI;CmdPalKeyboardService</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
@@ -102,7 +101,7 @@
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
<PackageReference Include="WinUIEx" />
<PackageReference Include="WinUIEx" />
<PackageReference Include="Microsoft.Windows.CsWin32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
@@ -148,16 +147,12 @@
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj" />
<ProjectReference Include="$(ProjectDir)\..\Microsoft.Terminal.UI\Microsoft.Terminal.UI.vcxproj">
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
<BuildProject>True</BuildProject>
<ProjectReference Include="..\Microsoft.Terminal.UI\Microsoft.Terminal.UI.vcxproj">
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
<!-- WinRT metadata reference -->
<CsWinRTInputs Include="$(OutputPath)\Microsoft.Terminal.UI.winmd" />
<!-- Native implementation DLL -->
<None Include="$(OutputPath)\Microsoft.Terminal.UI.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<ProjectReference Include="..\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj">
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
<Private>True</Private>

View File

@@ -12,9 +12,9 @@ namespace winrt::Microsoft::Terminal::UI::implementation
// Check if the code point is in the Private Use Area range used by Fluent UI icons.
[[nodiscard]] constexpr bool _isFluentIconPua(const UChar32 cp) noexcept
{
constexpr UChar32 fluentIconsPrivateUseAreaStart = 0xE700;
constexpr UChar32 fluentIconsPrivateUseAreaEnd = 0xF8FF;
return cp >= fluentIconsPrivateUseAreaStart && cp <= fluentIconsPrivateUseAreaEnd;
static constexpr UChar32 _fluentIconsPrivateUseAreaStart = 0xE700;
static constexpr UChar32 _fluentIconsPrivateUseAreaEnd = 0xF8FF;
return cp >= _fluentIconsPrivateUseAreaStart && cp <= _fluentIconsPrivateUseAreaEnd;
}
// Determine if the given text (as a sequence of UChar code units) is emoji

View File

@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup>
<PathToRoot>..\..\..\..\</PathToRoot>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.250907003</WasdkNuget>
</PropertyGroup>
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -27,11 +28,6 @@
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.26100.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.ImplementationLibrary" GeneratePathProperty="true" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM64">
@@ -51,6 +47,10 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
@@ -200,11 +200,43 @@
<Midl Include="FontIconGlyphClassifier.idl" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Microsoft.Terminal.UI.def" />
</ItemGroup>
<PropertyGroup>
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
<ImportGroup Label="ExtensionTargets">
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(MSBuildThisFileDirectory)..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- The packages.config acts as the global version for all of the NuGet packages contained within. -->
<packages>
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -3,9 +3,10 @@
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup>
<RepoRoot>$(MSBuildThisFileDirectory)..\..\..\..\..\</RepoRoot>
<WindowsSdkPackageVersion>10.0.26100.57</WindowsSdkPackageVersion>
<OutputPath>$(RepoRoot)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions.Toolkit</OutputPath>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions.Toolkit</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<ImplicitUsings>enable</ImplicitUsings>
@@ -20,7 +21,7 @@
<PropertyGroup Condition="'$(CIBuild)'=='true'">
<SignAssembly>true</SignAssembly>
<DelaySign>true</DelaySign>
<AssemblyOriginatorKeyFile>$(RepoRoot).pipelines\272MSSharedLibSN2048.snk</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)..\..\..\..\..\.pipelines\272MSSharedLibSN2048.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
@@ -46,19 +47,11 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.vcxproj">
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
<BuildProject>True</BuildProject>
</ProjectReference>
<CsWinRTInputs Include="$(RepoRoot)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.winmd" />
<!-- Native implementation DLL -->
<None Include="$(RepoRoot)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ProjectReference Include="..\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.vcxproj" />
</ItemGroup>
<ItemGroup>
<Content Include="$(RepoRoot)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.winmd" Link="Microsoft.CommandPalette.Extensions.winmd" CopyToOutputDirectory="PreserveNewest" />
<Content Include="$(SolutionDir)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.winmd" Link="Microsoft.CommandPalette.Extensions.winmd" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
<PropertyGroup>
<PathToRoot>..\..\..\..\..\</PathToRoot>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.250907003</WasdkNuget>
<CppWinRTNuget>$(PathToRoot)packages\Microsoft.Windows.CppWinRT.2.0.240111.5</CppWinRTNuget>
<WindowsSdkBuildToolsNuget>$(PathToRoot)packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.6901</WindowsSdkBuildToolsNuget>
<WebView2Nuget>$(PathToRoot)packages\Microsoft.Web.WebView2.1.0.2903.40</WebView2Nuget>
</PropertyGroup>
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.props')" />
<PropertyGroup Label="Globals">
<RepoRoot>$(MSBuildThisFileDirectory)..\..\..\..\..\</RepoRoot>
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
@@ -25,13 +25,7 @@
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
<WindowsAppSDKVerifyTransitiveDependencies>false</WindowsAppSDKVerifyTransitiveDependencies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.ImplementationLibrary" GeneratePathProperty="true" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM64">
@@ -51,6 +45,10 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
@@ -155,6 +153,7 @@
<Midl Include="Microsoft.CommandPalette.Extensions.idl" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Microsoft.CommandPalette.Extensions.def" />
</ItemGroup>
<ItemGroup>
@@ -162,9 +161,23 @@
<DeploymentContent>false</DeploymentContent>
</Text>
</ItemGroup>
<PropertyGroup>
<OutDir>$(RepoRoot)$(Platform)\$(Configuration)\Microsoft.CommandPalette.Extensions\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="$(WebView2Nuget)\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('$(WebView2Nuget)\build\native\Microsoft.Web.WebView2.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(WindowsSdkBuildToolsNuget)\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(CppWinRTNuget)\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('$(WebView2Nuget)\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(WebView2Nuget)\build\native\Microsoft.Web.WebView2.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.6901" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -1,16 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -35,17 +37,9 @@
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>PowerToys.PowerRename.pri</ProjectPriFileName>
<RuntimeIdentifier>win10-x64;win10-arm64</RuntimeIdentifier>
<WindowsAppSDKVerifyTransitiveDependencies>false</WindowsAppSDKVerifyTransitiveDependencies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.ImplementationLibrary" GeneratePathProperty="true" />
<PackageReference Include="boost" GeneratePathProperty="true" />
<PackageReference Include="boost_regex-vc143" GeneratePathProperty="true" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
@@ -218,10 +212,54 @@
<ResourceCompile Include="PowerRenameUI.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="..\..\..\..\packages\boost.1.87.0\build\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.87.0\build\boost.targets')" />
<Import Project="..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets" Condition="Exists('..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\boost.1.87.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost.1.87.0\build\boost.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets'))" />
</Target>
<Target Name="AddWildCardItems" AfterTargets="BuildGenerateSources">
<ItemGroup>
<PRIResource Include="@(_WildCardPRIResource)" />
</ItemGroup>
</Target>
</Project>
</Project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="boost" version="1.87.0" targetFramework="native" />
<package id="boost_regex-vc143" version="1.87.0" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -407,18 +407,15 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY
hour12 = 12;
}
// Order matters. Longer patterns are processed before any prefixes.
// Years.
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%04d"), L"$01", fileTime.wYear);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$YYYY"), replaceTerm);
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", (fileTime.wYear % 100));
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$YY"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$YY(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $YYY, $YYYY, or metadata patterns
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", (fileTime.wYear % 10));
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$Y"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$Y(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $YY, $YYYY, or metadata patterns
// Months.
GetDateFormatEx(localeName, NULL, &fileTime, L"MMMM", formattedDate, MAX_PATH, NULL);
formattedDate[0] = towupper(formattedDate[0]);
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
@@ -427,15 +424,14 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY
GetDateFormatEx(localeName, NULL, &fileTime, L"MMM", formattedDate, MAX_PATH, NULL);
formattedDate[0] = towupper(formattedDate[0]);
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MMM"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MMM(?!M)"), replaceTerm); // Negative lookahead prevents matching $MMMM
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wMonth);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MM"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$MM(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $MMM, $MMMM, or metadata patterns
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wMonth);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$M"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$M(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $MM, $MMM, $MMMM, or metadata patterns
// Days.
GetDateFormatEx(localeName, NULL, &fileTime, L"dddd", formattedDate, MAX_PATH, NULL);
formattedDate[0] = towupper(formattedDate[0]);
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
@@ -444,27 +440,19 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY
GetDateFormatEx(localeName, NULL, &fileTime, L"ddd", formattedDate, MAX_PATH, NULL);
formattedDate[0] = towupper(formattedDate[0]);
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", formattedDate);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DDD"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DDD(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $DDDD or metadata patterns
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wDay);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DD"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$DD(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $DDD, $DDDD, or metadata patterns
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wDay);
// $D overlaps with metadata patterns like $DATE_TAKEN_YYYY, so we use negative
// lookahead to prevent matching those.
res = regex_replace(
res,
std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$D(?!(ATE_TAKEN_|ESCRIPTION|OCUMENT_ID))"), /* #no-spell-check-line */
replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$D(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $DD, $DDD, $DDDD, or metadata patterns like $DATE_TAKEN_YYYY
// Time.
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", hour12);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$HH"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$HH(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $HHH or metadata patterns
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", hour12);
// $H overlaps with metadata's $HEIGHT, so we use negative lookahead to prevent
// matching that.
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$H(?!(EIGHT))"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$H(?![A-Z])"), replaceTerm); // Negative lookahead prevents matching $HH or metadata patterns
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", (fileTime.wHour < 12) ? L"AM" : L"PM");
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$TT"), replaceTerm);
@@ -473,31 +461,31 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$tt"), replaceTerm);
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wHour);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$hh"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$hh(?!h)"), replaceTerm); // Negative lookahead prevents matching $hhh
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wHour);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$h"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$h(?!h)"), replaceTerm); // Negative lookahead prevents matching $hh
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wMinute);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$mm"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$mm(?!m)"), replaceTerm); // Negative lookahead prevents matching $mmm
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wMinute);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$m"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$m(?!m)"), replaceTerm); // Negative lookahead prevents matching $mm
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wSecond);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$ss"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$ss(?!s)"), replaceTerm); // Negative lookahead prevents matching $sss
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wSecond);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$s"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$s(?!s)"), replaceTerm); // Negative lookahead prevents matching $ss
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%03d"), L"$01", fileTime.wMilliseconds);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$fff"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$fff(?!f)"), replaceTerm); // Negative lookahead prevents matching $ffff
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wMilliseconds / 10);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$ff"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$ff(?!f)"), replaceTerm); // Negative lookahead prevents matching $fff
StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wMilliseconds / 100);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$f"), replaceTerm);
res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$f(?!f)"), replaceTerm); // Negative lookahead prevents matching $ff or $fff
hr = StringCchCopy(result, cchMax, res.c_str());
}

View File

@@ -507,26 +507,24 @@ namespace HelpersTests
return testTime;
}
// Category 1: Tests for patterns with extra characters. Verifies negative
// lookahead doesn't cause issues with partially matched patterns and the
// ordering of pattern matches is correct, i.e. longer patterns are matched
// first.
// Category 1: Tests for invalid patterns with extra characters (verify negative lookahead prevents wrong matching)
TEST_METHOD(ValidPattern_YYY_PartiallyMatched)
TEST_METHOD(InvalidPattern_YYY_NotMatched)
{
// Test $YYY (3 Y's) is recognized as a valid pattern $YY plus a verbatim 'Y'
// Test $YYY (3 Y's) is not a valid pattern and should remain unchanged
// Negative lookahead in $YY(?!Y) prevents matching $YYY
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$YYY", testTime);
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_24Y", result);
Assert::AreEqual(L"file_$YYY", result); // $YYY is invalid, should remain unchanged
}
TEST_METHOD(ValidPattern_DDD_Matched)
TEST_METHOD(InvalidPattern_DDD_NotPartiallyMatched)
{
// Test that $DDD (short weekday) is not confused with $DD (2-digit day)
// Verifies that the matching of $DDD before $DD works correctly
// This verifies negative lookahead works correctly
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$DDD", testTime);
@@ -535,10 +533,9 @@ namespace HelpersTests
Assert::AreEqual(L"file_Fri", result); // Should be "Fri", not "15D"
}
TEST_METHOD(ValidPattern_MMM_Matched)
TEST_METHOD(InvalidPattern_MMM_NotPartiallyMatched)
{
// Test that $MMM (short month name) is not confused with $MM (2-digit month)
// Verifies that the matching of $MMM before $MM works correctly
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$MMM", testTime);
@@ -547,16 +544,15 @@ namespace HelpersTests
Assert::AreEqual(L"file_Mar", result); // Should be "Mar", not "03M"
}
TEST_METHOD(ValidPattern_HHH_PartiallyMatched)
TEST_METHOD(InvalidPattern_HHH_NotMatched)
{
// Test $HHH (3 H's) should match $HH and leave extra H unchanged
// Also confirms that $HH is matched before $H
// Test $HHH (3 H's) is not valid and negative lookahead prevents $HH from matching
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$HHH", testTime);
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_02H", result);
Assert::AreEqual(L"file_$HHH", result); // Should remain unchanged
}
TEST_METHOD(SeparatedPatterns_SingleY)
@@ -673,9 +669,9 @@ namespace HelpersTests
Assert::AreEqual(E_INVALIDARG, hr);
}
// Category 4: Tests to explicitly verify execution order
// Category 4: Tests to explicitly verify negative lookahead is working
TEST_METHOD(ExecutionOrder_YearNotMatchedInYYYY)
TEST_METHOD(NegativeLookahead_YearNotMatchedInYYYY)
{
// Verify $Y doesn't match when part of $YYYY
SYSTEMTIME testTime = GetTestTime();
@@ -686,9 +682,9 @@ namespace HelpersTests
Assert::AreEqual(L"file_2024", result); // Should be "2024", not "202Y"
}
TEST_METHOD(ExecutionOrder_MonthNotMatchedInMMM)
TEST_METHOD(NegativeLookahead_MonthNotMatchedInMMM)
{
// Verify $M or $MM don't match when $MMM is given
// Verify $M doesn't match when part of $MMM
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$MMM", testTime);
@@ -697,9 +693,9 @@ namespace HelpersTests
Assert::AreEqual(L"file_Mar", result); // Should be "Mar", not "3ar"
}
TEST_METHOD(ExecutionOrder_DayNotMatchedInDDDD)
TEST_METHOD(NegativeLookahead_DayNotMatchedInDDDD)
{
// Verify $D or $DD don't match when $DDDD is given
// Verify $D doesn't match when part of $DDDD
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$DDDD", testTime);
@@ -708,7 +704,7 @@ namespace HelpersTests
Assert::AreEqual(L"file_Friday", result); // Should be "Friday", not "15riday"
}
TEST_METHOD(ExecutionOrder_HourNotMatchedInHH)
TEST_METHOD(NegativeLookahead_HourNotMatchedInHH)
{
// Verify $H doesn't match when part of $HH
// Note: $HH is 12-hour format, so 14:00 (2 PM) displays as "02"
@@ -720,9 +716,9 @@ namespace HelpersTests
Assert::AreEqual(L"file_02", result); // 14:00 in 12-hour format is "02 PM"
}
TEST_METHOD(ExecutionOrder_MillisecondNotMatchedInFFF)
TEST_METHOD(NegativeLookahead_MillisecondNotMatchedInFFF)
{
// Verify $f or $ff don't match when $fff is given
// Verify $f doesn't match when part of $fff
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$fff", testTime);
@@ -766,68 +762,5 @@ namespace HelpersTests
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"15-15-Fri-Friday", result);
}
// Category 6: Specific bug fixes and collision avoidance
TEST_METHOD(BugFix_DDT_AllowsSuffixT)
{
// #44202 - $DDT should be allowed and matched as $DD plus verbatim 'T'. It
// was previously blocked due to the negative lookahead for any capital
// letter after $DD.
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$DDT", testTime);
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_15T", result);
}
TEST_METHOD(RelaxedConstraint_VerbatimCapitalAfterPatterns)
{
// Verify that patterns can be followed by capital letters that are not part
// of longer patterns, e.g., $DDC should match $DD + 'C'.
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$YYYYA_$MMB_$DDC", testTime); /* #no-spell-check-line */
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_2024A_03B_15C", result);
}
TEST_METHOD(Collision_DateTaken_Protected)
{
// Verify that date patterns do not collide with metadata patterns like
// DATE_TAKEN_YYYY.
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$DATE_TAKEN_YYYY", testTime);
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_$DATE_TAKEN_YYYY", result); // Not replaced
}
TEST_METHOD(Collision_Height_Protected)
{
// Verify that HEIGHT metadata pattern does not collide with date pattern $H.
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$HEIGHT", testTime);
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_$HEIGHT", result); // Not replaced
}
TEST_METHOD(Collision_SafeSuffix_Deer)
{
// Verifies that patterns can be safely followed by certain suffix letters as
// long as they don't match a longer pattern. $DEER should be matched as
// $D + 'EER'
SYSTEMTIME testTime = GetTestTime();
wchar_t result[MAX_PATH] = { 0 };
HRESULT hr = GetDatedFileName(result, MAX_PATH, L"file_$DEER", testTime);
Assert::IsTrue(SUCCEEDED(hr));
Assert::AreEqual(L"file_15EER", result);
}
};
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<!-- Windows App SDK and all transitive dependencies -->
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
</packages>

View File

@@ -1,34 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted ..\..\tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h runner.base.rc runner.rc" />
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)\tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h runner.base.rc runner.rc" />
</Target>
<PropertyGroup>
<NoWarn>81010002</NoWarn>
</PropertyGroup>
<PropertyGroup Label="NuGet">
<!-- Tell NuGet this is PackageReference style -->
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<!-- Tell NuGet we're a native project -->
<NuGetTargetMoniker>native,Version=v0.0</NuGetTargetMoniker>
<!-- Tell NuGet we target Windows (use your existing WindowsTargetPlatformVersion) -->
<NuGetTargetPlatformIdentifier>Windows</NuGetTargetPlatformIdentifier>
<NuGetTargetPlatformVersion>$(WindowsTargetPlatformVersion)</NuGetTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}</ProjectGuid>
<RootNamespace>powertoys</RootNamespace>
<ProjectName>runner</ProjectName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.WindowsAppSDK.Foundation" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CppWinRT" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.ImplementationLibrary" GeneratePathProperty="true" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="..\..\deps\expected.props" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<ImportGroup Label="Shared" />
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -38,6 +31,10 @@
<WindowsAppSdkUndockedRegFreeWinRTInitialize>true</WindowsAppSdkUndockedRegFreeWinRTInitialize>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@@ -133,6 +130,9 @@
<Project>{17da04df-e393-4397-9cf0-84dabe11032e}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Manifest Include="PowerToys.exe.manifest" />
</ItemGroup>
@@ -141,15 +141,39 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\deps\spdlog.props" />
<!-- Deduplicate WindowsAppRuntimeAutoInitializer.cpp (added twice via transitive imports causing LNK4042). Remove all then add exactly once. -->
<Target Name="FixWinAppSDKAutoInitializer" BeforeTargets="ClCompile" AfterTargets="WindowsAppRuntimeAutoInitializer">
<ItemGroup>
<!-- Remove ALL injected versions of the file -->
<ClCompile Remove="@(ClCompile)" Condition="'%(Filename)' == 'WindowsAppRuntimeAutoInitializer'" />
<!-- Add ONE copy back manually -->
<ClCompile Include="$(PkgMicrosoft_WindowsAppSDK_Foundation)\include\WindowsAppRuntimeAutoInitializer.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
</Target>
</Project>

View File

@@ -118,6 +118,7 @@
<CopyFileToFolders Include="svgs\icon.ico" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="runner.base.rc" />
</ItemGroup>
<ItemGroup>

View File

@@ -314,7 +314,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
string selectedType = draft.ServiceType ?? string.Empty;
AIServiceType serviceKind = draft.ServiceTypeKind;
bool requiresEndpoint = RequiresEndpointForService(serviceKind);
bool requiresEndpoint = serviceKind is AIServiceType.AzureOpenAI
or AIServiceType.AzureAIInference
or AIServiceType.Mistral
or AIServiceType.Ollama;
bool requiresDeployment = serviceKind == AIServiceType.AzureOpenAI;
bool requiresApiVersion = serviceKind == AIServiceType.AzureOpenAI;
bool requiresModelPath = serviceKind == AIServiceType.Onnx;
@@ -785,17 +788,12 @@ namespace Microsoft.PowerToys.Settings.UI.Views
string serviceType = draft.ServiceType ?? "OpenAI";
string apiKey = PasteAIApiKeyPasswordBox.Password;
string trimmedApiKey = apiKey?.Trim() ?? string.Empty;
var serviceKind = draft.ServiceTypeKind;
bool requiresEndpoint = RequiresEndpointForService(serviceKind);
string endpoint = (draft.EndpointUrl ?? string.Empty).Trim();
// Never persist placeholder text or stale values for services that don't use an endpoint.
if (!requiresEndpoint)
if (endpoint == string.Empty)
{
endpoint = string.Empty;
endpoint = GetEndpointPlaceholder(draft.ServiceTypeKind);
}
// For endpoint-based services, keep empty if the user didn't provide a value.
if (RequiresApiKeyForService(serviceType) && string.IsNullOrWhiteSpace(trimmedApiKey))
{
args.Cancel = true;
@@ -835,14 +833,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
};
}
private static bool RequiresEndpointForService(AIServiceType serviceKind)
{
return serviceKind is AIServiceType.AzureOpenAI
or AIServiceType.AzureAIInference
or AIServiceType.Mistral
or AIServiceType.Ollama;
}
private static string GetEndpointPlaceholder(AIServiceType serviceKind)
{
return serviceKind switch
@@ -851,7 +841,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
AIServiceType.AzureAIInference => "https://{resource-name}.cognitiveservices.azure.com/",
AIServiceType.Mistral => "https://api.mistral.ai/v1/",
AIServiceType.Ollama => "http://localhost:11434/",
_ => string.Empty,
_ => "https://your-resource.openai.azure.com/",
};
}