Compare commits

..

2 Commits

Author SHA1 Message Date
Clint Rutkas
77f7906f0a adding in rename now too 2025-05-22 10:13:48 -07:00
Clint Rutkas
cda283f3ee Attempt to simplify upgrades 2025-05-22 10:05:52 -07:00
103 changed files with 1090 additions and 1483 deletions

View File

@@ -14,7 +14,6 @@ AColumn
acrt
ACTIVATEAPP
activationaction
ACTIVATEOPTIONS
ACVS
adaptivecards
ADate
@@ -1589,7 +1588,6 @@ steamapps
STGC
STGM
STGMEDIUM
STGMREAD
STICKYKEYS
sticpl
storelogo
@@ -1694,7 +1692,6 @@ TLayout
tlb
tlbimp
tlc
TGM
TNP
Toolhelp
toolkitconverters
@@ -1998,4 +1995,3 @@ culori
Evercoder
LCh
CIELCh
CLSCTXINPROCALL

View File

@@ -126,15 +126,16 @@ Get-ChildItem -Path $rootPath -Recurse packages.config | ForEach-Object {
}
# Update Directory.Packages.props file
Get-ChildItem -Path $rootPath -Recurse "Directory.Packages.props" | ForEach-Object {
$file = Read-FileWithEncoding -Path $_.FullName
$propsFile = [System.IO.Path]::Combine($rootPath,"Directory.Packages.props")
if (Test-Path $propsFile) {
$file = Read-FileWithEncoding -Path $propsFile
$content = $file.Content
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
Write-FileWithEncoding -Path $propsFile -Content $content -Encoding $file.encoding
Write-Host "Modified " $propsFile
}
}
@@ -143,8 +144,8 @@ 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
$newVersionString = '\Microsoft.WindowsAppSDK.' + $WinAppSDKVersion + '\'
$oldVersionString = '\\Microsoft.WindowsAppSDK.[-.0-9a-zA-Z]*\\'
$content = $content -replace $oldVersionString, $newVersionString
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
Write-Host "Modified " $_.FullName

View File

@@ -1,28 +1,7 @@
$VSInstances = ([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml))
$VSPackages = $VSInstances.instances.instance.packages.package
$LatestVCPackage = ($VSPackages | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" })
$LatestVCPackage = ($VSInstances.instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" })
$LatestVCToolsVersion = $LatestVCPackage.version;
$VSRoot = (& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property 'resolvedInstallationPath')
$VCToolsRoot = Join-Path $VSRoot "VC\Tools\MSVC"
# We have observed a few instances where the VC tools package version actually
# differs from the version on the files themselves. We might as well check
# whether the version we just found _actually exists_ before we use it.
# We'll use whichever highest version exists.
$PackageVCToolPath = Join-Path $VCToolsRoot $LatestVCToolsVersion
If ($Null -Eq (Get-Item $PackageVCToolPath -ErrorAction:Ignore)) {
$VCToolsVersions = Get-ChildItem $VCToolsRoot | ForEach-Object {
[Version]$_.Name
} | Sort -Descending
$LatestActualVCToolsVersion = $VCToolsVersions | Select -First 1
If ([Version]$LatestVCToolsVersion -Ne $LatestActualVCToolsVersion) {
Write-Output "VC Tools Mismatch: Directory = $LatestActualVCToolsVersion, Package = $LatestVCToolsVersion"
$LatestVCToolsVersion = $LatestActualVCToolsVersion.ToString(3)
}
}
Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion"
Write-Output "Updating VCToolsVersion environment variable for job"
Write-Output "##vso[task.setvariable variable=VCToolsVersion]$LatestVCToolsVersion"

View File

@@ -55,7 +55,7 @@
-->
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250401001" />
<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" />

View File

@@ -1472,7 +1472,7 @@ SOFTWARE.
- Microsoft.Windows.CsWin32 0.2.46-beta
- Microsoft.Windows.CsWinRT 2.2.0
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
- Microsoft.WindowsAppSDK 1.7.250513003
- Microsoft.WindowsAppSDK 1.7.250401001
- Microsoft.WindowsPackageManager.ComInterop 1.10.340
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
- Microsoft.Xaml.Behaviors.Wpf 1.1.39

View File

@@ -706,8 +706,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZones.FuzzTests", "src\modules\fancyzones\FancyZones.FuzzTests\FancyZones.FuzzTests.csproj", "{0217E86E-3476-9946-DE8E-9D200CEBD47A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
@@ -2598,14 +2596,6 @@ Global
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|ARM64.ActiveCfg = Release|ARM64
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.ActiveCfg = Release|x64
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.Build.0 = Release|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.Build.0 = Debug|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.ActiveCfg = Debug|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.Build.0 = Debug|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.ActiveCfg = Release|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.Build.0 = Release|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.ActiveCfg = Release|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2876,7 +2866,6 @@ Global
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{0217E86E-3476-9946-DE8E-9D200CEBD47A} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
EndGlobalSection

View File

@@ -7,6 +7,6 @@
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
<!-- Suppress DynamicallyAccessedMemberTypes.PublicParameterlessConstructor in fallback code path of Windows SDK projection -->
<WarningsNotAsErrors>IL2081;CsWinRT1028;$(WarningsNotAsErrors)</WarningsNotAsErrors>
<WarningsNotAsErrors>IL2081;$(WarningsNotAsErrors)</WarningsNotAsErrors>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,18 @@
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="ExtensionTargetsAppSdkCppProp">
<Import Project="$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImportsWinAppSdkCppProp" 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('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,5 @@
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.WindowsAppSDK.1.7.250401001\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(MsbuildThisFileDirectory)\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
</Project>

View File

@@ -92,9 +92,6 @@ namespace Microsoft.PowerToys.FilePreviewCommon
var run = 0;
var chunksLen = fileSize - QOI_PADDING_LENGTH;
var x = 0;
var rowAdd = bitmapData.Stride - (channels * bitmapData.Width);
for (var dataIndex = 0; dataIndex < dataLength; dataIndex += channels)
{
if (run > 0)
@@ -156,14 +153,6 @@ namespace Microsoft.PowerToys.FilePreviewCommon
bitmapPixel[3] = pixel.A;
}
}
x++;
if (x == bitmapData.Width)
{
// We align dataIndex with the stride
dataIndex += rowAdd;
x = 0;
}
}
bitmap.UnlockBits(bitmapData);

View File

@@ -6,10 +6,9 @@ using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using PowerToys.Interop;
namespace ManagedCommon
@@ -41,72 +40,25 @@ namespace ManagedCommon
/// <param name="isLocalLow">If the process using Logger is a low-privilege process.</param>
public static void InitializeLogger(string applicationLogPath, bool isLocalLow = false)
{
string basePath;
if (isLocalLow)
{
basePath = Environment.GetEnvironmentVariable("userprofile") + "\\appdata\\LocalLow\\Microsoft\\PowerToys" + applicationLogPath;
applicationLogPath = Environment.GetEnvironmentVariable("userprofile") + "\\appdata\\LocalLow\\Microsoft\\PowerToys" + applicationLogPath + "\\" + Version;
}
else
{
basePath = Constants.AppDataPath() + applicationLogPath;
applicationLogPath = Constants.AppDataPath() + applicationLogPath + "\\" + Version;
}
string versionedPath = Path.Combine(basePath, Version);
if (!Directory.Exists(versionedPath))
if (!Directory.Exists(applicationLogPath))
{
Directory.CreateDirectory(versionedPath);
Directory.CreateDirectory(applicationLogPath);
}
var logFilePath = Path.Combine(versionedPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
Trace.AutoFlush = true;
// Clean up old version log folders
Task.Run(() => DeleteOldVersionLogFolders(basePath, versionedPath));
}
/// <summary>
/// Deletes old version log folders, keeping only the current version's folder.
/// </summary>
/// <param name="basePath">The base path to the log files folder.</param>
/// <param name="currentVersionPath">The path to the current version's log folder.</param>
private static void DeleteOldVersionLogFolders(string basePath, string currentVersionPath)
{
try
{
if (!Directory.Exists(basePath))
{
return;
}
var dirs = Directory.GetDirectories(basePath)
.Select(d => new DirectoryInfo(d))
.OrderBy(d => d.CreationTime)
.Where(d => !string.Equals(d.FullName, currentVersionPath, StringComparison.OrdinalIgnoreCase))
.Take(3)
.ToList();
foreach (var directory in dirs)
{
try
{
Directory.Delete(directory.FullName, true);
LogInfo($"Deleted old log directory: {directory.FullName}");
Task.Delay(500).Wait();
}
catch (Exception ex)
{
LogError($"Failed to delete old log directory: {directory.FullName}", ex);
}
}
}
catch (Exception ex)
{
LogError("Error cleaning up old log folders", ex);
}
}
public static void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)

View File

@@ -152,7 +152,6 @@
</data>
<data name="ClipboardHistoryImage" xml:space="preserve">
<value>Image data</value>
<comment>Label used to represent an image in the clipboard history</comment>
</data>
<data name="ClipboardHistoryItemMoreOptionsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>More options</value>
@@ -195,19 +194,15 @@
</data>
<data name="TranscodeToMp3" xml:space="preserve">
<value>Transcode to .mp3</value>
<comment>Option to transcode audio files to MP3 format</comment>
</data>
<data name="TranscodeToMp4" xml:space="preserve">
<value>Transcode to .mp4 (H.264/AAC)</value>
<comment>Option to transcode video files to MP4 format with H.264 video codec and AAC audio codec</comment>
</data>
<data name="TranscodeErrorGeneral" xml:space="preserve">
<value>An error occurred while transcoding media file</value>
<comment>Error message displayed when media conversion fails for an unknown or general reason</comment>
</data>
<data name="TranscodeErrorUnsupportedCodec" xml:space="preserve">
<value>The media file contains an unsupported codec</value>
<comment>Error message displayed when media conversion fails due to an unsupported codec in the source file</comment>
</data>
<data name="PasteButtonAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Paste</value>

View File

@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\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')" />
<Import Project="..\..\..\WinAppSdkCppPre.props" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -136,24 +134,16 @@
<ResourceCompile Include="PowerToys.MeasureToolCore.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\WinAppSdkCppPost.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.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\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.7.250513003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.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.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\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.7.250513003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets'))" />
</Target>
</Project>

View File

@@ -4,5 +4,5 @@
<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.22621.2428" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.7.250513003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.7.250401001" targetFramework="native" />
</packages>

View File

@@ -13,7 +13,6 @@
#include <common/utils/winapi_error.h>
#include <common/utils/processApi.h>
#include <common/utils/elevation.h>
#include <common/utils/logger_helper.h>
HINSTANCE g_hInst_MouseWithoutBorders = 0;
@@ -410,12 +409,9 @@ public:
{
app_name = L"MouseWithoutBorders";
app_key = app_name;
LoggerHelpers::init_logger(app_key, L"ModuleInterface", LogSettings::mouseWithoutBordersLoggerName);
std::filesystem::path oldLogPath(PTSettingsHelper::get_module_save_folder_location(app_key));
oldLogPath.append("LogsModuleInterface");
LoggerHelpers::delete_old_log_folder(oldLogPath);
std::filesystem::path logFilePath(PTSettingsHelper::get_module_save_folder_location(app_key));
logFilePath.append(LogSettings::mouseWithoutBordersLogPath);
Logger::init(LogSettings::mouseWithoutBordersLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
try
{

View File

@@ -1,4 +1,4 @@
<Project>
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
@@ -9,7 +9,7 @@
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250401001" />
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="System.Text.Json" Version="9.0.5" />

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<RootNamespace>TemplateCmdPalExtension</RootNamespace>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup>

View File

@@ -11,7 +11,6 @@
<!-- Other merged dictionaries here -->
<ResourceDictionary Source="Styles/Button.xaml" />
<ResourceDictionary Source="Styles/Colors.xaml" />
<ResourceDictionary Source="Styles/TextBlock.xaml" />
<ResourceDictionary Source="Styles/TextBox.xaml" />
<ResourceDictionary Source="Styles/Settings.xaml" />
<ResourceDictionary Source="Controls/Tag.xaml" />

View File

@@ -34,13 +34,8 @@
Orientation="Vertical"
Spacing="4" />
<cmdpalUI:ContextItemTemplateSelector
x:Key="ContextItemTemplateSelector"
Critical="{StaticResource CriticalContextMenuViewModelTemplate}"
Default="{StaticResource DefaultContextMenuViewModelTemplate}" />
<!-- Template for context items in the context item menu -->
<DataTemplate x:Key="DefaultContextMenuViewModelTemplate" x:DataType="viewmodels:CommandContextItemViewModel">
<!-- Template for actions in the mode actions dropdown button -->
<DataTemplate x:Key="ContextMenuViewModelTemplate" x:DataType="viewmodels:CommandContextItemViewModel">
<Grid AutomationProperties.Name="{x:Bind Title, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
@@ -68,38 +63,6 @@
Text="{x:Bind RequestedShortcut, Mode=OneWay, Converter={StaticResource KeyChordToStringConverter}}" />
</Grid>
</DataTemplate>
<!-- Template for context items flagged as critical -->
<DataTemplate x:Key="CriticalContextMenuViewModelTemplate" x:DataType="viewmodels:CommandContextItemViewModel">
<Grid AutomationProperties.Name="{x:Bind Title, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<cpcontrols:IconBox
Width="16"
Height="16"
Margin="4,0,0,0"
HorizontalAlignment="Left"
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
SourceKey="{x:Bind Icon, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource ContextItemTitleTextBlockCriticalStyle}"
Text="{x:Bind Title, Mode=OneWay}" />
<TextBlock
Grid.Column="2"
Margin="16,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Style="{StaticResource ContextItemCaptionTextBlockCriticalStyle}"
Text="{x:Bind RequestedShortcut, Mode=OneWay, Converter={StaticResource KeyChordToStringConverter}}" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
@@ -274,7 +237,7 @@
Margin="-16,-12,-16,-12"
IsItemClickEnabled="True"
ItemClick="CommandsDropdown_ItemClick"
ItemTemplateSelector="{StaticResource ContextItemTemplateSelector}"
ItemTemplate="{StaticResource ContextMenuViewModelTemplate}"
ItemsSource="{x:Bind ViewModel.ContextMenu.FilteredItems, Mode=OneWay}"
KeyDown="CommandsDropdown_KeyDown"
SelectionMode="Single">

View File

@@ -1,21 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.CmdPal.UI;
internal sealed partial class ContextItemTemplateSelector : DataTemplateSelector
{
public DataTemplate? Default { get; set; }
public DataTemplate? Critical { get; set; }
protected override DataTemplate? SelectTemplateCore(object item)
{
return ((CommandContextItemViewModel)item).IsCritical ? Critical : Default;
}
}

View File

@@ -39,7 +39,9 @@
</PropertyGroup>
<!-- BODGY: XES Versioning and WinAppSDK get into a fight about the app manifest, which breaks WinAppSDK. -->
<Target Name="RearrangeXefVersioningAndWinAppSDKResourceGeneration" DependsOnTargets="GetNewAppManifestValues;CreateWinRTRegistration" BeforeTargets="XesWriteVersionInfoResourceFile">
<Target Name="RearrangeXefVersioningAndWinAppSDKResourceGeneration"
DependsOnTargets="GetNewAppManifestValues;CreateWinRTRegistration"
BeforeTargets="XesWriteVersionInfoResourceFile">
<PropertyGroup>
<!-- XES uses this property to store the "final" location of the app manifest, before it erases it.
We have to update it to the value WinAppSDK set it to. -->

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:CommunityToolkit.WinUI.Converters">
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<Style
x:Key="ContextItemTitleTextBlockCriticalStyle"
BasedOn="{StaticResource BaseTextBlockStyle}"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
<Setter Property="FontWeight" Value="Normal" />
</Style>
<Style
x:Key="ContextItemCaptionTextBlockCriticalStyle"
BasedOn="{StaticResource CaptionTextBlockStyle}"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
</Style>
</ResourceDictionary>

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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.7.250513003</WasdkNuget>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.7.250401001</WasdkNuget>
</PropertyGroup>
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" />
<PropertyGroup Label="Globals">

View File

@@ -1,6 +1,6 @@
# ![cmdpal logo](./Microsoft.CmdPal.UI/Assets/Stable/StoreLogo.scale-100.png) Command Palette
Windows Command Palette ("CmdPal") is the next iteration of PowerToys Run. With extensibility at its core, the Command Palette is your one-stop launcher to start _anything_.
Windows Command Palette ("CmdPal") is the next iteration of PowerToys Run. With extensibility at it's core, the Command Palette is your one-stop launcher to start _anything_.
By default, CmdPal is bound to <kbd>Win+Alt+Space</kbd>.

View File

@@ -71,7 +71,7 @@ public class AllAppsSettings : JsonSettingsManager
internal static string SettingsJsonPath()
{
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
string directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
Directory.CreateDirectory(directory);
// now, the state is just next to the exe

View File

@@ -8,12 +8,7 @@ using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Services.Maps;
using Windows.Win32;
using Windows.Win32.System.Com;
using Windows.Win32.UI.Shell;
using WyHash;
namespace Microsoft.CmdPal.Ext.Apps;
@@ -32,31 +27,26 @@ internal sealed partial class AppCommand : InvokableCommand
internal static async Task StartApp(string aumid)
{
var appManager = new ApplicationActivationManager();
const ActivateOptions noFlags = ActivateOptions.None;
await Task.Run(() =>
{
unsafe
try
{
IApplicationActivationManager* appManager = null;
try
{
PInvoke.CoCreateInstance(typeof(ApplicationActivationManager).GUID, null, CLSCTX.CLSCTX_INPROC_SERVER, out appManager).ThrowOnFailure();
using var handle = new SafeComHandle((IntPtr)appManager);
appManager->ActivateApplication(
aumid,
string.Empty,
ACTIVATEOPTIONS.AO_NONE,
out var unusedPid);
}
catch (System.Exception ex)
{
Logger.LogError(ex.Message);
}
appManager.ActivateApplication(aumid, /*queryArguments*/ string.Empty, noFlags, out var unusedPid);
}
catch (System.Exception ex)
{
Logger.LogError(ex.Message);
}
}).ConfigureAwait(false);
}
internal static async Task StartExe(string path)
{
var appManager = new ApplicationActivationManager();
// const ActivateOptions noFlags = ActivateOptions.None;
await Task.Run(() =>
{
try

View File

@@ -1,13 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Ext.Apps</RootNamespace>
<Nullable>enable</Nullable>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<DisableRuntimeMarshalling>true</DisableRuntimeMarshalling>
</PropertyGroup>
<ItemGroup>
@@ -51,9 +49,4 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="NativeMethods.txt" />
<AdditionalFiles Include="NativeMethods.json" />
</ItemGroup>
</Project>

View File

@@ -1,7 +0,0 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false,
"comInterop": {
"preserveSigMethods": [ "*" ]
}
}

View File

@@ -1,20 +1,19 @@
IStream
GetPhysicallyInstalledSystemMemory
GlobalMemoryStatusEx
GetSystemInfo
CoCreateInstance
IApplicationActivationManager
ApplicationActivationManager
SetForegroundWindow
IsIconic
RegisterHotKey
SetWindowLongPtr
CallWindowProc
ShowWindow
SetForegroundWindow
SetFocus
SetActiveWindow
MonitorFromWindow
GetMonitorInfo
SHCreateStreamOnFileEx
SHCreateItemFromParsingName
IShellItem
ISequentialStream
SHLoadIndirectString
IAppxFactory
AppxFactory
IAppxManifestReader
IAppxManifestApplicationsEnumerator
IAppxManifestApplication
IAppxManifestProperties
IShellLinkW
ShellLink
IPersistFile
CoTaskMemFree
IUnknown
CoAllowSetForegroundWindow
SHCreateStreamOnFileEx
SHLoadIndirectString

View File

@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
// Reference : https://stackoverflow.com/questions/32122679/getting-icon-of-modern-windows-app-from-a-desktop-application
[Guid("5842a140-ff9f-4166-8f5c-62f5b7b0c781")]
[ComImport]
public class AppxFactory
{
}

View File

@@ -2,75 +2,42 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.UI.Xaml.Controls;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Storage.Packaging.Appx;
using System.Runtime.InteropServices;
using Windows.Win32.System.Com;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
public static class AppxPackageHelper
{
internal static unsafe List<IntPtr> GetAppsFromManifest(IStream* stream)
private static readonly IAppxFactory AppxFactory = (IAppxFactory)new AppxFactory();
// This function returns a list of attributes of applications
internal static IEnumerable<IAppxManifestApplication> GetAppsFromManifest(IStream stream)
{
PInvoke.CoCreateInstance(typeof(AppxFactory).GUID, null, CLSCTX.CLSCTX_INPROC_SERVER, out IAppxFactory* appxFactory).ThrowOnFailure();
using var handle = new SafeComHandle((IntPtr)appxFactory);
var reader = AppxFactory.CreateManifestReader(stream);
var manifestApps = reader.GetApplications();
IAppxManifestReader* reader = null;
IAppxManifestApplicationsEnumerator* manifestApps = null;
var result = new List<IntPtr>();
appxFactory->CreateManifestReader(stream, &reader);
using var readerHandle = new SafeComHandle((IntPtr)reader);
reader->GetApplications(&manifestApps);
using var manifestAppsHandle = new SafeComHandle((IntPtr)manifestApps);
while (true)
while (manifestApps.GetHasCurrent())
{
manifestApps->GetHasCurrent(out var hasCurrent);
if (hasCurrent == false)
var manifestApp = manifestApps.GetCurrent();
var hr = manifestApp.GetStringValue("AppListEntry", out var appListEntry);
_ = CheckHRAndReturnOrThrow(hr, appListEntry);
if (appListEntry != "none")
{
break;
yield return manifestApp;
}
IAppxManifestApplication* manifestApp = null;
manifestApps.MoveNext();
}
}
try
{
manifestApps->GetCurrent(&manifestApp).ThrowOnFailure();
var hr = manifestApp->GetStringValue("AppListEntry", out var appListEntryPtr);
var appListEntry = ComFreeHelper.GetStringAndFree(hr, appListEntryPtr);
if (appListEntry != "none")
{
result.Add((IntPtr)manifestApp);
}
else if (manifestApp != null)
{
manifestApp->Release();
}
}
catch (Exception ex)
{
if (manifestApp != null)
{
manifestApp->Release();
}
Logger.LogError($"Failed to get current application from manifest: {ex.Message}");
}
manifestApps->MoveNext(out var hasNext);
if (hasNext == false)
{
break;
}
internal static T CheckHRAndReturnOrThrow<T>(HRESULT hr, T result)
{
if (hr != HRESULT.S_OK)
{
Marshal.ThrowExceptionForHR((int)hr);
}
return result;

View File

@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
// Reference : https://github.com/MicrosoftEdge/edge-launcher/blob/108e63df0b4cb5cd9d5e45aa7a264690851ec51d/MIcrosoftEdgeLauncherCsharp/Program.cs
[Flags]
public enum ActivateOptions
{
None = 0x00000000,
DesignMode = 0x00000001,
NoErrorUI = 0x00000002,
NoSplashScreen = 0x00000004,
}
// ApplicationActivationManager
[ComImport]
[Guid("2e941141-7f97-4756-ba1d-9decde894a3d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IApplicationActivationManager
{
IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId);
IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId);
IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId);
}
// Application Activation Manager Class
[ComImport]
[Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")]
public class ApplicationActivationManager : IApplicationActivationManager
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)/*, PreserveSig*/]
public extern IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public extern IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public extern IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId);
}

View File

@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using Windows.Win32.System.Com;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
[Guid("BEB94909-E451-438B-B5A7-D79E767B75D8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxFactory
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Implements COM Interface")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Implements COM Interface")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
void _VtblGap0_2(); // skip 2 methods
internal IAppxManifestReader CreateManifestReader(IStream inputStream);
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
[Guid("5DA89BF4-3773-46BE-B650-7E744863B7E8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxManifestApplication
{
[PreserveSig]
HRESULT GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
[PreserveSig]
HRESULT GetAppUserModelId([MarshalAs(UnmanagedType.LPWStr)] out string value);
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
[Guid("9EB8A55A-F04B-4D0D-808D-686185D4847A")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxManifestApplicationsEnumerator
{
IAppxManifestApplication GetCurrent();
bool GetHasCurrent();
bool MoveNext();
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
[Guid("03FAF64D-F26F-4B2C-AAF7-8FE7789B8BCA")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxManifestProperties
{
[PreserveSig]
HRESULT GetBoolValue([MarshalAs(UnmanagedType.LPWStr)] string name, out bool value);
[PreserveSig]
HRESULT GetStringValue([MarshalAs(UnmanagedType.LPWStr)] string name, [MarshalAs(UnmanagedType.LPWStr)] out string value);
}

View File

@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
[Guid("4E1BD148-55A0-4480-A3D1-15544710637C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxManifestReader
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Implements COM Interface")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Implements COM Interface")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
void _VtblGap0_1(); // skip 1 method
IAppxManifestProperties GetProperties();
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Implements COM Interface")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Implements COM Interface")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
void _VtblGap1_5(); // skip 5 methods
IAppxManifestApplicationsEnumerator GetApplications();
}

View File

@@ -5,7 +5,6 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
@@ -17,7 +16,7 @@ namespace Microsoft.CmdPal.Ext.Apps.Programs;
/// <summary>
/// Provides access to NTFS reparse points in .Net.
/// </summary>
public static partial class ReparsePoint
public static class ReparsePoint
{
#pragma warning disable SA1310 // Field names should not contain underscore
@@ -37,7 +36,7 @@ public static partial class ReparsePoint
#pragma warning restore SA1310 // Field names should not contain underscore
[Flags]
internal enum FileAccessType : uint
private enum FileAccessType : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
@@ -101,7 +100,7 @@ public static partial class ReparsePoint
}
[Flags]
internal enum FileShareType : uint
private enum FileShareType : uint
{
None = 0x00000000,
Read = 0x00000001,
@@ -109,7 +108,7 @@ public static partial class ReparsePoint
Delete = 0x00000004,
}
internal enum CreationDisposition : uint
private enum CreationDisposition : uint
{
New = 1,
CreateAlways = 2,
@@ -119,7 +118,7 @@ public static partial class ReparsePoint
}
[Flags]
internal enum FileAttributes : uint
private enum FileAttributes : uint
{
Readonly = 0x00000001,
Hidden = 0x00000002,
@@ -196,9 +195,8 @@ public static partial class ReparsePoint
public AppExecutionAliasReparseTagBufferLayoutVersion Version;
}
[LibraryImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool DeviceIoControl(
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr inBuffer,
@@ -208,8 +206,8 @@ public static partial class ReparsePoint
out int pBytesReturned,
IntPtr lpOverlapped);
[LibraryImport("kernel32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
internal static partial int CreateFile(
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreateFile(
string lpFileName,
FileAccessType dwDesiredAccess,
FileShareType dwShareMode,
@@ -286,18 +284,15 @@ public static partial class ReparsePoint
ThrowLastWin32Error("Unable to get information about reparse point.");
}
unsafe
AppExecutionAliasReparseTagHeader aliasReparseHeader = Marshal.PtrToStructure<AppExecutionAliasReparseTagHeader>(outBuffer);
if (aliasReparseHeader.ReparseTag == IO_REPARSE_TAG_APPEXECLINK)
{
var aliasReparseHeader = Unsafe.Read<AppExecutionAliasReparseTagHeader>((void*)outBuffer);
var metadata = AppExecutionAliasMetadata.FromPersistedRepresentationIntPtr(
outBuffer,
aliasReparseHeader.Version);
if (aliasReparseHeader.ReparseTag == IO_REPARSE_TAG_APPEXECLINK)
{
var metadata = AppExecutionAliasMetadata.FromPersistedRepresentationIntPtr(
outBuffer,
aliasReparseHeader.Version);
return metadata.ExePath;
}
return metadata.ExePath;
}
return null;
@@ -324,65 +319,61 @@ public static partial class ReparsePoint
public static AppExecutionAliasMetadata FromPersistedRepresentationIntPtr(IntPtr reparseDataBufferPtr, AppExecutionAliasReparseTagBufferLayoutVersion version)
{
unsafe
var dataOffset = Marshal.SizeOf<AppExecutionAliasReparseTagHeader>();
var dataBufferPtr = reparseDataBufferPtr + dataOffset;
string? packageFullName = null;
string? packageFamilyName = null;
string? aumid = null;
string? exePath = null;
VerifyVersion(version);
switch (version)
{
var dataOffset = Unsafe.SizeOf<AppExecutionAliasReparseTagHeader>();
case AppExecutionAliasReparseTagBufferLayoutVersion.Initial:
packageFullName = Marshal.PtrToStringUni(dataBufferPtr);
if (packageFullName is not null)
{
dataBufferPtr += Encoding.Unicode.GetByteCount(packageFullName) + Encoding.Unicode.GetByteCount("\0");
aumid = Marshal.PtrToStringUni(dataBufferPtr);
var dataBufferPtr = reparseDataBufferPtr + dataOffset;
string? packageFullName = null;
string? packageFamilyName = null;
string? aumid = null;
string? exePath = null;
VerifyVersion(version);
switch (version)
{
case AppExecutionAliasReparseTagBufferLayoutVersion.Initial:
packageFullName = Marshal.PtrToStringUni(dataBufferPtr);
if (packageFullName is not null)
if (aumid is not null)
{
dataBufferPtr += Encoding.Unicode.GetByteCount(packageFullName) + Encoding.Unicode.GetByteCount("\0");
aumid = Marshal.PtrToStringUni(dataBufferPtr);
if (aumid is not null)
{
dataBufferPtr += Encoding.Unicode.GetByteCount(aumid) + Encoding.Unicode.GetByteCount("\0");
exePath = Marshal.PtrToStringUni(dataBufferPtr);
}
dataBufferPtr += Encoding.Unicode.GetByteCount(aumid) + Encoding.Unicode.GetByteCount("\0");
exePath = Marshal.PtrToStringUni(dataBufferPtr);
}
}
break;
break;
case AppExecutionAliasReparseTagBufferLayoutVersion.PackageFamilyName:
case AppExecutionAliasReparseTagBufferLayoutVersion.MultiAppTypeSupport:
packageFamilyName = Marshal.PtrToStringUni(dataBufferPtr);
case AppExecutionAliasReparseTagBufferLayoutVersion.PackageFamilyName:
case AppExecutionAliasReparseTagBufferLayoutVersion.MultiAppTypeSupport:
packageFamilyName = Marshal.PtrToStringUni(dataBufferPtr);
if (packageFamilyName is not null)
if (packageFamilyName is not null)
{
dataBufferPtr += Encoding.Unicode.GetByteCount(packageFamilyName) + Encoding.Unicode.GetByteCount("\0");
aumid = Marshal.PtrToStringUni(dataBufferPtr);
if (aumid is not null)
{
dataBufferPtr += Encoding.Unicode.GetByteCount(packageFamilyName) + Encoding.Unicode.GetByteCount("\0");
aumid = Marshal.PtrToStringUni(dataBufferPtr);
dataBufferPtr += Encoding.Unicode.GetByteCount(aumid) + Encoding.Unicode.GetByteCount("\0");
if (aumid is not null)
{
dataBufferPtr += Encoding.Unicode.GetByteCount(aumid) + Encoding.Unicode.GetByteCount("\0");
exePath = Marshal.PtrToStringUni(dataBufferPtr);
}
exePath = Marshal.PtrToStringUni(dataBufferPtr);
}
}
break;
}
return new AppExecutionAliasMetadata
{
PackageFullName = packageFullName ?? string.Empty,
PackageFamilyName = packageFamilyName ?? string.Empty,
Aumid = aumid ?? string.Empty,
ExePath = exePath ?? string.Empty,
};
break;
}
return new AppExecutionAliasMetadata
{
PackageFullName = packageFullName ?? string.Empty,
PackageFamilyName = packageFamilyName ?? string.Empty,
Aumid = aumid ?? string.Empty,
ExePath = exePath ?? string.Empty,
};
}
private static void VerifyVersion(AppExecutionAliasReparseTagBufferLayoutVersion version)

View File

@@ -3,19 +3,17 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Storage.Packaging.Appx;
using Windows.Win32.System.Com;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
@@ -57,7 +55,7 @@ public partial class UWP
FamilyName = package.FamilyName;
}
public unsafe void InitializeAppInfo(string installedLocation)
public void InitializeAppInfo(string installedLocation)
{
Location = installedLocation;
LocationLocalized = ShellLocalization.Instance.GetLocalizedPath(installedLocation);
@@ -67,31 +65,26 @@ public partial class UWP
InitPackageVersion(namespaces);
const uint noAttribute = 0x80;
const uint STGMREAD = 0x00000000;
try
{
IStream* stream = null;
PInvoke.SHCreateStreamOnFileEx(path, STGMREAD, noAttribute, false, null, &stream).ThrowOnFailure();
using var streamHandle = new SafeComHandle((IntPtr)stream);
Apps = AppxPackageHelper.GetAppsFromManifest(stream).Select(appInManifest =>
{
using var appHandle = new SafeComHandle(appInManifest);
return new UWPApplication((IAppxManifestApplication*)appInManifest, this);
}).Where(a =>
var access = (uint)STGM.READ;
var hResult = PInvoke.SHCreateStreamOnFileEx(path, access, noAttribute, false, null, out IStream stream);
// S_OK
if (hResult == 0)
{
Apps = AppxPackageHelper.GetAppsFromManifest(stream).Select(appInManifest => new UWPApplication(appInManifest, this)).Where(a =>
{
var valid =
!string.IsNullOrEmpty(a.UserModelId) &&
!string.IsNullOrEmpty(a.DisplayName) &&
a.AppListEntry != "none";
!string.IsNullOrEmpty(a.UserModelId) &&
!string.IsNullOrEmpty(a.DisplayName) &&
a.AppListEntry != "none";
return valid;
}).ToList();
}
catch (Exception ex)
else
{
Apps = Array.Empty<UWPApplication>();
Logger.LogError($"Failed to initialize UWP app info for {Name} ({FullName}): {ex.Message}");
return;
}
}
@@ -130,36 +123,35 @@ public partial class UWP
{
var windows10 = new Version(10, 0);
var support = Environment.OSVersion.Version.Major >= windows10.Major;
if (support)
{
var applications = CurrentUserPackages().AsParallel().SelectMany(p =>
{
UWP u;
try
{
u = new UWP(p);
u.InitializeAppInfo(p.InstalledLocation);
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
return Array.Empty<UWPApplication>();
}
if (!support)
return u.Apps;
});
var updatedListWithoutDisabledApps = applications
.Where(t1 => AllAppsSettings.Instance.DisabledProgramSources.All(x => x.UniqueIdentifier != t1.UniqueIdentifier))
.Select(x => x);
return updatedListWithoutDisabledApps.ToArray();
}
else
{
return Array.Empty<UWPApplication>();
}
var appsBag = new ConcurrentBag<UWPApplication>();
Parallel.ForEach(CurrentUserPackages(), p =>
{
try
{
var u = new UWP(p);
u.InitializeAppInfo(p.InstalledLocation);
foreach (var app in u.Apps)
{
if (AllAppsSettings.Instance.DisabledProgramSources.All(x => x.UniqueIdentifier != app.UniqueIdentifier))
{
appsBag.Add(app);
}
}
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
}
});
return appsBag.ToArray();
}
private static IEnumerable<IPackage> CurrentUserPackages()

View File

@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using ManagedCommon;
@@ -14,9 +13,7 @@ using Microsoft.CmdPal.Ext.Apps.Commands;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Storage.Packaging.Appx;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
using PackageVersion = Microsoft.CmdPal.Ext.Apps.Programs.UWP.PackageVersion;
using Theme = Microsoft.CmdPal.Ext.Apps.Utils.Theme;
@@ -100,27 +97,27 @@ public class UWPApplication : IProgram
return commands;
}
internal unsafe UWPApplication(IAppxManifestApplication* manifestApp, UWP package)
public UWPApplication(IAppxManifestApplication manifestApp, UWP package)
{
ArgumentNullException.ThrowIfNull(manifestApp);
var hr = manifestApp->GetAppUserModelId(out var tmpUserModelIdPtr);
UserModelId = ComFreeHelper.GetStringAndFree(hr, tmpUserModelIdPtr);
var hr = manifestApp.GetAppUserModelId(out var tmpUserModelId);
UserModelId = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, tmpUserModelId);
manifestApp->GetAppUserModelId(out var tmpUniqueIdentifierPtr);
UniqueIdentifier = ComFreeHelper.GetStringAndFree(hr, tmpUniqueIdentifierPtr);
hr = manifestApp.GetAppUserModelId(out var tmpUniqueIdentifier);
UniqueIdentifier = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, tmpUniqueIdentifier);
manifestApp->GetStringValue("DisplayName", out var tmpDisplayNamePtr);
DisplayName = ComFreeHelper.GetStringAndFree(hr, tmpDisplayNamePtr);
hr = manifestApp.GetStringValue("DisplayName", out var tmpDisplayName);
DisplayName = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, tmpDisplayName);
manifestApp->GetStringValue("Description", out var tmpDescriptionPtr);
Description = ComFreeHelper.GetStringAndFree(hr, tmpDescriptionPtr);
hr = manifestApp.GetStringValue("Description", out var tmpDescription);
Description = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, tmpDescription);
manifestApp->GetStringValue("BackgroundColor", out var tmpBackgroundColorPtr);
BackgroundColor = ComFreeHelper.GetStringAndFree(hr, tmpBackgroundColorPtr);
hr = manifestApp.GetStringValue("BackgroundColor", out var tmpBackgroundColor);
BackgroundColor = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, tmpBackgroundColor);
manifestApp->GetStringValue("EntryPoint", out var tmpEntryPointPtr);
EntryPoint = ComFreeHelper.GetStringAndFree(hr, tmpEntryPointPtr);
hr = manifestApp.GetStringValue("EntryPoint", out var tmpEntryPoint);
EntryPoint = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, tmpEntryPoint);
Package = package ?? throw new ArgumentNullException(nameof(package));
@@ -169,7 +166,7 @@ public class UWPApplication : IProgram
return false;
}
internal unsafe string ResourceFromPri(string packageFullName, string resourceReference)
internal string ResourceFromPri(string packageFullName, string resourceReference)
{
const string prefix = "ms-resource:";
@@ -203,8 +200,30 @@ public class UWPApplication : IProgram
parsedFallback = prefix + "///" + key;
}
if (string.IsNullOrEmpty(parsedFallback))
var outBuffer = new StringBuilder(128);
var source = $"@{{{packageFullName}? {parsed}}}";
var capacity = (uint)outBuffer.Capacity;
var hResult = SHLoadIndirectString(source, outBuffer, capacity, IntPtr.Zero);
if (hResult != HRESULT.S_OK)
{
if (!string.IsNullOrEmpty(parsedFallback))
{
var sourceFallback = $"@{{{packageFullName}? {parsedFallback}}}";
hResult = SHLoadIndirectString(sourceFallback, outBuffer, capacity, IntPtr.Zero);
if (hResult == HRESULT.S_OK)
{
var loaded = outBuffer.ToString();
if (!string.IsNullOrEmpty(loaded))
{
return loaded;
}
else
{
return string.Empty;
}
}
}
// https://github.com/Wox-launcher/Wox/issues/964
// known hresult 2147942522:
// 'Microsoft Corporation' violates pattern constraint of '\bms-resource:.{1,256}'.
@@ -213,40 +232,17 @@ public class UWPApplication : IProgram
// Microsoft.BingFoodAndDrink_3.0.4.336_x64__8wekyb3d8bbwe: ms-resource:AppDescription
return string.Empty;
}
var capacity = 1024U;
PWSTR outBuffer = new PWSTR((char*)(void*)Marshal.AllocHGlobal((int)capacity * sizeof(char)));
var source = $"@{{{packageFullName}? {parsed}}}";
void* reserved = null;
try
else
{
PInvoke.SHLoadIndirectString(source, outBuffer, capacity, ref reserved).ThrowOnFailure();
var loaded = outBuffer.ToString();
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
}
catch (Exception)
{
try
if (!string.IsNullOrEmpty(loaded))
{
var sourceFallback = $"@{{{packageFullName}?{parsedFallback}}}";
PInvoke.SHLoadIndirectString(sourceFallback, outBuffer, capacity, ref reserved).ThrowOnFailure();
var loaded = outBuffer.ToString();
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
return loaded;
}
catch (Exception)
else
{
// ProgramLogger.Exception($"Unable to load resource {resourceReference} from {packageFullName}", new InvalidOperationException(), GetType(), packageFullName);
return string.Empty;
}
finally
{
}
}
finally
{
Marshal.FreeHGlobal((IntPtr)outBuffer.Value);
}
}
else
@@ -262,12 +258,13 @@ public class UWPApplication : IProgram
{ PackageVersion.Windows8, "SmallLogo" },
};
internal unsafe string LogoUriFromManifest(IAppxManifestApplication* app)
internal string LogoUriFromManifest(IAppxManifestApplication app)
{
if (_logoKeyFromVersion.TryGetValue(Package.Version, out var key))
{
var hr = app->GetStringValue(key, out var logoUriFromAppPtr);
return ComFreeHelper.GetStringAndFree(hr, logoUriFromAppPtr);
var hr = app.GetStringValue(key, out var logoUriFromApp);
_ = AppxPackageHelper.CheckHRAndReturnOrThrow(hr, logoUriFromApp);
return logoUriFromApp;
}
else
{
@@ -352,7 +349,7 @@ public class UWPApplication : IProgram
var prefix = path.Substring(0, end);
var paths = new List<string> { };
const int appIconSize = 36;
var targetSizes = new List<int> { 16, 24, 30, 36, 44, 60, 72, 96, 128, 180, 256 };
var targetSizes = new List<int> { 16, 24, 30, 36, 44, 60, 72, 96, 128, 180, 256 }.AsParallel();
var pathFactorPairs = new Dictionary<string, int>();
foreach (var factor in targetSizes)

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Diagnostics;
@@ -842,69 +841,18 @@ public class Win32Program : IProgram
var disabledProgramsList = settings.DisabledProgramSources;
// Get all paths but exclude all normal .Executables
var pathBag = new ConcurrentBag<string>();
paths.UnionWith(sources
.AsParallel()
.SelectMany(source => source.IsEnabled ? source.GetPaths() : Enumerable.Empty<string>())
.Where(programPath => disabledProgramsList.All(x => x.UniqueIdentifier != programPath))
.Where(path => !ExecutableApplicationExtensions.Contains(Extension(path))));
runCommandPaths.UnionWith(runCommandSources
.AsParallel()
.SelectMany(source => source.IsEnabled ? source.GetPaths() : Enumerable.Empty<string>())
.Where(programPath => disabledProgramsList.All(x => x.UniqueIdentifier != programPath)));
Parallel.ForEach(sources, source =>
{
if (!source.IsEnabled)
{
return;
}
foreach (var path in source.GetPaths())
{
if (disabledProgramsList.All(x => x.UniqueIdentifier != path) &&
!ExecutableApplicationExtensions.Contains(Extension(path)))
{
pathBag.Add(path);
}
}
});
paths.UnionWith(pathBag);
var runCommandPathBag = new ConcurrentBag<string>();
Parallel.ForEach(runCommandSources, source =>
{
if (!source.IsEnabled)
{
return;
}
foreach (var path in source.GetPaths())
{
if (disabledProgramsList.All(x => x.UniqueIdentifier != path))
{
runCommandPathBag.Add(path);
}
}
});
runCommandPaths.UnionWith(runCommandPathBag);
var programsList = new ConcurrentBag<Win32Program>();
Parallel.ForEach(paths, source =>
{
var program = GetProgramFromPath(source);
if (program != null)
{
programsList.Add(program);
}
});
var runCommandProgramsList = new ConcurrentBag<Win32Program>();
Parallel.ForEach(runCommandPaths, source =>
{
var program = GetRunCommandProgramFromPath(source);
if (program != null)
{
runCommandProgramsList.Add(program);
}
});
var programs = programsList.ToList();
var runCommandPrograms = runCommandProgramsList.ToList();
var programs = paths.AsParallel().Select(source => GetProgramFromPath(source));
var runCommandPrograms = runCommandPaths.AsParallel().Select(source => GetRunCommandProgramFromPath(source));
return DeduplicatePrograms(programs.Concat(runCommandPrograms).Where(program => program?.Valid == true));
}

View File

@@ -69,6 +69,11 @@ public class ListRepository<T> : IRepository<T>, IEnumerable<T>
}
}
public ParallelQuery<T> AsParallel()
{
return _items.Values.AsParallel();
}
public bool Contains(T item)
{
if (item is not null)

View File

@@ -6,8 +6,8 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Abstractions;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Programs;
@@ -15,9 +15,11 @@ using Win32Program = Microsoft.CmdPal.Ext.Apps.Programs.Win32Program;
namespace Microsoft.CmdPal.Ext.Apps.Storage;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
internal sealed partial class Win32ProgramRepository : ListRepository<Programs.Win32Program>, IProgramRepository
{
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
private const string LnkExtension = ".lnk";
private const string UrlExtension = ".url";

View File

@@ -1,35 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
namespace Microsoft.CmdPal.Ext.Apps.Utils;
public static class ComFreeHelper
{
internal static unsafe string GetStringAndFree(HRESULT hr, PWSTR ptr)
{
hr.ThrowOnFailure();
try
{
return ptr.ToString();
}
finally
{
PInvoke.CoTaskMemFree(ptr);
}
}
public static unsafe void ComObjectRelease<T>(T* comPtr)
where T : unmanaged
{
if (comPtr != null)
{
((IUnknown*)comPtr)->Release();
}
}
}

View File

@@ -0,0 +1,157 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.CmdPal.Ext.Apps.Utils;
[SuppressMessage("Interoperability", "CA1401:P/Invokes should not be visible", Justification = "We want plugins to share this NativeMethods class, instead of each one creating its own.")]
public sealed class Native
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, int cchOutBuf, nint ppvReserved);
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, nint pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem);
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern HRESULT SHCreateStreamOnFileEx(string fileName, STGM grfMode, uint attributes, bool create, System.Runtime.InteropServices.ComTypes.IStream reserved, out System.Runtime.InteropServices.ComTypes.IStream stream);
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern HRESULT SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, uint cchOutBuf, nint ppvReserved);
public enum HRESULT : uint
{
/// <summary>
/// Operation successful.
/// </summary>
S_OK = 0x00000000,
/// <summary>
/// Operation successful. (negative condition/no operation)
/// </summary>
S_FALSE = 0x00000001,
/// <summary>
/// Not implemented.
/// </summary>
E_NOTIMPL = 0x80004001,
/// <summary>
/// No such interface supported.
/// </summary>
E_NOINTERFACE = 0x80004002,
/// <summary>
/// Pointer that is not valid.
/// </summary>
E_POINTER = 0x80004003,
/// <summary>
/// Operation aborted.
/// </summary>
E_ABORT = 0x80004004,
/// <summary>
/// Unspecified failure.
/// </summary>
E_FAIL = 0x80004005,
/// <summary>
/// Unexpected failure.
/// </summary>
E_UNEXPECTED = 0x8000FFFF,
/// <summary>
/// General access denied error.
/// </summary>
E_ACCESSDENIED = 0x80070005,
/// <summary>
/// Handle that is not valid.
/// </summary>
E_HANDLE = 0x80070006,
/// <summary>
/// Failed to allocate necessary memory.
/// </summary>
E_OUTOFMEMORY = 0x8007000E,
/// <summary>
/// One or more arguments are not valid.
/// </summary>
E_INVALIDARG = 0x80070057,
/// <summary>
/// The operation was canceled by the user. (Error source 7 means Win32.)
/// </summary>
/// <SeeAlso href="https://learn.microsoft.com/windows/win32/debug/system-error-codes--1000-1299-"/>
/// <SeeAlso href="https://en.wikipedia.org/wiki/HRESULT"/>
E_CANCELLED = 0x800704C7,
}
public static class ShellItemTypeConstants
{
/// <summary>
/// Guid for type IShellItem.
/// </summary>
public static readonly Guid ShellItemGuid = new("43826d1e-e718-42ee-bc55-a1e261c37bfe");
/// <summary>
/// Guid for type IShellItem2.
/// </summary>
public static readonly Guid ShellItem2Guid = new("7E9FB0D3-919F-4307-AB2E-9B1860310C93");
}
/// <summary>
/// The following are ShellItem DisplayName types.
/// </summary>
[Flags]
public enum SIGDN : uint
{
NORMALDISPLAY = 0,
PARENTRELATIVEPARSING = 0x80018001,
PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
DESKTOPABSOLUTEPARSING = 0x80028000,
PARENTRELATIVEEDITING = 0x80031001,
DESKTOPABSOLUTEEDITING = 0x8004c000,
FILESYSPATH = 0x80058000,
URL = 0x80068000,
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
public interface IShellItem
{
void BindToHandler(
nint pbc,
[MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
out nint ppv);
void GetParent(out IShellItem ppsi);
void GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
void Compare(IShellItem psi, uint hint, out int piOrder);
}
/// <summary>
/// <see href="https://learn.microsoft.com/windows/win32/stg/stgm-constants">see all STGM values</see>
/// </summary>
[Flags]
public enum STGM : long
{
READ = 0x00000000L,
WRITE = 0x00000001L,
READWRITE = 0x00000002L,
CREATE = 0x00001000L,
}
}

View File

@@ -1,30 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.Apps.Utils;
public partial class SafeComHandle : SafeHandle
{
public SafeComHandle()
: base(IntPtr.Zero, ownsHandle: true)
{
}
public SafeComHandle(IntPtr handle)
: base(IntPtr.Zero, ownsHandle: true)
{
SetHandle(handle);
}
public override bool IsInvalid => handle == IntPtr.Zero;
protected override bool ReleaseHandle()
{
var count = Marshal.Release(handle);
return true;
}
}

View File

@@ -3,17 +3,124 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using ManagedCommon;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
using Windows.Win32.UI.Shell;
namespace Microsoft.CmdPal.Ext.Apps.Utils;
public class ShellLinkHelper : IShellLinkHelper
{
[Flags]
private enum SLGP_FLAGS
{
SLGP_SHORTPATH = 0x1,
SLGP_UNCPRIORITY = 0x2,
SLGP_RAWPATH = 0x4,
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching COM")]
private struct WIN32_FIND_DATAW
{
public uint dwFileAttributes;
public long ftCreationTime;
public long ftLastAccessTime;
public long ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
[Flags]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Implements COM Interface")]
public enum SLR_FLAGS
{
SLR_NO_UI = 0x1,
SLR_ANY_MATCH = 0x2,
SLR_UPDATE = 0x4,
SLR_NOUPDATE = 0x8,
SLR_NOSEARCH = 0x10,
SLR_NOTRACK = 0x20,
SLR_NOLINKINFO = 0x40,
SLR_INVOKE_MSI = 0x80,
}
// Reference : http://www.pinvoke.net/default.aspx/Interfaces.IShellLinkW
// The IShellLink interface allows Shell links to be created, modified, and resolved
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
private interface IShellLinkW
{
/// <summary>Retrieves the path and file name of a Shell link object</summary>
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, ref WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
/// <summary>Retrieves the list of item identifiers for a Shell link object</summary>
void GetIDList(out nint ppidl);
/// <summary>Sets the pointer to an item identifier list (PIDL) for a Shell link object.</summary>
void SetIDList(nint pidl);
/// <summary>Retrieves the description string for a Shell link object</summary>
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
/// <summary>Sets the description for a Shell link object. The description can be any application-defined string</summary>
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
/// <summary>Retrieves the name of the working directory for a Shell link object</summary>
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
/// <summary>Sets the name of the working directory for a Shell link object</summary>
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
/// <summary>Retrieves the command-line arguments associated with a Shell link object</summary>
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
/// <summary>Sets the command-line arguments for a Shell link object</summary>
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
/// <summary>Retrieves the hot key for a Shell link object</summary>
void GetHotkey(out short pwHotkey);
/// <summary>Sets a hot key for a Shell link object</summary>
void SetHotkey(short wHotkey);
/// <summary>Retrieves the show command for a Shell link object</summary>
void GetShowCmd(out int piShowCmd);
/// <summary>Sets the show command for a Shell link object. The show command sets the initial show state of the window.</summary>
void SetShowCmd(int iShowCmd);
/// <summary>Retrieves the location (path and index) of the icon for a Shell link object</summary>
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
/// <summary>Sets the location (path and index) of the icon for a Shell link object</summary>
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
/// <summary>Sets the relative path to the Shell link object</summary>
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
/// <summary>Attempts to find the target of a Shell link, even if it has been moved or renamed</summary>
void Resolve(ref nint hwnd, SLR_FLAGS fFlags);
/// <summary>Sets the path and file name of a Shell link object</summary>
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
[ComImport]
[Guid("00021401-0000-0000-C000-000000000046")]
private class ShellLink
{
}
// Contains the description of the app
public string Description { get; set; } = string.Empty;
@@ -23,63 +130,60 @@ public class ShellLinkHelper : IShellLinkHelper
public bool HasArguments { get; set; }
// Retrieve the target path using Shell Link
public unsafe string RetrieveTargetPath(string path)
public string RetrieveTargetPath(string path)
{
var target = string.Empty;
const int MAX_PATH = 260;
IShellLinkW* link = null;
var link = new ShellLink();
const int STGM_READ = 0;
PInvoke.CoCreateInstance(typeof(ShellLink).GUID, null, CLSCTX.CLSCTX_INPROC_SERVER, out link).ThrowOnFailure();
using var linkHandle = new SafeComHandle((IntPtr)link);
const int STGMREAD = 0;
IPersistFile* persistFile = null;
Guid iid = typeof(IPersistFile).GUID;
((IUnknown*)link)->QueryInterface(&iid, (void**)&persistFile);
if (persistFile != null)
try
{
using var persistFileHandle = new SafeComHandle((IntPtr)persistFile);
try
{
persistFile->Load(path, STGMREAD);
}
catch (System.IO.FileNotFoundException)
{
// Log.Exception($"Failed to load {path}, {e.Message}", e, GetType());
return string.Empty;
}
((IPersistFile)link).Load(path, STGM_READ);
}
catch (System.IO.FileNotFoundException ex)
{
Logger.LogError(ex.Message);
return string.Empty;
}
var hwnd = HWND.Null;
const uint SLR_NO_UI = 0x1;
link->Resolve(hwnd, SLR_NO_UI);
var hwnd = default(nint);
((IShellLinkW)link).Resolve(ref hwnd, 0);
var buffer = stackalloc char[MAX_PATH];
const int MAX_PATH = 260;
var buffer = new StringBuilder(MAX_PATH);
var hr = link->GetPath((PWSTR)buffer, MAX_PATH, null, 0x1);
target = hr.Succeeded ? new string(buffer) : string.Empty;
var data = default(WIN32_FIND_DATAW);
((IShellLinkW)link).GetPath(buffer, buffer.Capacity, ref data, SLGP_FLAGS.SLGP_SHORTPATH);
var target = buffer.ToString();
// To set the app description
if (!string.IsNullOrEmpty(target))
{
var descBuffer = stackalloc char[MAX_PATH];
var desHr = link->GetDescription(descBuffer, MAX_PATH);
Description = desHr.Succeeded ? new string(descBuffer) : string.Empty;
buffer = new StringBuilder(MAX_PATH);
try
{
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
Description = buffer.ToString();
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
Description = string.Empty;
}
var argsBuffer = stackalloc char[MAX_PATH];
var argHr = link->GetArguments(argsBuffer, MAX_PATH);
Arguments = argHr.Succeeded ? new string(argsBuffer) : string.Empty;
var argumentBuffer = new StringBuilder(MAX_PATH);
((IShellLinkW)link).GetArguments(argumentBuffer, argumentBuffer.Capacity);
Arguments = argumentBuffer.ToString();
// Set variable to true if the program takes in any arguments
if (Arguments.Length != 0)
if (argumentBuffer.Length != 0)
{
HasArguments = true;
}
}
// To release unmanaged memory
Marshal.ReleaseComObject(link);
return target;
}
}

View File

@@ -4,8 +4,7 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using Windows.Win32;
using Windows.Win32.UI.Shell;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
namespace Microsoft.CmdPal.Ext.Apps.Utils;
@@ -24,7 +23,7 @@ public class ShellLocalization
/// </summary>
/// <param name="path">Path to the shell item (e. g. shortcut 'File Explorer.lnk').</param>
/// <returns>The localized name as string or <see cref="string.Empty"/>.</returns>
public unsafe string GetLocalizedName(string path)
public string GetLocalizedName(string path)
{
var lowerInvariantPath = path.ToLowerInvariant();
@@ -34,29 +33,18 @@ public class ShellLocalization
return value;
}
void* shellItemPtrVoid = null;
try
{
var retCode = PInvoke.SHCreateItemFromParsingName(path, null, typeof(IShellItem).GUID, out shellItemPtrVoid).ThrowOnFailure();
using var shellItemHandle = new SafeComHandle((IntPtr)shellItemPtrVoid);
IShellItem* shellItemPtr = (IShellItem*)shellItemPtrVoid;
var hr = shellItemPtr->GetDisplayName(SIGDN.SIGDN_NORMALDISPLAY, out var filenamePtr);
var filename = ComFreeHelper.GetStringAndFree(hr, filenamePtr);
if (filename == null)
{
return string.Empty;
}
_ = _localizationCache.TryAdd(lowerInvariantPath, filename);
return filename;
}
catch (Exception)
var shellItemType = ShellItemTypeConstants.ShellItemGuid;
var retCode = SHCreateItemFromParsingName(path, nint.Zero, ref shellItemType, out var shellItem);
if (retCode != 0)
{
return string.Empty;
}
shellItem.GetDisplayName(SIGDN.NORMALDISPLAY, out var filename);
_ = _localizationCache.TryAdd(lowerInvariantPath, filename);
return filename;
}
/// <summary>

View File

@@ -35,7 +35,7 @@ public static class CalculateHelper
{
if (string.IsNullOrWhiteSpace(input))
{
return false;
throw new ArgumentNullException(paramName: nameof(input));
}
if (!RegValidExpressChar.IsMatch(input))

View File

@@ -23,9 +23,6 @@ public static partial class QueryHelper
CultureInfo inputCulture = settings.InputUseEnglishFormat ? new CultureInfo("en-us") : CultureInfo.CurrentCulture;
CultureInfo outputCulture = settings.OutputUseEnglishFormat ? new CultureInfo("en-us") : CultureInfo.CurrentCulture;
// In case the user pastes a query with a leading =
query = query.TrimStart('=');
// Happens if the user has only typed the action key so far
if (string.IsNullOrEmpty(query))
{
@@ -35,11 +32,6 @@ public static partial class QueryHelper
NumberTranslator translator = NumberTranslator.Create(inputCulture, new CultureInfo("en-US"));
var input = translator.Translate(query.Normalize(NormalizationForm.FormKC));
if (string.IsNullOrWhiteSpace(input))
{
return ErrorHandler.OnError(isFallbackSearch, query, Properties.Resources.calculator_expression_empty);
}
if (!CalculateHelper.InputValid(input))
{
return null;

View File

@@ -132,15 +132,6 @@ namespace Microsoft.CmdPal.Ext.Calc.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Please enter an expression.
/// </summary>
public static string calculator_expression_empty {
get {
return ResourceManager.GetString("calculator_expression_empty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Expression wrong or incomplete.
/// </summary>

View File

@@ -199,7 +199,4 @@
<data name="calculator_copy_binary" xml:space="preserve">
<value>Copy binary</value>
</data>
<data name="calculator_expression_empty" xml:space="preserve">
<value>Please enter an expression</value>
</data>
</root>

View File

@@ -0,0 +1,144 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.System.Helpers;
[SuppressMessage("Interoperability", "CA1401:P/Invokes should not be visible", Justification = "We want plugins to share this NativeMethods class, instead of each one creating its own.")]
public sealed class Native
{
public enum HRESULT : uint
{
/// <summary>
/// Operation successful.
/// </summary>
S_OK = 0x00000000,
/// <summary>
/// Operation successful. (negative condition/no operation)
/// </summary>
S_FALSE = 0x00000001,
/// <summary>
/// Not implemented.
/// </summary>
E_NOTIMPL = 0x80004001,
/// <summary>
/// No such interface supported.
/// </summary>
E_NOINTERFACE = 0x80004002,
/// <summary>
/// Pointer that is not valid.
/// </summary>
E_POINTER = 0x80004003,
/// <summary>
/// Operation aborted.
/// </summary>
E_ABORT = 0x80004004,
/// <summary>
/// Unspecified failure.
/// </summary>
E_FAIL = 0x80004005,
/// <summary>
/// Unexpected failure.
/// </summary>
E_UNEXPECTED = 0x8000FFFF,
/// <summary>
/// General access denied error.
/// </summary>
E_ACCESSDENIED = 0x80070005,
/// <summary>
/// Handle that is not valid.
/// </summary>
E_HANDLE = 0x80070006,
/// <summary>
/// Failed to allocate necessary memory.
/// </summary>
E_OUTOFMEMORY = 0x8007000E,
/// <summary>
/// One or more arguments are not valid.
/// </summary>
E_INVALIDARG = 0x80070057,
/// <summary>
/// The operation was canceled by the user. (Error source 7 means Win32.)
/// </summary>
/// <SeeAlso href="https://learn.microsoft.com/windows/win32/debug/system-error-codes--1000-1299-"/>
/// <SeeAlso href="https://en.wikipedia.org/wiki/HRESULT"/>
E_CANCELLED = 0x800704C7,
}
public static class ShellItemTypeConstants
{
/// <summary>
/// Guid for type IShellItem.
/// </summary>
public static readonly Guid ShellItemGuid = new("43826d1e-e718-42ee-bc55-a1e261c37bfe");
/// <summary>
/// Guid for type IShellItem2.
/// </summary>
public static readonly Guid ShellItem2Guid = new("7E9FB0D3-919F-4307-AB2E-9B1860310C93");
}
/// <summary>
/// The following are ShellItem DisplayName types.
/// </summary>
[Flags]
public enum SIGDN : uint
{
NORMALDISPLAY = 0,
PARENTRELATIVEPARSING = 0x80018001,
PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
DESKTOPABSOLUTEPARSING = 0x80028000,
PARENTRELATIVEEDITING = 0x80031001,
DESKTOPABSOLUTEEDITING = 0x8004c000,
FILESYSPATH = 0x80058000,
URL = 0x80068000,
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
public interface IShellItem
{
void BindToHandler(
nint pbc,
[MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
out nint ppv);
void GetParent(out IShellItem ppsi);
void GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
void Compare(IShellItem psi, uint hint, out int piOrder);
}
/// <summary>
/// <see href="https://learn.microsoft.com/windows/win32/stg/stgm-constants">see all STGM values</see>
/// </summary>
[Flags]
public enum STGM : long
{
READ = 0x00000000L,
WRITE = 0x00000001L,
READWRITE = 0x00000002L,
CREATE = 0x00001000L,
}
}

View File

@@ -32,11 +32,6 @@
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="NativeMethods.txt" />
<AdditionalFiles Include="NativeMethods.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />

View File

@@ -1,7 +0,0 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false,
"comInterop": {
"preserveSigMethods": [ "*" ]
}
}

View File

@@ -20,25 +20,20 @@ public class WindowsPackageManagerStandardFactory : WindowsPackageManagerFactory
protected override T CreateInstance<T>(Guid clsid, Guid iid)
{
var pUnknown = IntPtr.Zero;
unsafe
try
{
try
var hr = PInvoke.CoCreateInstance(clsid, null, CLSCTX.CLSCTX_ALL, iid, out var result);
Marshal.ThrowExceptionForHR(hr);
pUnknown = Marshal.GetIUnknownForObject(result);
return MarshalGeneric<T>.FromAbi(pUnknown);
}
finally
{
// CoCreateInstance and FromAbi both AddRef on the native object.
// Release once to prevent memory leak.
if (pUnknown != IntPtr.Zero)
{
var hr = PInvoke.CoCreateInstance(clsid, null, CLSCTX.CLSCTX_ALL, iid, out var result);
Marshal.ThrowExceptionForHR(hr);
pUnknown = new IntPtr(result);
return MarshalGeneric<T>.FromAbi(pUnknown);
}
finally
{
// CoCreateInstance and FromAbi both AddRef on the native object.
// Release once to prevent memory leak.
if (pUnknown != IntPtr.Zero)
{
Marshal.Release(pUnknown);
}
Marshal.Release(pUnknown);
}
}
}

View File

@@ -36,7 +36,6 @@ internal sealed class ContextMenuHelper
contextMenu.Add(new CommandContextItem(new KillProcessCommand(windowData))
{
RequestedShortcut = KeyChordHelpers.FromModifiers(true, false, false, false, (int)VirtualKey.Delete, 0),
IsCritical = true,
});
}

View File

@@ -4,7 +4,6 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers;
@@ -12,16 +11,18 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers;
/// Interface for accessing Virtual Desktop Manager.
/// Code used from <see href="https://learn.microsoft.com/archive/blogs/winsdk/virtual-desktop-switching-in-windows-10"./>
/// </summary>
[GeneratedComInterface]
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")]
public partial interface IVirtualDesktopManager
[System.Security.SuppressUnmanagedCodeSecurity]
internal interface IVirtualDesktopManager
{
[PreserveSig]
int IsWindowOnCurrentVirtualDesktop(IntPtr hTopLevelWindow, out int onCurrentDesktop);
int IsWindowOnCurrentVirtualDesktop([In] IntPtr hTopLevelWindow, [Out] out int onCurrentDesktop);
[PreserveSig]
int GetWindowDesktopId(IntPtr hTopLevelWindow, out Guid desktop);
int GetWindowDesktopId([In] IntPtr hTopLevelWindow, [Out] out Guid desktop);
[PreserveSig]
int MoveWindowToDesktop(IntPtr hTopLevelWindow, ref Guid desktop);
int MoveWindowToDesktop([In] IntPtr hTopLevelWindow, [MarshalAs(UnmanagedType.LPStruct)][In] Guid desktop);
}

View File

@@ -13,7 +13,7 @@ using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessage
namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers;
[SuppressMessage("Interoperability", "CA1401:P/Invokes should not be visible", Justification = "We want plugins to share this NativeMethods class, instead of each one creating its own.")]
public static partial class NativeMethods
public static class NativeMethods
{
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int EnumWindows(EnumWindowsProc callPtr, IntPtr lParam);
@@ -99,14 +99,31 @@ public static partial class NativeMethods
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetFirmwareType(ref FirmwareType FirmwareType);
[LibraryImport("ole32.dll")]
[return: MarshalAs(UnmanagedType.U4)]
public static partial uint CoCreateInstance(
ref Guid rclsid,
IntPtr pUnkOuter,
uint dwClsContext,
ref Guid riid,
out IntPtr rReturnedComObject);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
[DllImport("user32")]
public static extern void LockWorkStation();
[DllImport("Powrprof.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
public static extern uint SHEmptyRecycleBin(IntPtr hWnd, uint dwFlags);
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern HRESULT SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, uint cchOutBuf, IntPtr ppvReserved);
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern HRESULT SHCreateStreamOnFileEx(string fileName, STGM grfMode, uint attributes, bool create, System.Runtime.InteropServices.ComTypes.IStream reserved, out System.Runtime.InteropServices.ComTypes.IStream stream);
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem);
[DllImport("rpcrt4.dll")]
public static extern int UuidCreateSequential(out GUIDDATA Uuid);
}
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "These are the names used by win32.")]
@@ -144,6 +161,19 @@ public static class Win32Constants
public const int RPC_S_UUID_LOCAL_ONLY = 0x720;
}
public static class ShellItemTypeConstants
{
/// <summary>
/// Guid for type IShellItem.
/// </summary>
public static readonly Guid ShellItemGuid = new("43826d1e-e718-42ee-bc55-a1e261c37bfe");
/// <summary>
/// Guid for type IShellItem2.
/// </summary>
public static readonly Guid ShellItem2Guid = new("7E9FB0D3-919F-4307-AB2E-9B1860310C93");
}
public enum HRESULT : uint
{
/// <summary>
@@ -1094,6 +1124,26 @@ public enum ExtendedWindowStyles : uint
WS_EX_NOACTIVATE = 0x8000000,
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
public interface IShellItem
{
void BindToHandler(
IntPtr pbc,
[MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
out IntPtr ppv);
void GetParent(out IShellItem ppsi);
void GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
void Compare(IShellItem psi, uint hint, out int piOrder);
}
/// <summary>
/// The following are ShellItem DisplayName types.
/// </summary>

View File

@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using System.Text;
using Microsoft.CmdPal.Ext.WindowWalker.Properties;
@@ -49,10 +48,6 @@ public class VirtualDesktopHelper
/// </summary>
private readonly List<Guid> _availableDesktops = [];
#pragma warning disable SA1306 // Field names should begin with lower-case letter
private readonly uint CLSCTXINPROCALL = 0x17;
#pragma warning restore SA1306 // Field names should begin with lower-case letter
/// <summary>
/// Id of the current visible Desktop.
/// </summary>
@@ -60,27 +55,15 @@ public class VirtualDesktopHelper
private static readonly CompositeFormat VirtualDesktopHelperDesktop = System.Text.CompositeFormat.Parse(Properties.Resources.VirtualDesktopHelper_Desktop);
private Guid iVirtualDesktopManagerCLSID = new("aa509086-5ca9-4c25-8f95-589d3c07b48a");
private Guid iVirtualDesktopManagerIID = new("a5cd92ff-29be-454c-8d04-d82879fb3f1b");
/// <summary>
/// Initializes a new instance of the <see cref="VirtualDesktopHelper"/> class.
/// </summary>
/// <param name="desktopListUpdate">Setting to configure if the list of available desktops should update automatically or only when calling <see cref="UpdateDesktopList"/>. Per default this is set to manual update (false) to have less registry queries.</param>
public VirtualDesktopHelper(bool desktopListUpdate = false)
{
var cw = new StrategyBasedComWrappers();
try
{
var hr = NativeMethods.CoCreateInstance(ref this.iVirtualDesktopManagerCLSID, nint.Zero, CLSCTXINPROCALL, ref iVirtualDesktopManagerIID, out var virtualDesktopManagerPtr);
if (hr != 0)
{
throw new ArgumentException($"Failed to create IVirtualDesktopManager instance. HR: 0x{hr:X}");
}
_virtualDesktopManager = (IVirtualDesktopManager)cw.GetOrCreateObjectForComInstance(virtualDesktopManagerPtr, CreateObjectFlags.None);
_virtualDesktopManager = (IVirtualDesktopManager)new CVirtualDesktopManager();
}
catch (COMException ex)
{
@@ -426,7 +409,7 @@ public class VirtualDesktopHelper
/// <param name="hWindow">Handle of the top level window.</param>
/// <param name="desktopId">Guid of the target desktop.</param>
/// <returns><see langword="True"/> on success and <see langword="false"/> on failure.</returns>
public bool MoveWindowToDesktop(IntPtr hWindow, ref Guid desktopId)
public bool MoveWindowToDesktop(IntPtr hWindow, in Guid desktopId)
{
if (_virtualDesktopManager == null)
{
@@ -434,7 +417,7 @@ public class VirtualDesktopHelper
return false;
}
var hr = _virtualDesktopManager.MoveWindowToDesktop(hWindow, ref desktopId);
var hr = _virtualDesktopManager.MoveWindowToDesktop(hWindow, desktopId);
if (hr != (int)HRESULT.S_OK)
{
ExtensionHost.LogMessage(new LogMessage() { Message = "VirtualDesktopHelper.MoveWindowToDesktop() failed: An exception was thrown when moving the window ({hWindow}) to another desktop ({desktopId})." });
@@ -472,7 +455,7 @@ public class VirtualDesktopHelper
}
Guid newDesktop = _availableDesktops[windowDesktopNumber - 1];
return MoveWindowToDesktop(hWindow, ref newDesktop);
return MoveWindowToDesktop(hWindow, newDesktop);
}
/// <summary>
@@ -503,7 +486,7 @@ public class VirtualDesktopHelper
}
Guid newDesktop = _availableDesktops[windowDesktopNumber + 1];
return MoveWindowToDesktop(hWindow, ref newDesktop);
return MoveWindowToDesktop(hWindow, newDesktop);
}
/// <summary>

View File

@@ -3,12 +3,18 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
using Microsoft.CmdPal.Ext.WindowsTerminal.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.UI;
namespace Microsoft.CmdPal.Ext.WindowsTerminal.Commands;
@@ -62,23 +68,7 @@ internal sealed partial class LaunchProfileAsAdminCommand : InvokableCommand
private void Launch(string id, string profile)
{
ComWrappers cw = new StrategyBasedComWrappers();
var hr = NativeHelpers.CoCreateInstance(ref NativeHelpers.ApplicationActivationManagerCLSID, IntPtr.Zero, NativeHelpers.CLSCTXINPROCALL, ref NativeHelpers.ApplicationActivationManagerIID, out var appManagerPtr);
if (hr != 0)
{
throw new ArgumentException($"Failed to create IApplicationActivationManager instance. HR: 0x{hr:X}");
}
var appManager = (IApplicationActivationManager)cw.GetOrCreateObjectForComInstance(
appManagerPtr, CreateObjectFlags.None);
if (appManager == null)
{
throw new ArgumentException("Failed to get IApplicationActivationManager interface");
}
var appManager = new ApplicationActivationManager();
const ActivateOptions noFlags = ActivateOptions.None;
var queryArguments = TerminalHelper.GetArguments(profile, _openNewTab, _openQuake);
try

View File

@@ -3,12 +3,18 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
using Microsoft.CmdPal.Ext.WindowsTerminal.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.UI;
namespace Microsoft.CmdPal.Ext.WindowsTerminal.Commands;
@@ -32,22 +38,7 @@ internal sealed partial class LaunchProfileCommand : InvokableCommand
private void Launch(string id, string profile)
{
ComWrappers cw = new StrategyBasedComWrappers();
var hr = NativeHelpers.CoCreateInstance(ref NativeHelpers.ApplicationActivationManagerCLSID, IntPtr.Zero, NativeHelpers.CLSCTXINPROCALL, ref NativeHelpers.ApplicationActivationManagerIID, out var appManagerPtr);
if (hr != 0)
{
throw new ArgumentException($"Failed to create IApplicationActivationManager instance. HR: 0x{hr:X}");
}
var appManager = (IApplicationActivationManager)cw.GetOrCreateObjectForComInstance(
appManagerPtr, CreateObjectFlags.None);
if (appManager == null)
{
throw new ArgumentException("Failed to get IApplicationActivationManager interface");
}
var appManager = new ApplicationActivationManager();
const ActivateOptions noFlags = ActivateOptions.None;
var queryArguments = TerminalHelper.GetArguments(profile, _openNewTab, _openQuake);
try

View File

@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
// Application Activation Manager Class
[ComImport]
[Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")]
public class ApplicationActivationManager : IApplicationActivationManager
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)/*, PreserveSig*/]
public extern IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public extern IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public extern IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId);
}

View File

@@ -4,7 +4,6 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
namespace Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
@@ -19,13 +18,14 @@ public enum ActivateOptions
}
// ApplicationActivationManager
[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]
[ComImport]
[Guid("2e941141-7f97-4756-ba1d-9decde894a3d")]
public partial interface IApplicationActivationManager
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IApplicationActivationManager
{
void ActivateApplication(string appUserModelId, string arguments, ActivateOptions options, out uint processId);
IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId);
void ActivateForFile(string appUserModelId, IntPtr /*IShellItemArray* */ itemArray, string verb, out uint processId);
IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId);
void ActivateForProtocol(string appUserModelId, IntPtr /* IShellItemArray* */itemArray, out uint processId);
IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId);
}

View File

@@ -1,32 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
public sealed partial class NativeHelpers
{
public const uint CLSCTXINPROCALL = 0x17;
[LibraryImport("ole32.dll")]
public static partial uint CoCreateInstance(
ref Guid rclsid,
IntPtr pUnkOuter,
uint dwClsContext,
ref Guid riid,
out IntPtr rReturnedComObject);
#pragma warning disable CA2211 // Non-constant fields should not be visible
#pragma warning disable SA1401 // Fields should be private
public static Guid ApplicationActivationManagerCLSID = new Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C");
public static Guid ApplicationActivationManagerIID = new Guid("2e941141-7f97-4756-ba1d-9decde894a3d");
#pragma warning restore SA1401 // Fields should be private
#pragma warning restore CA2211 // Non-constant fields should not be visible
}

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PathToRoot>..\..\..\..\..\</PathToRoot>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.7.250513003</WasdkNuget>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.7.250401001</WasdkNuget>
<CppWinRTNuget>$(PathToRoot)packages\Microsoft.Windows.CppWinRT.2.0.240111.5</CppWinRTNuget>
<WindowsSdkBuildToolsNuget>$(PathToRoot)packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428</WindowsSdkBuildToolsNuget>
<WebView2Nuget>$(PathToRoot)packages\Microsoft.Web.WebView2.1.0.2903.40</WebView2Nuget>

View File

@@ -3,5 +3,5 @@
<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.SDK.BuildTools" version="10.0.22621.2428" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.7.250513003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.7.250401001" targetFramework="native" />
</packages>

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.FuzzTest.props" />
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\FancyZones.FuzzTests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\editor\FancyZonesEditor\Utils\ParsingResult.cs" Link="ParsingResult.cs" />
<Compile Include="..\FancyZonesEditorCommon\Data\CustomLayouts.cs" Link="CustomLayouts.cs" />
<Compile Include="..\FancyZonesEditorCommon\Data\EditorData`1.cs" Link="EditorData`1.cs" />
<Compile Include="..\FancyZonesEditorCommon\Data\LayoutDefaultSettings.cs" Link="LayoutDefaultSettings.cs" />
<Compile Include="..\FancyZonesEditorCommon\Utils\DashCaseNamingPolicy.cs" Link="DashCaseNamingPolicy.cs" />
<Compile Include="..\FancyZonesEditorCommon\Utils\IOUtils.cs" Link="IOUtils.cs" />
<Compile Include="..\FancyZonesEditorCommon\Utils\StringUtils.cs" Link="StringUtils.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MSTest" />
<PackageReference Include="System.IO.Abstractions" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<Content Include="OneFuzzConfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -1,86 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Text.Json;
using FancyZonesEditorCommon.Data;
using FancyZonesEditorCommon.Utils;
using static FancyZonesEditorCommon.Data.CustomLayouts;
namespace FancyZones.FuzzTests
{
public class FuzzTests
{
public static void FuzzGridFromJsonElement(ReadOnlySpan<byte> input)
{
if (input.Length < 4)
{
return;
}
int inputData = BitConverter.ToInt32(input.Slice(0, 4));
// mock user input for custom-layouts.json
string mockCustomLayouts = $@"{{""custom-layouts"": [{{
""uuid"": ""{{B8C275E-A7BC-485F-A35C-67B69164F51F}}"",
""name"": ""Custom layout 1"",
""type"": ""grid"",
""info"": {{
""rows"": {inputData},
""columns"": {inputData},
""rows-percentage"": [ {inputData} ],
""columns-percentage"": [ {inputData}, {inputData}, {inputData} ],
""cell-child-map"": [ [{inputData}, {inputData}, {inputData}] ],
""show-spacing"": true,
""spacing"": {inputData},
""sensitivity-radius"": {inputData}
}}
}}]}}";
CustomLayoutListWrapper wrapper;
try
{
wrapper = JsonSerializer.Deserialize<CustomLayoutListWrapper>(mockCustomLayouts, JsonOptions);
}
catch (JsonException)
{
return;
}
List<CustomLayouts.CustomLayoutWrapper> customLayouts = wrapper.CustomLayouts;
if (customLayouts == null)
{
return;
}
// Get Layout Info from mockCustomLayouts
foreach (var zoneSet in customLayouts)
{
if (zoneSet.Uuid == null || zoneSet.Uuid.Length == 0)
{
return;
}
CustomLayouts deserializer = new CustomLayouts();
// Fuzzing the deserializer
_ = deserializer.GridFromJsonElement(zoneSet.Info.GetRawText());
}
}
private static JsonSerializerOptions JsonOptions
{
get
{
return new JsonSerializerOptions
{
PropertyNamingPolicy = new DashCaseNamingPolicy(),
WriteIndented = true,
};
}
}
}
}

View File

@@ -1,5 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]

View File

@@ -1,51 +0,0 @@
{
"configVersion": 3,
"entries": [
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "FancyZones.FuzzTests.dll",
"class": "FancyZones.FuzzTests.FuzzTests",
"method": "FuzzGridFromJsonElement",
"FuzzingTargetBinaries": [
"PowerToys.FancyZones.dll"
]
},
"adoTemplate": {
// supply the values appropriate to your
// project, where bugs will be filed
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
"skip": false,
"rebootAfterSetup": false,
"oneFuzzJobs": [
// at least one job is required
{
"projectName": "FancyZones",
"targetName": "FancyZones-dotnet-fuzzer-FuzzGridFromJsonElement"
}
],
"jobDependencies": [
// this should contain, at minimum,
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"FancyZones.FuzzTests.dll",
"FancyZones.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"Newtonsoft.Json.dll",
"System.IO.Abstractions.dll",
"Testably.Abstractions.FileSystem.Interface.dll",
"TestableIO.System.IO.Abstractions.dll",
"TestableIO.System.IO.Abstractions.Wrappers.dll",
"WinRT.Runtime.dll"
],
"SdlWorkItemId": 49911822
}
]
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.SelfContained.props" />

View File

@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\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')" />
<Import Project="..\..\..\WinAppSdkCppPre.props" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
@@ -202,12 +200,10 @@
<ResourceCompile Include="PowerRenameUI.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\WinAppSdkCppPost.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.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\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.7.250513003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.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>
@@ -215,14 +211,8 @@
<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.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\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.7.250513003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.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>

View File

@@ -184,7 +184,6 @@
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<StackPanel
@@ -559,33 +558,6 @@
Content="&#xE8B1;"
FontFamily="{ThemeResource SymbolThemeFontFamily}" />
</StackPanel>
<TextBlock
x:Name="FileTimeLabel"
x:Uid="TextBlock_FileTime"
Margin="0,16,0,8"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<StackPanel
Grid.Row="2"
Grid.Column="1"
Orientation="Horizontal"
Spacing="4">
<ComboBox
x:Name="comboBox_fileTimeParts"
Grid.Row="1"
Grid.Column="0"
Width="200"
HorizontalAlignment="Stretch"
AutomationProperties.LabeledBy="{Binding ElementName=FileDateLabel}"
SelectedIndex="0">
<ComboBoxItem x:Uid="FileTimeParts_CreationTime" />
<ComboBoxItem x:Uid="FileTimeParts_ModificationTime" />
<ComboBoxItem x:Uid="FileTimeParts_AccessTime" />
</ComboBox>
</StackPanel>
</StackPanel>
<Rectangle

View File

@@ -792,32 +792,6 @@ namespace winrt::PowerRenameUI::implementation
button_settings().Click([&](auto const&, auto const&) {
OpenSettingsApp();
});
// ComboBox RenameParts
comboBox_fileTimeParts().SelectionChanged([&](auto const&, auto const&) {
int selectedIndex = comboBox_fileTimeParts().SelectedIndex();
if (selectedIndex == 0)
{
// default behaviour. Date Created
UpdateFlag(CreationTime, UpdateFlagCommand::Set);
UpdateFlag(ModificationTime, UpdateFlagCommand::Reset);
UpdateFlag(AccessTime, UpdateFlagCommand::Reset);
}
else if (selectedIndex == 1)
{
// Date Modified
UpdateFlag(ModificationTime, UpdateFlagCommand::Set);
UpdateFlag(CreationTime, UpdateFlagCommand::Reset);
UpdateFlag(AccessTime, UpdateFlagCommand::Reset);
}
else if (selectedIndex == 2)
{
// Accessed
UpdateFlag(AccessTime, UpdateFlagCommand::Set);
UpdateFlag(CreationTime, UpdateFlagCommand::Reset);
UpdateFlag(ModificationTime, UpdateFlagCommand::Reset);
}
});
}
void MainWindow::ToggleItem(int32_t id, bool checked)

View File

@@ -411,16 +411,4 @@
<data name="ToggleButton_RandItems.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Random string features</value>
</data>
<data name="TextBlock_FileTime.Text" xml:space="preserve">
<value>Time used for replacement</value>
</data>
<data name="FileTimeParts_CreationTime.Content" xml:space="preserve">
<value>Creation Time</value>
</data>
<data name="FileTimeParts_ModificationTime.Content" xml:space="preserve">
<value>Modification Time</value>
</data>
<data name="FileTimeParts_AccessTime.Content" xml:space="preserve">
<value>Access Time</value>
</data>
</root>

View File

@@ -6,5 +6,5 @@
<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.22621.2428" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.7.250513003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.7.250401001" targetFramework="native" />
</packages>

View File

@@ -18,10 +18,7 @@ enum PowerRenameFlags
Lowercase = 0x400,
Titlecase = 0x800,
Capitalized = 0x1000,
RandomizeItems = 0x2000,
CreationTime = 0x4000,
ModificationTime = 0x8000,
AccessTime = 0x10000,
RandomizeItems = 0x2000
};
enum PowerRenameFilters
@@ -70,7 +67,7 @@ interface __declspec(uuid("C7F59201-4DE1-4855-A3A2-26FC3279C8A5")) IPowerRenameI
public:
IFACEMETHOD(PutPath)(_In_opt_ PCWSTR newPath) = 0;
IFACEMETHOD(GetPath)(_Outptr_ PWSTR * path) = 0;
IFACEMETHOD(GetTime)(_In_ DWORD flags, _Outptr_ SYSTEMTIME * time) = 0;
IFACEMETHOD(GetTime)(_Outptr_ SYSTEMTIME* time) = 0;
IFACEMETHOD(GetShellItem)(_Outptr_ IShellItem** ppsi) = 0;
IFACEMETHOD(GetOriginalName)(_Outptr_ PWSTR * originalName) = 0;
IFACEMETHOD(PutOriginalName)(_In_opt_ PCWSTR originalName) = 0;

View File

@@ -56,28 +56,12 @@ IFACEMETHODIMP CPowerRenameItem::GetPath(_Outptr_ PWSTR* path)
return hr;
}
IFACEMETHODIMP CPowerRenameItem::GetTime(_In_ DWORD flags, _Outptr_ SYSTEMTIME* time)
IFACEMETHODIMP CPowerRenameItem::GetTime(_Outptr_ SYSTEMTIME* time)
{
CSRWSharedAutoLock lock(&m_lock);
HRESULT hr = E_FAIL;
PowerRenameFlags parsedTimeType;
// Get Time by PowerRenameFlags
if (flags & PowerRenameFlags::ModificationTime)
{
parsedTimeType = PowerRenameFlags::ModificationTime;
}
else if (flags & PowerRenameFlags::AccessTime)
{
parsedTimeType = PowerRenameFlags::AccessTime;
}
else
{
// Default to modification time if no specific flag is set
parsedTimeType = PowerRenameFlags::CreationTime;
}
if (m_isTimeParsed && parsedTimeType == m_parsedTimeType)
if (m_isTimeParsed)
{
hr = S_OK;
}
@@ -86,43 +70,21 @@ IFACEMETHODIMP CPowerRenameItem::GetTime(_In_ DWORD flags, _Outptr_ SYSTEMTIME*
HANDLE hFile = CreateFileW(m_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
FILETIME FileTime;
bool success = false;
// Get Time by PowerRenameFlags
switch (parsedTimeType)
{
case PowerRenameFlags::CreationTime:
success = GetFileTime(hFile, &FileTime, NULL, NULL);
break;
case PowerRenameFlags::ModificationTime:
success = GetFileTime(hFile, NULL, NULL, &FileTime);
break;
case PowerRenameFlags::AccessTime:
success = GetFileTime(hFile, NULL, &FileTime, NULL);
break;
default:
// Default to modification time if no specific flag is set
success = GetFileTime(hFile, NULL, NULL, &FileTime);
break;
}
if (success)
FILETIME CreationTime;
if (GetFileTime(hFile, &CreationTime, NULL, NULL))
{
SYSTEMTIME SystemTime, LocalTime;
if (FileTimeToSystemTime(&FileTime, &SystemTime))
if (FileTimeToSystemTime(&CreationTime, &SystemTime))
{
if (SystemTimeToTzSpecificLocalTime(NULL, &SystemTime, &LocalTime))
{
m_time = LocalTime;
m_isTimeParsed = true;
m_parsedTimeType = parsedTimeType;
hr = S_OK;
}
}
}
}
CloseHandle(hFile);
}
*time = m_time;

View File

@@ -16,7 +16,7 @@ public:
// IPowerRenameItem
IFACEMETHODIMP PutPath(_In_opt_ PCWSTR newPath);
IFACEMETHODIMP GetPath(_Outptr_ PWSTR* path);
IFACEMETHODIMP GetTime(_In_ DWORD flags, _Outptr_ SYSTEMTIME* time);
IFACEMETHODIMP GetTime(_Outptr_ SYSTEMTIME* time);
IFACEMETHODIMP GetShellItem(_Outptr_ IShellItem** ppsi);
IFACEMETHODIMP PutOriginalName(_In_opt_ PCWSTR originalName);
IFACEMETHODIMP GetOriginalName(_Outptr_ PWSTR* originalName);
@@ -54,7 +54,6 @@ protected:
bool m_selected = true;
bool m_isFolder = false;
bool m_isTimeParsed = false;
PowerRenameFlags m_parsedTimeType = PowerRenameFlags::CreationTime;
bool m_canRename = true;
int m_id = -1;
int m_iconIndex = -1;

View File

@@ -78,7 +78,7 @@ bool DoRename(CComPtr<IPowerRenameRegEx>& spRenameRegEx, unsigned long& itemEnum
if (useFileTime)
{
winrt::check_hresult(spItem->GetTime(flags, &fileTime));
winrt::check_hresult(spItem->GetTime(&fileTime));
winrt::check_hresult(spRenameRegEx->PutFileTime(fileTime));
}

View File

@@ -1,64 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@@ -148,7 +89,7 @@
<value>This setting has been disabled by your administrator.</value>
</data>
<data name="STARTUP_DISABLED_BY_USER" xml:space="preserve">
<value>This setting has been disabled manually via &lt;a href="https://ms_settings_startupapps" target="_blank"&gt;Startup Settings&lt;/a&gt;.</value>
<value>This setting has been disabled manually via &lt;a href=&quot;https://ms_settings_startupapps&quot; target=&quot;_blank&quot;&gt;Startup Settings&lt;/a&gt;.</value>
</data>
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
<value>An update to PowerToys is available.</value>
@@ -180,9 +121,6 @@
<value>Exit</value>
<comment>Exit as a verb, as in Exit the application</comment>
</data>
<data name="SHOW_TRAY_ICON_MENU_TEXT" xml:space="preserve">
<value>Show icon</value>
</data>
<data name="SUBMIT_BUG_TEXT" xml:space="preserve">
<value>Report bug</value>
</data>
@@ -196,4 +134,4 @@
<data name="TRAY_ICON_ADMIN_TOOLTIP" xml:space="preserve">
<value>Administrator</value>
</data>
</root>
</root>

View File

@@ -5,13 +5,12 @@
#include <comdef.h>
#include <taskschd.h>
#include <common/logger/logger.h>
// Helper macros from wix.
// TODO: use "s" and "..." parameters to report errors from these functions.
#define ExitOnFailure(x, s, ...) \
if (FAILED(x)) \
{ \
Logger::error(s, ##__VA_ARGS__); \
goto LExit; \
}
#define ExitWithLastError(x, s, ...) \
@@ -22,7 +21,6 @@
{ \
x = E_FAIL; \
} \
Logger::error(s, ##__VA_ARGS__); \
goto LExit; \
}
#define ExitFunction() \
@@ -54,11 +52,11 @@ bool create_auto_start_task_for_this_user(bool runElevated)
// Get the Domain/Username for the trigger.
if (!GetEnvironmentVariable(L"USERNAME", username, USERNAME_LEN))
{
ExitWithLastError(hr, "Getting username failed: {:x}", hr);
ExitWithLastError(hr, "Getting username failed: %x", hr);
}
if (!GetEnvironmentVariable(L"USERDOMAIN", username_domain, USERNAME_DOMAIN_LEN))
{
ExitWithLastError(hr, "Getting the user's domain failed: {:x}", hr);
ExitWithLastError(hr, "Getting the user's domain failed: %x", hr);
}
wcscat_s(username_domain, L"\\");
wcscat_s(username_domain, username);
@@ -78,11 +76,11 @@ bool create_auto_start_task_for_this_user(bool runElevated)
CLSCTX_INPROC_SERVER,
IID_ITaskService,
reinterpret_cast<void**>(&pService));
ExitOnFailure(hr, "Failed to create an instance of ITaskService: {:x}", hr);
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
ExitOnFailure(hr, "ITaskService::Connect failed: {:x}", hr);
ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
// ------------------------------------------------------
// Get the PowerToys task folder. Creates it if it doesn't exist.
@@ -92,12 +90,12 @@ bool create_auto_start_task_for_this_user(bool runElevated)
// Folder doesn't exist. Get the Root folder and create the PowerToys subfolder.
ITaskFolder* pRootFolder = NULL;
hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
ExitOnFailure(hr, "Cannot get Root Folder pointer: {:x}", hr);
ExitOnFailure(hr, "Cannot get Root Folder pointer: %x", hr);
hr = pRootFolder->CreateFolder(_bstr_t(L"\\PowerToys"), _variant_t(L""), &pTaskFolder);
if (FAILED(hr))
{
pRootFolder->Release();
ExitOnFailure(hr, "Cannot create PowerToys task folder: {:x}", hr);
ExitOnFailure(hr, "Cannot create PowerToys task folder: %x", hr);
}
}
@@ -120,47 +118,47 @@ bool create_auto_start_task_for_this_user(bool runElevated)
// Create the task builder object to create the task.
hr = pService->NewTask(0, &pTask);
ExitOnFailure(hr, "Failed to create a task definition: {:x}", hr);
ExitOnFailure(hr, "Failed to create a task definition: %x", hr);
// ------------------------------------------------------
// Get the registration info for setting the identification.
hr = pTask->get_RegistrationInfo(&pRegInfo);
ExitOnFailure(hr, "Cannot get identification pointer: {:x}", hr);
ExitOnFailure(hr, "Cannot get identification pointer: %x", hr);
hr = pRegInfo->put_Author(_bstr_t(username_domain));
ExitOnFailure(hr, "Cannot put identification info: {:x}", hr);
ExitOnFailure(hr, "Cannot put identification info: %x", hr);
// ------------------------------------------------------
// Create the settings for the task
hr = pTask->get_Settings(&pSettings);
ExitOnFailure(hr, "Cannot get settings pointer: {:x}", hr);
ExitOnFailure(hr, "Cannot get settings pointer: %x", hr);
hr = pSettings->put_StartWhenAvailable(VARIANT_FALSE);
ExitOnFailure(hr, "Cannot put_StartWhenAvailable setting info: {:x}", hr);
ExitOnFailure(hr, "Cannot put_StartWhenAvailable setting info: %x", hr);
hr = pSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
ExitOnFailure(hr, "Cannot put_StopIfGoingOnBatteries setting info: {:x}", hr);
ExitOnFailure(hr, "Cannot put_StopIfGoingOnBatteries setting info: %x", hr);
hr = pSettings->put_ExecutionTimeLimit(_bstr_t(L"PT0S")); //Unlimited
ExitOnFailure(hr, "Cannot put_ExecutionTimeLimit setting info: {:x}", hr);
ExitOnFailure(hr, "Cannot put_ExecutionTimeLimit setting info: %x", hr);
hr = pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
ExitOnFailure(hr, "Cannot put_DisallowStartIfOnBatteries setting info: {:x}", hr);
ExitOnFailure(hr, "Cannot put_DisallowStartIfOnBatteries setting info: %x", hr);
hr = pSettings->put_Priority(4);
ExitOnFailure(hr, "Cannot put_Priority setting info : {:x}", hr);
ExitOnFailure(hr, "Cannot put_Priority setting info : %x", hr);
// ------------------------------------------------------
// Get the trigger collection to insert the logon trigger.
hr = pTask->get_Triggers(&pTriggerCollection);
ExitOnFailure(hr, "Cannot get trigger collection: {:x}", hr);
ExitOnFailure(hr, "Cannot get trigger collection: %x", hr);
// Add the logon trigger to the task.
{
ITrigger* pTrigger = NULL;
ILogonTrigger* pLogonTrigger = NULL;
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
ExitOnFailure(hr, "Cannot create the trigger: {:x}", hr);
ExitOnFailure(hr, "Cannot create the trigger: %x", hr);
hr = pTrigger->QueryInterface(
IID_ILogonTrigger, reinterpret_cast<void**>(&pLogonTrigger));
pTrigger->Release();
ExitOnFailure(hr, "QueryInterface call failed for ILogonTrigger: {:x}", hr);
ExitOnFailure(hr, "QueryInterface call failed for ILogonTrigger: %x", hr);
hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
@@ -172,7 +170,7 @@ bool create_auto_start_task_for_this_user(bool runElevated)
// The specified user must be a user on this computer.
hr = pLogonTrigger->put_UserId(_bstr_t(username_domain));
pLogonTrigger->Release();
ExitOnFailure(hr, "Cannot add user ID to logon trigger: {:x}", hr);
ExitOnFailure(hr, "Cannot add user ID to logon trigger: %x", hr);
}
// ------------------------------------------------------
@@ -184,23 +182,23 @@ bool create_auto_start_task_for_this_user(bool runElevated)
// Get the task action collection pointer.
hr = pTask->get_Actions(&pActionCollection);
ExitOnFailure(hr, "Cannot get Task collection pointer: {:x}", hr);
ExitOnFailure(hr, "Cannot get Task collection pointer: %x", hr);
// Create the action, specifying that it is an executable action.
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
pActionCollection->Release();
ExitOnFailure(hr, "Cannot create the action: {:x}", hr);
ExitOnFailure(hr, "Cannot create the action: %x", hr);
// QI for the executable task pointer.
hr = pAction->QueryInterface(
IID_IExecAction, reinterpret_cast<void**>(&pExecAction));
pAction->Release();
ExitOnFailure(hr, "QueryInterface call failed for IExecAction: {:x}", hr);
ExitOnFailure(hr, "QueryInterface call failed for IExecAction: %x", hr);
// Set the path of the executable to PowerToys (passed as CustomActionData).
hr = pExecAction->put_Path(_bstr_t(wszExecutablePath));
pExecAction->Release();
ExitOnFailure(hr, "Cannot set path of executable: {:x}", hr);
ExitOnFailure(hr, "Cannot set path of executable: %x", hr);
}
// ------------------------------------------------------
@@ -208,7 +206,7 @@ bool create_auto_start_task_for_this_user(bool runElevated)
{
IPrincipal* pPrincipal = NULL;
hr = pTask->get_Principal(&pPrincipal);
ExitOnFailure(hr, "Cannot get principal pointer: {:x}", hr);
ExitOnFailure(hr, "Cannot get principal pointer: %x", hr);
// Set up principal information:
hr = pPrincipal->put_Id(_bstr_t(L"Principal1"));
@@ -226,7 +224,7 @@ bool create_auto_start_task_for_this_user(bool runElevated)
hr = pPrincipal->put_RunLevel(_TASK_RUNLEVEL::TASK_RUNLEVEL_LUA);
}
pPrincipal->Release();
ExitOnFailure(hr, "Cannot put principal run level: {:x}", hr);
ExitOnFailure(hr, "Cannot put principal run level: %x", hr);
}
// ------------------------------------------------------
// Save the task in the PowerToys folder.
@@ -241,7 +239,7 @@ bool create_auto_start_task_for_this_user(bool runElevated)
TASK_LOGON_INTERACTIVE_TOKEN,
SDDL_FULL_ACCESS_FOR_EVERYONE,
&pRegisteredTask);
ExitOnFailure(hr, "Error saving the Task : {:x}", hr);
ExitOnFailure(hr, "Error saving the Task : %x", hr);
}
LExit:
@@ -277,7 +275,7 @@ bool delete_auto_start_task_for_this_user()
// Get the Username for the task.
if (!GetEnvironmentVariable(L"USERNAME", username, USERNAME_LEN))
{
ExitWithLastError(hr, "Getting username failed: {:x}", hr);
ExitWithLastError(hr, "Getting username failed: %x", hr);
}
// Task Name.
@@ -291,11 +289,11 @@ bool delete_auto_start_task_for_this_user()
CLSCTX_INPROC_SERVER,
IID_ITaskService,
reinterpret_cast<void**>(&pService));
ExitOnFailure(hr, "Failed to create an instance of ITaskService: {:x}", hr);
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
ExitOnFailure(hr, "ITaskService::Connect failed: {:x}", hr);
ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
// ------------------------------------------------------
// Get the PowerToys task folder.
@@ -342,7 +340,7 @@ bool is_auto_start_task_active_for_this_user()
// Get the Username for the task.
if (!GetEnvironmentVariable(L"USERNAME", username, USERNAME_LEN))
{
ExitWithLastError(hr, "Getting username failed: {:x}", hr);
ExitWithLastError(hr, "Getting username failed: %x", hr);
}
// Task Name.
@@ -356,16 +354,16 @@ bool is_auto_start_task_active_for_this_user()
CLSCTX_INPROC_SERVER,
IID_ITaskService,
reinterpret_cast<void**>(&pService));
ExitOnFailure(hr, "Failed to create an instance of ITaskService: {:x}", hr);
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
// Connect to the task service.
hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
ExitOnFailure(hr, "ITaskService::Connect failed: {:x}", hr);
ExitOnFailure(hr, "ITaskService::Connect failed: %x", hr);
// ------------------------------------------------------
// Get the PowerToys task folder.
hr = pService->GetFolder(_bstr_t(L"\\PowerToys"), &pTaskFolder);
ExitOnFailure(hr, "ITaskFolder doesn't exist: {:x}", hr);
ExitOnFailure(hr, "ITaskFolder doesn't exist: %x", hr);
// ------------------------------------------------------
// If the task exists, disable.

View File

@@ -1,7 +1,6 @@
#include "pch.h"
#include "general_settings.h"
#include "auto_start_helper.h"
#include "tray_icon.h"
#include "Generated files/resource.h"
#include <common/SettingsAPI/settings_helpers.h>
@@ -15,7 +14,6 @@
// TODO: would be nice to get rid of these globals, since they're basically cached json settings
static std::wstring settings_theme = L"system";
static bool show_tray_icon = true;
static bool run_as_elevated = false;
static bool show_new_updates_toast_notification = true;
static bool download_updates_automatically = true;
@@ -40,7 +38,6 @@ json::JsonObject GeneralSettings::to_json()
}
result.SetNamedValue(L"enabled", std::move(enabled));
result.SetNamedValue(L"show_tray_icon", json::value(showSystemTrayIcon));
result.SetNamedValue(L"is_elevated", json::value(isElevated));
result.SetNamedValue(L"run_elevated", json::value(isRunElevated));
result.SetNamedValue(L"show_new_updates_toast_notification", json::value(showNewUpdatesToastNotification));
@@ -77,9 +74,7 @@ json::JsonObject load_general_settings()
GeneralSettings get_general_settings()
{
const bool is_user_admin = check_user_is_admin();
GeneralSettings settings
{
.showSystemTrayIcon = show_tray_icon,
GeneralSettings settings{
.isElevated = is_process_elevated(),
.isRunElevated = run_as_elevated,
.isAdmin = is_user_admin,
@@ -219,13 +214,6 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save)
settings_theme = general_configs.GetNamedString(L"theme");
}
if (json::has(general_configs, L"show_tray_icon", json::JsonValueType::Boolean))
{
show_tray_icon = general_configs.GetNamedBoolean(L"show_tray_icon");
// Update tray icon visibility when setting is toggled
set_tray_icon_visible(show_tray_icon);
}
if (save)
{
GeneralSettings save_settings = get_general_settings();

View File

@@ -5,7 +5,6 @@
struct GeneralSettings
{
bool isStartupEnabled;
bool showSystemTrayIcon;
std::wstring startupDisabledReason;
std::map<std::wstring, bool> isModulesEnabledMap;
bool isElevated;

View File

@@ -90,7 +90,6 @@ void open_menu_from_another_instance(std::optional<std::string> settings_window)
msg = static_cast<LPARAM>(ESettingsWindowNames_from_string(settings_window.value()));
}
PostMessageW(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, msg);
SetForegroundWindow(hwnd_main); // Bring the settings window to the front
}
int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe, bool showRestartNotificationAfterUpdate)
@@ -105,7 +104,6 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
#endif
Trace::RegisterProvider();
start_tray_icon(isProcessElevated);
set_tray_icon_visible(get_general_settings().showSystemTrayIcon);
CentralizedKeyboardHook::Start();
int result = -1;

View File

@@ -20,5 +20,4 @@
#define ID_ABOUT_MENU_COMMAND 40003
#define ID_REPORT_BUG_COMMAND 40004
#define ID_DOCUMENTATION_MENU_COMMAND 40005
#define ID_QUICK_ACCESS_MENU_COMMAND 40006
#define ID_SHOW_TRAY_ICON_MENU_COMMAND 40007
#define ID_QUICK_ACCESS_MENU_COMMAND 40006

Binary file not shown.

View File

@@ -2,7 +2,6 @@
#include "Generated files/resource.h"
#include "settings_window.h"
#include "tray_icon.h"
#include "general_settings.h"
#include "centralized_hotkeys.h"
#include "centralized_kb_hook.h"
#include <Windows.h>
@@ -91,13 +90,6 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
}
DestroyWindow(window);
break;
case ID_SHOW_TRAY_ICON_MENU_COMMAND:
{
GeneralSettings settings = get_general_settings();
settings.showSystemTrayIcon = true;
apply_general_settings(settings.to_json(), true);
break;
}
case ID_ABOUT_MENU_COMMAND:
if (!about_box_shown)
{
@@ -199,13 +191,11 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
{
static std::wstring settings_menuitem_label = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT);
static std::wstring exit_menuitem_label = GET_RESOURCE_STRING(IDS_EXIT_MENU_TEXT);
static std::wstring show_tray_icon_menuitem_label = GET_RESOURCE_STRING(IDS_SHOW_TRAY_ICON_MENU_TEXT);
static std::wstring submit_bug_menuitem_label = GET_RESOURCE_STRING(IDS_SUBMIT_BUG_TEXT);
static std::wstring documentation_menuitem_label = GET_RESOURCE_STRING(IDS_DOCUMENTATION_MENU_TEXT);
static std::wstring quick_access_menuitem_label = GET_RESOURCE_STRING(IDS_QUICK_ACCESS_MENU_TEXT);
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
change_menu_item_text(ID_EXIT_MENU_COMMAND, exit_menuitem_label.data());
change_menu_item_text(ID_SHOW_TRAY_ICON_MENU_COMMAND, show_tray_icon_menuitem_label.data());
change_menu_item_text(ID_REPORT_BUG_COMMAND, submit_bug_menuitem_label.data());
change_menu_item_text(ID_DOCUMENTATION_MENU_COMMAND, documentation_menuitem_label.data());
change_menu_item_text(ID_QUICK_ACCESS_MENU_COMMAND, quick_access_menuitem_label.data());
@@ -322,14 +312,6 @@ void start_tray_icon(bool isProcessElevated)
}
}
void set_tray_icon_visible(bool shouldIconBeVisible)
{
tray_icon_data.uFlags |= NIF_STATE;
tray_icon_data.dwStateMask = NIS_HIDDEN;
tray_icon_data.dwState = shouldIconBeVisible ? 0 : NIS_HIDDEN;
Shell_NotifyIcon(NIM_MODIFY, &tray_icon_data);
}
void stop_tray_icon()
{
if (tray_icon_created)

View File

@@ -4,8 +4,6 @@
// Start the Tray Icon
void start_tray_icon(bool isProcessElevated);
// Change the Tray Icon visibility
void set_tray_icon_visible(bool shouldIconBeVisible);
// Stop the Tray Icon
void stop_tray_icon();
// Open the Settings Window
@@ -15,5 +13,4 @@ typedef void (*main_loop_callback_function)(PVOID);
// Calls a callback in _callback
bool dispatch_run_on_main_ui_thread(main_loop_callback_function _callback, PVOID data);
// Must be the same as: settings-ui/Settings.UI/Views/ShellPage.xaml.cs -> ExitPTItem_Tapped() -> const string ptTrayIconWindowClass
const inline wchar_t* pt_tray_icon_window_class = L"PToyTrayIconWindow";

View File

@@ -19,10 +19,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("startup")]
public bool Startup { get; set; }
// Gets or sets a value indicating whether the powertoys system tray icon should be hidden.
[JsonPropertyName("show_tray_icon")]
public bool ShowSysTrayIcon { get; set; }
// Gets or sets a value indicating whether the powertoy elevated.
[CmdConfigureIgnoreAttribute]
[JsonPropertyName("is_elevated")]
@@ -79,7 +75,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
public GeneralSettings()
{
Startup = false;
ShowSysTrayIcon = true;
IsAdmin = false;
EnableWarningsElevatedApps = true;
IsElevated = false;

View File

@@ -224,36 +224,6 @@ namespace ViewModelTests
viewModel.ThemeIndex = 0;
}
[TestMethod]
public void IsShowSysTrayIconEnabledByDefaultShouldDisableWhenSuccessful()
{
// Arrange
// Assert
Func<string, int> sendMockIPCConfigMSG = msg =>
{
OutGoingGeneralSettings snd = JsonSerializer.Deserialize<OutGoingGeneralSettings>(msg);
Assert.IsFalse(snd.GeneralSettings.ShowSysTrayIcon);
return 0;
};
Func<string, int> sendRestartAdminIPCMessage = msg => { return 0; };
Func<string, int> sendCheckForUpdatesIPCMessage = msg => { return 0; };
GeneralViewModel viewModel = new(
settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
"GeneralSettings_RunningAsAdminText",
"GeneralSettings_RunningAsUserText",
false,
false,
sendMockIPCConfigMSG,
sendRestartAdminIPCMessage,
sendCheckForUpdatesIPCMessage,
GeneralSettingsFileName);
Assert.IsTrue(viewModel.ShowSysTrayIcon);
// Act
viewModel.ShowSysTrayIcon = false;
}
[TestMethod]
public void AllModulesAreEnabledByDefault()
{

View File

@@ -17,7 +17,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
internal const int SW_SHOWNORMAL = 1;
internal const int SW_SHOWMAXIMIZED = 3;
internal const int SW_HIDE = 0;
internal const int WM_COMMAND = 0x0111; // https://learn.microsoft.com/en-us/windows/win32/menurc/wm-command
[DllImport("user32.dll")]
internal static extern IntPtr GetActiveWindow();
@@ -49,12 +48,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
[DllImport("Comdlg32.dll", CharSet = CharSet.Unicode)]
internal static extern bool GetOpenFileName([In, Out] OpenFileName openFileName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
internal static extern IntPtr SendMessage(IntPtr hWnd, IntPtr msg, UIntPtr wParam, UIntPtr lParam);
[DllImport("comdlg32.dll", CharSet = CharSet.Auto, EntryPoint = "ChooseFont", SetLastError = true)]
internal static extern bool ChooseFont(IntPtr lpChooseFont);

View File

@@ -39,7 +39,6 @@
<tkconverters:StringFormatConverter x:Key="StringFormatConverter" />
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
<x:Double x:Key="SettingsCardSpacing">2</x:Double>
<!-- Overrides -->
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>

View File

@@ -10,7 +10,7 @@
<StackPanel
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
Orientation="Vertical"
Spacing="{StaticResource SettingsCardSpacing}" />
Spacing="2" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>

View File

@@ -176,7 +176,7 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout
});
}
internal void ReportBugBtn_Click(object sender, RoutedEventArgs e)
private void ReportBugBtn_Click(object sender, RoutedEventArgs e)
{
ViewModel.StartBugReport();

View File

@@ -266,10 +266,6 @@
<tkcontrols:SettingsCard x:Uid="GeneralPage_RunAtStartUp" IsEnabled="{x:Bind ViewModel.IsRunAtStartupGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.Startup, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="ShowSystemTrayIcon">
<ToggleSwitch x:Uid="ShowSystemTrayIcon_ToggleSwitch" IsOn="{x:Bind ViewModel.ShowSysTrayIcon, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
BorderThickness="0"
@@ -406,11 +402,10 @@
</InfoBar>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback" Visibility="Visible">
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<StackPanel>
<HyperlinkButton
x:Uid="GeneralPage_DiagnosticsAndFeedback_Link"
Margin="0,0,0,8"
Padding="0"
Margin="-8,0,0,0"
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
<tkcontrols:SettingsCard
x:Uid="GeneralPage_EnableDataDiagnostics"
@@ -454,12 +449,7 @@
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
</InfoBar.ActionButton>
</InfoBar>
<tkcontrols:SettingsCard x:Uid="GeneralPage_ReportBugPackage" HeaderIcon="{ui:FontIcon Glyph=&#xEBE8;}">
<Button
x:Uid="GeneralPageReportBugPackage"
HorizontalAlignment="Right"
Click="BugReportToolClicked" />
</tkcontrols:SettingsCard>
</StackPanel>
</controls:SettingsGroup>
</StackPanel>

View File

@@ -7,7 +7,6 @@ using System.Threading;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Flyout;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
@@ -166,24 +165,5 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
await Task.Run(ViewModel.ViewDiagnosticData);
}
private void ExitPTItem_Tapped(object sender, RoutedEventArgs e)
{
const string ptTrayIconWindowClass = "PToyTrayIconWindow"; // Defined in runner/tray_icon.h
const nuint ID_EXIT_MENU_COMMAND = 40001; // Generated resource from runner/runner.base.rc
// Exit the XAML application
Application.Current.Exit();
// Invoke the exit command from the tray icon
IntPtr hWnd = NativeMethods.FindWindow(ptTrayIconWindowClass, ptTrayIconWindowClass);
NativeMethods.SendMessage(hWnd, NativeMethods.WM_COMMAND, ID_EXIT_MENU_COMMAND, 0);
}
private void BugReportToolClicked(object sender, RoutedEventArgs e)
{
var launchPage = new LaunchPage();
launchPage.ReportBugBtn_Click(sender, e);
}
}
}

View File

@@ -39,17 +39,10 @@
Margin="48,0,0,0"
VerticalAlignment="Top"
IsHitTestVisible="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftTitleBarColumn" Width="*" />
<ColumnDefinition x:Name="RightTitleBarColumn" Width="Auto" />
</Grid.ColumnDefinitions>
<animations:Implicit.Animations>
<animations:OffsetAnimation Duration="0:0:0.3" />
</animations:Implicit.Animations>
<StackPanel
Grid.Column="0"
HorizontalAlignment="Left"
Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<Image
Width="16"
Height="16"
@@ -71,24 +64,6 @@
TextWrapping="NoWrap"
Visibility="Collapsed" />
</StackPanel>
<StackPanel
Grid.Column="1"
Margin="0,0,148,0"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
x:Name="ShutDownBtn"
Height="48"
Click="ExitPTItem_Tapped"
Style="{StaticResource SubtleButtonStyle}">
<FontIcon FontSize="16" Glyph="&#xE7E8;" />
<ToolTipService.ToolTip>
<ToolTip>
<TextBlock x:Uid="AppTitleBarShutDown_Tooltip" />
</ToolTip>
</ToolTipService.ToolTip>
</Button>
</StackPanel>
</Grid>
<NavigationView
x:Name="navigationView"

Some files were not shown because too many files have changed in this diff Show More