diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt
index f5d259c0f2..f570a231af 100644
--- a/.github/actions/spell-check/allow/names.txt
+++ b/.github/actions/spell-check/allow/names.txt
@@ -91,6 +91,7 @@ Hemmerlein
hlaueriksson
Horvalds
Howett
+hotkidfamily
htcfreek
Huynh
Ionut
@@ -98,6 +99,7 @@ jamrobot
Jaswal
Jaylyn
jefflord
+Jeremic
Jordi
jyuwono
kai
@@ -222,6 +224,7 @@ openai
Quickime
regedit
roslyn
+Skia
Spotify
Vanara
wangyi
diff --git a/.github/actions/spell-check/excludes.txt b/.github/actions/spell-check/excludes.txt
index f7fb1ec196..f5710e72ce 100644
--- a/.github/actions/spell-check/excludes.txt
+++ b/.github/actions/spell-check/excludes.txt
@@ -126,3 +126,4 @@
^src/common/sysinternals/Eula/
^tools/Verification scripts/Check preview handler registration\.ps1$
ignore$
+^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 1dcfdef0e1..68555a02f9 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -1513,6 +1513,7 @@ SICHINT
SIDs
siex
sigdn
+Signedness
SIGNINGSCENARIO
signtool
SINGLEKEY
diff --git a/.pipelines/applyXamlStyling.ps1 b/.pipelines/applyXamlStyling.ps1
index 7cb7b4a4b0..1facedc569 100644
--- a/.pipelines/applyXamlStyling.ps1
+++ b/.pipelines/applyXamlStyling.ps1
@@ -41,6 +41,9 @@ Write-Output ""
Write-Output "Restoring dotnet tools..."
dotnet tool restore --disable-parallel --no-cache
+# Use Regex syntax
+$PathExcludes = "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)|(\\RegistryPreviewUILib\\Controls\\HexBox\\)"
+
if (-not $Passive)
{
# Look for unstaged changed files by default
@@ -87,7 +90,7 @@ if (-not $Passive)
}
Write-Output "Running Git Diff: $gitDiffCommand"
- $files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$"
+ $files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$" | Where-Object { $_ -notmatch $PathExcludes }
if (-not $Passive -and -not $Main -and -not $Unstaged -and -not $Staged -and -not $LastCommit)
{
@@ -107,7 +110,7 @@ if (-not $Passive)
else
{
Write-Output "Checking all files (passively)"
- $files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)" }
+ $files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch $PathExcludes }
if ($files.count -gt 0)
{
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8116fe99b6..06f8e8ddef 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -69,6 +69,8 @@
+
+
diff --git a/NOTICE.md b/NOTICE.md
index 2b94d67a4b..f36311d4ea 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1427,6 +1427,37 @@ EXHIBIT A -Mozilla Public License.
## Utility: Registry Preview
+### HexBox.WinUI
+
+We use HexBox.WinUI to show a preview of binary values.
+
+**Source**: https://github.com/hotkidfamily/HexBox.WinUI
+
+```
+MIT License
+
+Copyright (c) 2019 Filip Jeremic
+Copyright (c) 2024~2025 hotkidfamily@gmail.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+```
+
### Monaco Editor
**Source**: https://github.com/Microsoft/monaco-editor
@@ -1457,6 +1488,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
+
## NuGet Packages used by PowerToys
- AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta
@@ -1517,6 +1549,7 @@ SOFTWARE.
- ReverseMarkdown 4.1.0
- ScipBe.Common.Office.OneNote 3.0.1
- SharpCompress 0.37.2
+- SkiaSharp.Views.WinUI 2.88.9
- StreamJsonRpc 2.21.69
- StyleCop.Analyzers 1.2.0-beta.556
- System.CodeDom 9.0.6
diff --git a/src/codeAnalysis/GlobalSuppressions.cs b/src/codeAnalysis/GlobalSuppressions.cs
index d5ff98e548..ae544b0c76 100644
--- a/src/codeAnalysis/GlobalSuppressions.cs
+++ b/src/codeAnalysis/GlobalSuppressions.cs
@@ -76,3 +76,47 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.INotifyPropertyChangedGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "type", Target = "~T:Peek.UI.Views.TitleBar")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
+
+// HexBox control in RegistryPreviewUILib (We decided to copy the original code and not fix all theses problems for easier updating.)
+[assembly: SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("Naming", "CA1720:Identifiers should not contain type names", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("Performance", "CA1805:Do not initialize unnecessarily", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1648: has been used on an element that doesn't inherit from a base class or implement an interface.", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1500:Braces for multi-line statements should not share line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1502:Element should not be on a single line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1505:Opening braces should not be followed by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1507:Code should not contain multiple blank lines in a row", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1508:Closing braces should not be preceded by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1509:Opening braces should not be preceded by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:Single-line comments should not be followed by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:Statement should not use unnecessary parenthesis", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1407:Arithmetic expressions should declare precedence", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1413:Use trailing comma in multi-line initializers", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1312:Variable names should begin with lower-case letter", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1108:Block statements should not contain embedded comments", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1129:Do not use default value type constructor", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1000:Keywords should be spaced correctly", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1024:Colons Should Be Spaced Correctly", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1028:Code should not contain trailing whitespace", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
+[assembly: SuppressMessage("Usage", "CsWinRT1028:Class is not marked partial", Justification = "", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
diff --git a/src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj b/src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj
index 36bd1f4f4d..8ca723808f 100644
--- a/src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj
+++ b/src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj
@@ -31,7 +31,7 @@
-
+
diff --git a/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/App.xaml b/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/App.xaml
index 7c2836890c..400d0c71fd 100644
--- a/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/App.xaml
+++ b/src/modules/registrypreview/RegistryPreview/RegistryPreviewXAML/App.xaml
@@ -10,7 +10,31 @@
-
+
+
+
+
+
+
+
+
+ 1
+ 1,1,1,2
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+
+
diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/AddressFormat.cs b/src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/AddressFormat.cs
new file mode 100644
index 0000000000..8219ed8b51
--- /dev/null
+++ b/src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/AddressFormat.cs
@@ -0,0 +1,43 @@
+// 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.
+
+//
+// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
+// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
+// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
+//
+
+namespace RegistryPreviewUILib.HexBox
+{
+ ///
+ /// Enumerates the address column formatting options.
+ ///
+ public enum AddressFormat
+ {
+ ///
+ /// 16 bit HEX address "0000".
+ ///
+ Address16,
+
+ ///
+ /// 24 bit HEX address "00:0000".
+ ///
+ Address24,
+
+ ///
+ /// 32 bit HEX address "0000:0000".
+ ///
+ Address32,
+
+ ///
+ /// 48 bit HEX address "0000:00000000".
+ ///
+ Address48,
+
+ ///
+ /// 64 bit HEX address "00000000:00000000".
+ ///
+ Address64,
+ }
+}
diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/CanvasCommands.cs b/src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/CanvasCommands.cs
new file mode 100644
index 0000000000..dca1f95725
--- /dev/null
+++ b/src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/CanvasCommands.cs
@@ -0,0 +1,43 @@
+// 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.
+
+//
+// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
+// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
+// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
+//
+using System;
+using System.Windows.Input;
+
+namespace RegistryPreviewUILib.HexBox
+{
+ public class RelayCommand : ICommand
+ {
+ private readonly Action
-
+
+
+
@@ -51,6 +53,7 @@
+
@@ -59,10 +62,21 @@
Always
-
+
-
+
MSBuild:Compile
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+
+
+
+
diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs
index 1bf403c3fa..4bddb8d9a3 100644
--- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs
+++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs
@@ -6,7 +6,6 @@ using System;
using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml;
-using Windows.ApplicationModel.DataTransfer;
namespace RegistryPreviewUILib
{
@@ -29,6 +28,8 @@ namespace RegistryPreviewUILib
public string Value { get; set; }
+ public bool IsEmptyBinary { private get; set; }
+
public string ValueOneLine => Value.Replace('\r', ' ');
public string ToolTipText { get; set; }
@@ -54,6 +55,10 @@ namespace RegistryPreviewUILib
}
}
+ public bool ShowPreviewButton =>
+ Type != "ERROR" && Type != string.Empty &&
+ Value != string.Empty && IsEmptyBinary != true;
+
public RegistryValue(string name, string type, string value, string key)
{
this.Name = name;
diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw
index 9324207224..54ef71284e 100644
--- a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw
+++ b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw
@@ -277,16 +277,20 @@
Copy path
Like "Copy item"
-
+
Copy name
Like "Copy item"
+
+ Copy
+ Like "Copy item"
+
- Copy type
+ Copy
Like "Copy item"
- Copy data
+ Copy
Like "Copy item"
@@ -297,6 +301,65 @@
Copy value with key path
Like "Copy item"
+
+ Show extended preview
+
+
+ Show extended preview
+
+
+ View data
+
+
+ Close
+ like "Close window"
+
+
+ Hexadecimal
+
+
+ Decimal
+
+
+ Raw value
+
+
+ Expanded value
+
+
+ Readable text
+ Means text that is human readable and not only control characters.
+
+
+ Data
+ Like "binary data"
+
+
+ Multiline text value
+
+
+ Text value
+
+
+ Binary data preview
+
+
+ Preview of readable text
+
+
+ Copy
+ Like "copy the value"
+
+
+ Copy text
+ Like "Copy the text"
+
+
+ Select all
+
+
+ Extended data preview
+
New
diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Themes/Generic.xaml b/src/modules/registrypreview/RegistryPreviewUILib/Themes/Generic.xaml
new file mode 100644
index 0000000000..35011f155b
--- /dev/null
+++ b/src/modules/registrypreview/RegistryPreviewUILib/Themes/Generic.xaml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+