[EnvVar][Hosts][RegPrev]Decouple and refactor to make it "packable" as nuget package (#32604)
* WIP Hosts - remove deps * Add consumer app * Move App and MainWindow to Consumer app. Make Hosts dll * Try consume it * Fix errors * Make it work with custom build targets * Dependency injection Refactor Explicit page creation Wire missing dependencies * Fix installer * Remove unneeded stuff * Fix build again * Extract UI and logic from MainWindow to RegistryPreviewMainPage * Convert to lib Change namespace to RegistryPreviewUILib Remove PT deps * Add exe app and move App.xaml and MainWindow.xaml * Consume the lib * Update Hosts package creation * Fix RegistryPreview package creation * Rename RegistryPreviewUI back to RegistryPreview * Back to consuming lib * Ship icons and assets in nuget packages * Rename to EnvironmentVariablesUILib and convert to lib * Add app and consume * Telemetry * GPO * nuget * Rename HostsPackageConsumer to Hosts and Hosts lib to HostsUILib * Assets cleanup * nuget struct * v0 * assets * [Hosts] Re-add AppList to Lib Assets, [RegPrev] Copy lib assets to out dir * Sign UI dlls * Revert WinUIEx bump * Cleanup * Align deps * version exception dll * Fix RegistryPreview crashes * XAML format * XAML format 2 * Pack .pri files in lib/ dir --------- Co-authored-by: Darshak Bhatti <dabhatti@microsoft.com>
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 367 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 678 B |
|
After Width: | Height: | Size: 832 B |
|
After Width: | Height: | Size: 356 B |
39
src/modules/registrypreview/RegistryPreviewUILib/FileName.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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 RegistryPreviewUILib
|
||||
{
|
||||
// Workaround for File Pickers that don't work while running as admin, per:
|
||||
// https://github.com/microsoft/WindowsAppSDK/issues/2504
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct FileName
|
||||
{
|
||||
public int StructSize;
|
||||
public IntPtr HwndOwner;
|
||||
public IntPtr Instance;
|
||||
public string Filter;
|
||||
public string CustomFilter;
|
||||
public int MaxCustFilter;
|
||||
public int FilterIndex;
|
||||
public string File;
|
||||
public int MaxFile;
|
||||
public string FileTitle;
|
||||
public int MaxFileTitle;
|
||||
public string InitialDir;
|
||||
public string Title;
|
||||
public int Flags;
|
||||
public short FileOffset;
|
||||
public short FileExtension;
|
||||
public string DefExt;
|
||||
public IntPtr CustData;
|
||||
public IntPtr Hook;
|
||||
public string TemplateName;
|
||||
public IntPtr PtrReserved;
|
||||
public int Reserved;
|
||||
public int FlagsEx;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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 RegistryPreviewUILib
|
||||
{
|
||||
// Workaround for File Pickers that don't work while running as admin, per:
|
||||
// https://github.com/microsoft/WindowsAppSDK/issues/2504
|
||||
public static partial class OpenFilePicker
|
||||
{
|
||||
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
private static extern bool GetOpenFileName(ref FileName openFileName);
|
||||
|
||||
public static string ShowDialog(IntPtr windowHandle, string filter, string dialogTitle)
|
||||
{
|
||||
FileName openFileName = default(FileName);
|
||||
openFileName.StructSize = Marshal.SizeOf(openFileName);
|
||||
|
||||
openFileName.HwndOwner = windowHandle;
|
||||
openFileName.Filter = filter;
|
||||
openFileName.File = new string(new char[256]);
|
||||
openFileName.MaxFile = openFileName.File.Length;
|
||||
openFileName.FileTitle = new string(new char[64]);
|
||||
openFileName.MaxFileTitle = openFileName.FileTitle.Length;
|
||||
openFileName.Title = dialogTitle;
|
||||
|
||||
if (GetOpenFileName(ref openFileName))
|
||||
{
|
||||
return openFileName.File;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
/// <summary>
|
||||
/// Class representing an each item in the tree view, each one a Registry Key;
|
||||
/// FullPath is so we can re-select the node after a live update
|
||||
/// Tag is an Array of ListViewItems that stores all the children for the current object
|
||||
/// </summary>
|
||||
public class RegistryKey
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string FullPath { get; set; }
|
||||
|
||||
public string Image { get; set; }
|
||||
|
||||
public string ToolTipText { get; set; }
|
||||
|
||||
public object Tag { get; set; }
|
||||
|
||||
public RegistryKey(string name, string fullPath, string image, string toolTipText)
|
||||
{
|
||||
this.Name = name;
|
||||
this.FullPath = fullPath;
|
||||
this.Image = image;
|
||||
this.ToolTipText = toolTipText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.WinUI.UI.Controls;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Windows.Foundation.Metadata;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
public sealed partial class RegistryPreviewMainPage : Page
|
||||
{
|
||||
/// <summary>
|
||||
/// Event that is will prevent the app from closing if the "save file" flag is active
|
||||
/// </summary>
|
||||
public void MainWindow_Closed(object sender, WindowEventArgs args)
|
||||
{
|
||||
// Only block closing if the REG file has been edited but not yet saved
|
||||
if (saveButton.IsEnabled)
|
||||
{
|
||||
// if true, the app will not close
|
||||
args.Handled = true;
|
||||
|
||||
// ask the user if they want to save, discard or cancel the close; strings must be loaded here and passed to avoid timing issues
|
||||
HandleDirtyClosing(
|
||||
resourceLoader.GetString("YesNoCancelDialogTitle"),
|
||||
resourceLoader.GetString("YesNoCancelDialogContent"),
|
||||
resourceLoader.GetString("YesNoCancelDialogPrimaryButtonText"),
|
||||
resourceLoader.GetString("YesNoCancelDialogSecondaryButtonText"),
|
||||
resourceLoader.GetString("YesNoCancelDialogCloseButtonText"));
|
||||
}
|
||||
|
||||
// Check to see if the textbox's context menu is open
|
||||
if (textBox.ContextFlyout != null && textBox.ContextFlyout.IsOpen)
|
||||
{
|
||||
textBox.ContextFlyout.Hide();
|
||||
|
||||
// if true, the app will not close yet
|
||||
args.Handled = true;
|
||||
|
||||
// HACK: To fix https://github.com/microsoft/PowerToys/issues/28820, wait a bit for the close animation of the flyout to run before closing the application.
|
||||
// This might be called many times if the flyout still hasn't been closed, as Window_Closed will be called again by App.Current.Exit
|
||||
DispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
await Task.Delay(100);
|
||||
Application.Current.Exit();
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that gets fired after the visual tree has been fully loaded; the app opens the reg file from here so it can show a message box successfully
|
||||
/// </summary>
|
||||
private void GridPreview_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// static flag to track whether the Visual Tree is ready - if the main Grid has been loaded, the tree is ready.
|
||||
visualTreeReady = true;
|
||||
|
||||
// Check to see if the REG file was opened and parsed successfully
|
||||
if (OpenRegistryFile(_appFileName) == false)
|
||||
{
|
||||
if (File.Exists(_appFileName))
|
||||
{
|
||||
// Allow Refresh and Edit to be enabled because a broken Reg file might be fixable
|
||||
UpdateToolBarAndUI(false, true, true);
|
||||
_updateWindowTitleFunction(resourceLoader.GetString("InvalidRegistryFileTitle"));
|
||||
textBox.TextChanged += TextBox_TextChanged;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateToolBarAndUI(false, false, false);
|
||||
_updateWindowTitleFunction(string.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textBox.TextChanged += TextBox_TextChanged;
|
||||
}
|
||||
|
||||
textBox.Focus(FocusState.Programmatic);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses a picker to select a new file to open
|
||||
/// </summary>
|
||||
private async void OpenButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Check to see if the current file has been saved
|
||||
if (saveButton.IsEnabled)
|
||||
{
|
||||
ContentDialog contentDialog = new ContentDialog()
|
||||
{
|
||||
Title = resourceLoader.GetString("YesNoCancelDialogTitle"),
|
||||
Content = resourceLoader.GetString("YesNoCancelDialogContent"),
|
||||
PrimaryButtonText = resourceLoader.GetString("YesNoCancelDialogPrimaryButtonText"),
|
||||
SecondaryButtonText = resourceLoader.GetString("YesNoCancelDialogSecondaryButtonText"),
|
||||
CloseButtonText = resourceLoader.GetString("YesNoCancelDialogCloseButtonText"),
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
};
|
||||
|
||||
// Use this code to associate the dialog to the appropriate AppWindow by setting
|
||||
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
|
||||
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
|
||||
{
|
||||
contentDialog.XamlRoot = this.Content.XamlRoot;
|
||||
}
|
||||
|
||||
ContentDialogResult contentDialogResult = await contentDialog.ShowAsync();
|
||||
switch (contentDialogResult)
|
||||
{
|
||||
case ContentDialogResult.Primary:
|
||||
// Save, then continue the file open
|
||||
SaveFile();
|
||||
break;
|
||||
case ContentDialogResult.Secondary:
|
||||
// Don't save and continue the file open!
|
||||
saveButton.IsEnabled = false;
|
||||
break;
|
||||
default:
|
||||
// Don't open the new file!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Pull in a new REG file - we have to use the direct Win32 method because FileOpenPicker crashes when it's
|
||||
// called while running as admin
|
||||
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow);
|
||||
string filename = OpenFilePicker.ShowDialog(
|
||||
windowHandle,
|
||||
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
|
||||
resourceLoader.GetString("OpenDialogTitle"));
|
||||
|
||||
if (filename == string.Empty || File.Exists(filename) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StorageFile storageFile = await StorageFile.GetFileFromPathAsync(filename);
|
||||
|
||||
if (storageFile != null)
|
||||
{
|
||||
// mute the TextChanged handler to make for clean UI
|
||||
textBox.TextChanged -= TextBox_TextChanged;
|
||||
|
||||
_appFileName = storageFile.Path;
|
||||
UpdateToolBarAndUI(OpenRegistryFile(_appFileName));
|
||||
|
||||
// disable the Save button as it's a new file
|
||||
saveButton.IsEnabled = false;
|
||||
|
||||
// Restore the event handler as we're loaded
|
||||
textBox.TextChanged += TextBox_TextChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the currently opened file in place
|
||||
/// </summary>
|
||||
private void SaveButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveFile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses a picker to save out a copy of the current reg file
|
||||
/// </summary>
|
||||
private void SaveAsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Save out a new REG file and then open it - we have to use the direct Win32 method because FileOpenPicker crashes when it's
|
||||
// called while running as admin
|
||||
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(_mainWindow);
|
||||
string filename = SaveFilePicker.ShowDialog(
|
||||
windowHandle,
|
||||
resourceLoader.GetString("SuggestFileName"),
|
||||
resourceLoader.GetString("FilterRegistryName") + '\0' + "*.reg" + '\0' + resourceLoader.GetString("FilterAllFiles") + '\0' + "*.*" + '\0' + '\0',
|
||||
resourceLoader.GetString("SaveDialogTitle"));
|
||||
|
||||
if (filename == string.Empty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appFileName = filename;
|
||||
SaveFile();
|
||||
UpdateToolBarAndUI(OpenRegistryFile(_appFileName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reloads the current REG file from storage
|
||||
/// </summary>
|
||||
private void RefreshButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// mute the TextChanged handler to make for clean UI
|
||||
textBox.TextChanged -= TextBox_TextChanged;
|
||||
|
||||
// reload the current Registry file and update the toolbar accordingly.
|
||||
UpdateToolBarAndUI(OpenRegistryFile(_appFileName), true, true);
|
||||
|
||||
saveButton.IsEnabled = false;
|
||||
|
||||
// restore the TextChanged handler
|
||||
textBox.TextChanged += TextBox_TextChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the Registry Editor; UAC is handled by the request to open
|
||||
/// </summary>
|
||||
private void RegistryButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// pass in an empty string as we have no file to open
|
||||
OpenRegistryEditor(string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the Registry Editor and tries to set "last used"; UAC is handled by the request to open
|
||||
/// </summary>
|
||||
private void RegistryJumpToKeyButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Get the selected Key, if there is one
|
||||
TreeViewNode currentNode = treeView.SelectedNode;
|
||||
if (currentNode != null)
|
||||
{
|
||||
// since there is a valid node, get the FullPath of the key that was selected
|
||||
string key = ((RegistryKey)currentNode.Content).FullPath;
|
||||
|
||||
// it's impossible to directly open a key via command-line option, so we must override the last remember key
|
||||
Microsoft.Win32.Registry.SetValue(@"HKEY_Current_User\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit", "LastKey", key);
|
||||
}
|
||||
|
||||
// pass in an empty string as we have no file to open
|
||||
OpenRegistryEditor(string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges the currently saved file into the Registry Editor; UAC is handled by the request to open
|
||||
/// </summary>
|
||||
private async void WriteButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Check to see if the current file has been saved
|
||||
if (saveButton.IsEnabled)
|
||||
{
|
||||
ContentDialog contentDialog = new ContentDialog()
|
||||
{
|
||||
Title = resourceLoader.GetString("YesNoCancelDialogTitle"),
|
||||
Content = resourceLoader.GetString("YesNoCancelDialogContent"),
|
||||
PrimaryButtonText = resourceLoader.GetString("YesNoCancelDialogPrimaryButtonText"),
|
||||
SecondaryButtonText = resourceLoader.GetString("YesNoCancelDialogSecondaryButtonText"),
|
||||
CloseButtonText = resourceLoader.GetString("YesNoCancelDialogCloseButtonText"),
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
};
|
||||
|
||||
// Use this code to associate the dialog to the appropriate AppWindow by setting
|
||||
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
|
||||
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
|
||||
{
|
||||
contentDialog.XamlRoot = this.Content.XamlRoot;
|
||||
}
|
||||
|
||||
ContentDialogResult contentDialogResult = await contentDialog.ShowAsync();
|
||||
switch (contentDialogResult)
|
||||
{
|
||||
case ContentDialogResult.Primary:
|
||||
// Save, then continue the file open
|
||||
SaveFile();
|
||||
break;
|
||||
case ContentDialogResult.Secondary:
|
||||
// Don't save and continue the file open!
|
||||
saveButton.IsEnabled = false;
|
||||
break;
|
||||
default:
|
||||
// Don't open the new file!
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pass in the filename so we can edit the current file
|
||||
OpenRegistryEditor(_appFileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the currently saved file in the PC's default REG file editor (often Notepad)
|
||||
/// </summary>
|
||||
private void EditButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// use the REG file's filename and verb so we can respect the selected editor
|
||||
Process process = new Process();
|
||||
process.StartInfo.FileName = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", _appFileName);
|
||||
process.StartInfo.Verb = "Edit";
|
||||
process.StartInfo.UseShellExecute = true;
|
||||
|
||||
try
|
||||
{
|
||||
process.Start();
|
||||
}
|
||||
catch
|
||||
{
|
||||
ShowMessageBox(
|
||||
resourceLoader.GetString("ErrorDialogTitle"),
|
||||
resourceLoader.GetString("FileEditorError"),
|
||||
resourceLoader.GetString("OkButtonText"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trigger that fires when a node in treeView is clicked and which populates dataGrid
|
||||
/// Can also be fired from elsewhere in the code
|
||||
/// </summary>
|
||||
private void TreeView_ItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args)
|
||||
{
|
||||
TreeViewItemInvokedEventArgs localArgs = args as TreeViewItemInvokedEventArgs;
|
||||
TreeViewNode treeViewNode = null;
|
||||
|
||||
// if there are no args, the mouse didn't get clicked but we want to believe it did
|
||||
if (args != null)
|
||||
{
|
||||
treeViewNode = args.InvokedItem as TreeViewNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
treeViewNode = treeView.SelectedNode;
|
||||
}
|
||||
|
||||
// Update the toolbar button for the tree
|
||||
registryJumpToKeyButton.IsEnabled = CheckTreeForValidKey();
|
||||
|
||||
// Grab the object that has Registry data in it from the currently selected treeView node
|
||||
RegistryKey registryKey = (RegistryKey)treeViewNode.Content;
|
||||
|
||||
// no matter what happens, clear the ListView of items on each click
|
||||
ClearTable();
|
||||
|
||||
// if there's no ListView items stored for the selected node, dataGrid is clear so get out now
|
||||
if (registryKey.Tag == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if there WAS something in the Tag property, cast it to a list and Populate the ListView
|
||||
ArrayList arrayList = (ArrayList)registryKey.Tag;
|
||||
listRegistryValues = new List<RegistryValue>();
|
||||
|
||||
for (int i = 0; i < arrayList.Count; i++)
|
||||
{
|
||||
RegistryValue listViewItem = (RegistryValue)arrayList[i];
|
||||
listRegistryValues.Add(listViewItem);
|
||||
}
|
||||
|
||||
// create a new binding for dataGrid and reattach it, updating the rows
|
||||
Binding listRegistryValuesBinding = new Binding { Source = listRegistryValues };
|
||||
dataGrid.SetBinding(DataGrid.ItemsSourceProperty, listRegistryValuesBinding);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the text in textBox changes, reload treeView and possibly dataGrid and reset the save button
|
||||
/// </summary>
|
||||
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
RefreshRegistryFile();
|
||||
saveButton.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
<Page
|
||||
x:Class="RegistryPreviewUILib.RegistryPreviewMainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid
|
||||
x:Name="gridPreview"
|
||||
Grid.Row="1"
|
||||
Width="Auto"
|
||||
Height="Auto"
|
||||
Margin="12"
|
||||
x:FieldModifier="public"
|
||||
Loaded="GridPreview_Loaded"
|
||||
TabFocusNavigation="Cycle">
|
||||
<Grid.Resources>
|
||||
<Style x:Key="GridCardStyle" TargetType="Border">
|
||||
<Style.Setters>
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource OverlayCornerRadius}" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<Grid.ColumnDefinitions>
|
||||
<!-- Left, Splitter, Right -->
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<!-- CommandBar, Tree, Splitter, List -->
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="0,0,0,12"
|
||||
Style="{StaticResource GridCardStyle}">
|
||||
|
||||
<CommandBar
|
||||
Name="commandBar"
|
||||
HorizontalAlignment="Left"
|
||||
DefaultLabelPosition="Right">
|
||||
|
||||
<AppBarButton
|
||||
x:Name="openButton"
|
||||
x:Uid="OpenButton"
|
||||
Click="OpenButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="O" Modifiers="Control" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
x:Name="refreshButton"
|
||||
x:Uid="RefreshButton"
|
||||
Click="RefreshButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="F5" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarSeparator />
|
||||
<AppBarButton
|
||||
x:Name="saveButton"
|
||||
x:Uid="SaveButton"
|
||||
Click="SaveButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}"
|
||||
IsEnabled="False">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="S" Modifiers="Control" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
x:Name="saveAsButton"
|
||||
x:Uid="SaveAsButton"
|
||||
Click="SaveAsButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}"
|
||||
IsEnabled="True">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="S" Modifiers="Control,Shift" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarSeparator />
|
||||
<AppBarButton
|
||||
x:Name="editButton"
|
||||
x:Uid="EditButton"
|
||||
Click="EditButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="E" Modifiers="Control" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
x:Name="writeButton"
|
||||
x:Uid="WriteButton"
|
||||
Click="WriteButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="W" Modifiers="Control" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
x:Name="registryButton"
|
||||
x:Uid="RegistryButton"
|
||||
Click="RegistryButton_Click"
|
||||
Icon="{ui:FontIcon Glyph=}">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="R" Modifiers="Control" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
<AppBarButton
|
||||
x:Name="registryJumpToKeyButton"
|
||||
x:Uid="RegistryJumpToKeyButton"
|
||||
Click="RegistryJumpToKeyButton_Click"
|
||||
IsEnabled="True">
|
||||
<AppBarButton.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="R" Modifiers="Control,Shift" />
|
||||
</AppBarButton.KeyboardAccelerators>
|
||||
</AppBarButton>
|
||||
</CommandBar>
|
||||
</Border>
|
||||
|
||||
<TextBox
|
||||
x:Name="textBox"
|
||||
x:Uid="textBox"
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AcceptsReturn="True"
|
||||
CanBeScrollAnchor="False"
|
||||
CornerRadius="{StaticResource OverlayCornerRadius}"
|
||||
FontFamily="Cascadia Mono, Consolas, Courier New"
|
||||
IsSpellCheckEnabled="False"
|
||||
IsTabStop="True"
|
||||
IsTextPredictionEnabled="False"
|
||||
PlaceholderText="{Binding PlaceholderText}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Visible"
|
||||
ScrollViewer.IsHorizontalRailEnabled="True"
|
||||
ScrollViewer.IsVerticalRailEnabled="True"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Visible"
|
||||
TabIndex="0"
|
||||
TextWrapping="NoWrap" />
|
||||
|
||||
<Border
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Style="{StaticResource GridCardStyle}">
|
||||
<TreeView
|
||||
x:Name="treeView"
|
||||
AllowDrop="False"
|
||||
AllowFocusOnInteraction="True"
|
||||
CanDragItems="False"
|
||||
CanReorderItems="False"
|
||||
IsEnabled="True"
|
||||
IsTabStop="False"
|
||||
ItemInvoked="TreeView_ItemInvoked"
|
||||
ScrollViewer.BringIntoViewOnFocusChange="True"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Visible"
|
||||
ScrollViewer.HorizontalScrollMode="Enabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Visible"
|
||||
ScrollViewer.VerticalScrollMode="Auto"
|
||||
TabIndex="1">
|
||||
<TreeView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
IsTabStop="False"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Image
|
||||
MaxWidth="16"
|
||||
MaxHeight="16"
|
||||
Source="{Binding Path=Content.Image}"
|
||||
ToolTipService.ToolTip="{Binding Path=Content.ToolTipText}" />
|
||||
<TextBlock Text="{Binding Path=Content.Name}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
</TreeView>
|
||||
</Border>
|
||||
|
||||
<Border
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Style="{StaticResource GridCardStyle}">
|
||||
<tk7controls:DataGrid
|
||||
x:Name="dataGrid"
|
||||
AllowDrop="False"
|
||||
AreRowDetailsFrozen="True"
|
||||
AutoGenerateColumns="False"
|
||||
CanDrag="False"
|
||||
HeadersVisibility="Column"
|
||||
IsReadOnly="True"
|
||||
IsTabStop="true"
|
||||
ItemsSource="{x:Bind listRegistryValues}"
|
||||
RowDetailsVisibilityMode="Collapsed"
|
||||
SelectionMode="Single"
|
||||
TabIndex="2">
|
||||
<tk7controls:DataGrid.Columns>
|
||||
<tk7controls:DataGridTemplateColumn
|
||||
x:Uid="NameColumn"
|
||||
Width="Auto"
|
||||
IsReadOnly="True">
|
||||
<tk7controls:DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Image
|
||||
MaxWidth="16"
|
||||
MaxHeight="16"
|
||||
IsTabStop="False"
|
||||
Source="{Binding ImageUri}"
|
||||
ToolTipService.ToolTip="{Binding ToolTipText}" />
|
||||
<TextBlock
|
||||
IsTabStop="False"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{Binding Name}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</tk7controls:DataGridTemplateColumn.CellTemplate>
|
||||
</tk7controls:DataGridTemplateColumn>
|
||||
<tk7controls:DataGridTextColumn
|
||||
x:Uid="TypeColumn"
|
||||
Width="Auto"
|
||||
Binding="{Binding Type}"
|
||||
FontSize="{StaticResource CaptionTextBlockFontSize}" />
|
||||
<tk7controls:DataGridTextColumn
|
||||
x:Uid="ValueColumn"
|
||||
Width="Auto"
|
||||
Binding="{Binding Value}"
|
||||
FontSize="{StaticResource CaptionTextBlockFontSize}" />
|
||||
</tk7controls:DataGrid.Columns>
|
||||
</tk7controls:DataGrid>
|
||||
</Border>
|
||||
|
||||
<tkcontrols:GridSplitter
|
||||
x:Name="verticalSplitter"
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="3"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
IsTabStop="False" />
|
||||
<tkcontrols:GridSplitter
|
||||
x:Name="horizontalSplitter"
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
IsTabStop="False" />
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,55 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
public sealed partial class RegistryPreviewMainPage : Page
|
||||
{
|
||||
// Const values
|
||||
private const string REGISTRYHEADER4 = "regedit4";
|
||||
private const string REGISTRYHEADER5 = "windows registry editor version 5.00";
|
||||
private const string APPNAME = "RegistryPreview";
|
||||
private const string KEYIMAGE = "ms-appx:///Assets/RegistryPreview/folder32.png";
|
||||
private const string DELETEDKEYIMAGE = "ms-appx:///Assets/RegistryPreview/deleted-folder32.png";
|
||||
private const string ERRORIMAGE = "ms-appx:///Assets/RegistryPreview/error32.png";
|
||||
|
||||
// private members
|
||||
private ResourceLoader resourceLoader;
|
||||
private bool visualTreeReady;
|
||||
private Dictionary<string, TreeViewNode> mapRegistryKeys;
|
||||
private List<RegistryValue> listRegistryValues;
|
||||
|
||||
private UpdateWindowTitleFunction _updateWindowTitleFunction;
|
||||
private string _appFileName;
|
||||
private Window _mainWindow;
|
||||
|
||||
public RegistryPreviewMainPage(Window mainWindow, UpdateWindowTitleFunction updateWindowTitleFunction, string appFilename)
|
||||
{
|
||||
// TODO (stefan): check ctor
|
||||
this.InitializeComponent();
|
||||
|
||||
_mainWindow = mainWindow;
|
||||
_updateWindowTitleFunction = updateWindowTitleFunction;
|
||||
_appFileName = appFilename;
|
||||
|
||||
_mainWindow.Closed += MainWindow_Closed;
|
||||
|
||||
// Initialize the string table
|
||||
resourceLoader = ResourceLoaderInstance.ResourceLoader;
|
||||
|
||||
// Update Toolbar
|
||||
if ((_appFileName == null) || (File.Exists(_appFileName) != true))
|
||||
{
|
||||
UpdateToolBarAndUI(false);
|
||||
_updateWindowTitleFunction(resourceLoader.GetString("FileNotFound"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Condition="exists('..\..\..\Version.props')" Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net8.0-windows10.0.20348</TargetFramework>
|
||||
<RootNamespace>RegistryPreviewUILib</RootNamespace>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<AssemblyName>PowerToys.RegistryPreviewUILib</AssemblyName>
|
||||
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
|
||||
<ProjectPriFileName>PowerToys.RegistryPreviewUILib.pri</ProjectPriFileName>
|
||||
|
||||
<GenerateLibraryLayout>true</GenerateLibraryLayout>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(OutDir)\PowerToys.RegistryPreviewUILib.pri" Pack="True" PackageCopyToOutput="true" PackagePath="lib/$(TargetFramework)" />
|
||||
<None Include="$(OutDir)\PowerToys.RegistryPreviewUILib.pri" Pack="True" PackageCopyToOutput="True" PackagePath="contentFiles\any\$(TargetFramework)" />
|
||||
<XBFFile Include="$(OutDir)**\*.xbf" />
|
||||
<None Include="@(XBFFile)" Pack="True" PackageCopyToOutput="True" PackagePath="contentFiles\any\$(TargetFramework)" />
|
||||
<None Include="$(OutDir)\PowerToys.RegistryPreviewUILib.pdb" Pack="True" PackageCopyToOutput="true" PackagePath="lib/$(TargetFramework)" />
|
||||
|
||||
<None Include="Assets\**\*.png" Pack="true" PackageCopyToOutput="true" PackagePath="contentFiles\any\$(TargetFramework)\Assets" />
|
||||
<None Include="Assets\**\*.ico" Pack="true" PackageCopyToOutput="true" PackagePath="contentFiles\any\$(TargetFramework)\Assets" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Assets\**\*.png" Pack="false" />
|
||||
<Content Remove="Assets\**\*.ico" Pack="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\RegistryPreview\*">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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;
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
/// <summary>
|
||||
/// Class representing an each item in the list view, each one a Registry Value.
|
||||
/// </summary>
|
||||
public class RegistryValue
|
||||
{
|
||||
// Static members
|
||||
private static Uri uriStringValue = new Uri("ms-appx:///Assets/RegistryPreview/string32.png");
|
||||
private static Uri uriBinaryValue = new Uri("ms-appx:///Assets/RegistryPreview/data32.png");
|
||||
private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreview/deleted-value32.png");
|
||||
private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreview/error32.png");
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public string ToolTipText { get; set; }
|
||||
|
||||
public Uri ImageUri
|
||||
{
|
||||
// Based off the Type of the item, pass back the correct image Uri used by the Binding of the DataGrid
|
||||
get
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case "REG_SZ":
|
||||
case "REG_EXPAND_SZ":
|
||||
case "REG_MULTI_SZ":
|
||||
return uriStringValue;
|
||||
case "ERROR":
|
||||
return uriErrorValue;
|
||||
case "":
|
||||
return uriDeleteValue;
|
||||
}
|
||||
|
||||
return uriBinaryValue;
|
||||
}
|
||||
}
|
||||
|
||||
public RegistryValue(string name, string type, string value)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Type = type;
|
||||
this.Value = value;
|
||||
this.ToolTipText = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// 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.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
internal static class ResourceLoaderInstance
|
||||
{
|
||||
internal static ResourceLoader ResourceLoader { get; private set; }
|
||||
|
||||
static ResourceLoaderInstance()
|
||||
{
|
||||
ResourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("PowerToys.RegistryPreviewUILib.pri", "PowerToys.RegistryPreviewUILib/Resources");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// 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 RegistryPreviewUILib
|
||||
{
|
||||
// Workaround for File Pickers that don't work while running as admin, per:
|
||||
// https://github.com/microsoft/WindowsAppSDK/issues/2504
|
||||
public static partial class SaveFilePicker
|
||||
{
|
||||
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
private static extern bool GetSaveFileName(ref FileName saveFileName);
|
||||
|
||||
public static string ShowDialog(IntPtr windowHandle, string suggestedFilename, string filter, string dialogTitle)
|
||||
{
|
||||
FileName saveFileName = default(FileName);
|
||||
saveFileName.StructSize = Marshal.SizeOf(saveFileName);
|
||||
|
||||
saveFileName.HwndOwner = windowHandle;
|
||||
saveFileName.Filter = filter;
|
||||
saveFileName.File = new string(new char[256]);
|
||||
saveFileName.MaxFile = saveFileName.File.Length;
|
||||
saveFileName.File = string.Concat(suggestedFilename, saveFileName.File);
|
||||
saveFileName.FileTitle = new string(new char[64]);
|
||||
saveFileName.MaxFileTitle = saveFileName.FileTitle.Length;
|
||||
saveFileName.Title = dialogTitle;
|
||||
saveFileName.DefExt = "reg";
|
||||
|
||||
if (GetSaveFileName(ref saveFileName))
|
||||
{
|
||||
return saveFileName.File;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
<?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">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="EditButton.Label" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="ErrorDialogTitle" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="FileEditorError" xml:space="preserve">
|
||||
<value>The REG file editor could not be opened.</value>
|
||||
</data>
|
||||
<data name="FileNotFound" xml:space="preserve">
|
||||
<value>File was not found</value>
|
||||
</data>
|
||||
<data name="FileSaveError" xml:space="preserve">
|
||||
<value>The REG file cannot be written to.</value>
|
||||
</data>
|
||||
<data name="FilterAllFiles" xml:space="preserve">
|
||||
<value>All files (*.*)</value>
|
||||
</data>
|
||||
<data name="FilterRegistryName" xml:space="preserve">
|
||||
<value>Registry files (*.reg)</value>
|
||||
</data>
|
||||
<data name="InvalidBinary" xml:space="preserve">
|
||||
<value>(Invalid binary value)</value>
|
||||
</data>
|
||||
<data name="InvalidDword" xml:space="preserve">
|
||||
<value>(Invalid DWORD (32-bit) value)</value>
|
||||
</data>
|
||||
<data name="InvalidQword" xml:space="preserve">
|
||||
<value>(Invalid QWORD (64-bit) value)</value>
|
||||
</data>
|
||||
<data name="InvalidRegistryFile" xml:space="preserve">
|
||||
<value> appears to be an invalid registry file.</value>
|
||||
</data>
|
||||
<data name="InvalidRegistryFileTitle" xml:space="preserve">
|
||||
<value>File was not a Registry file</value>
|
||||
</data>
|
||||
<data name="InvalidString" xml:space="preserve">
|
||||
<value>(Invalid string value)</value>
|
||||
</data>
|
||||
<data name="LargeRegistryFile" xml:space="preserve">
|
||||
<value> is larger than 10MB which is too large for this application.</value>
|
||||
</data>
|
||||
<data name="LargeRegistryFileTitle" xml:space="preserve">
|
||||
<value>File is too large</value>
|
||||
</data>
|
||||
<data name="NameColumn.Header" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="NoNodesFoundInFile" xml:space="preserve">
|
||||
<value>No valid Keys were found</value>
|
||||
</data>
|
||||
<data name="OkButtonText" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
<comment>as on the OK button</comment>
|
||||
</data>
|
||||
<data name="OpenButton.Label" xml:space="preserve">
|
||||
<value>Open…</value>
|
||||
</data>
|
||||
<data name="OpenDialogTitle" xml:space="preserve">
|
||||
<value>Open Registry file</value>
|
||||
</data>
|
||||
<data name="RefreshButton.Label" xml:space="preserve">
|
||||
<value>Reload</value>
|
||||
</data>
|
||||
<data name="RegistryButton.Label" xml:space="preserve">
|
||||
<value>Open Registry Editor</value>
|
||||
</data>
|
||||
<data name="RegistryJumpToKeyButton.Label" xml:space="preserve">
|
||||
<value>Open Key</value>
|
||||
</data>
|
||||
<data name="SaveDialogTitle" xml:space="preserve">
|
||||
<value>Save As</value>
|
||||
</data>
|
||||
<data name="SaveAsButton.Label" xml:space="preserve">
|
||||
<value>Save as…</value>
|
||||
</data>
|
||||
<data name="SaveButton.Label" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="SuggestFileName" xml:space="preserve">
|
||||
<value>New Registry file</value>
|
||||
</data>
|
||||
<data name="textBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Registry file text will appear here</value>
|
||||
</data>
|
||||
<data name="titleBarText.ApplicationTitle" xml:space="preserve">
|
||||
<value>Registry Preview</value>
|
||||
</data>
|
||||
<data name="ToolTipAddedKey" xml:space="preserve">
|
||||
<value>Key will be added, if needed</value>
|
||||
</data>
|
||||
<data name="ToolTipBinaryValue" xml:space="preserve">
|
||||
<value>Binary value will be updated</value>
|
||||
</data>
|
||||
<data name="ToolTipDeletedKey" xml:space="preserve">
|
||||
<value>Key will be deleted</value>
|
||||
</data>
|
||||
<data name="ToolTipDeletedValue" xml:space="preserve">
|
||||
<value>Value will be deleted</value>
|
||||
</data>
|
||||
<data name="ToolTipErrorKey" xml:space="preserve">
|
||||
<value>Key couldn't be parsed</value>
|
||||
</data>
|
||||
<data name="ToolTipErrorValue" xml:space="preserve">
|
||||
<value>Value has a syntax error</value>
|
||||
</data>
|
||||
<data name="ToolTipStringValue" xml:space="preserve">
|
||||
<value>String value will be updated</value>
|
||||
</data>
|
||||
<data name="TypeColumn.Header" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
<comment>noun, as in "a type of..."</comment>
|
||||
</data>
|
||||
<data name="UACDialogError" xml:space="preserve">
|
||||
<value>Click Yes on the User Account Control dialog to run the application.</value>
|
||||
</data>
|
||||
<data name="UACDialogTitle" xml:space="preserve">
|
||||
<value>User Account Control</value>
|
||||
</data>
|
||||
<data name="ValueColumn.Header" xml:space="preserve">
|
||||
<value>Data</value>
|
||||
</data>
|
||||
<data name="WriteButton.Label" xml:space="preserve">
|
||||
<value>Write to Registry</value>
|
||||
</data>
|
||||
<data name="YesNoCancelDialogCloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="YesNoCancelDialogContent" xml:space="preserve">
|
||||
<value>Save changes?</value>
|
||||
</data>
|
||||
<data name="YesNoCancelDialogPrimaryButtonText" xml:space="preserve">
|
||||
<value>Save</value>
|
||||
</data>
|
||||
<data name="YesNoCancelDialogSecondaryButtonText" xml:space="preserve">
|
||||
<value>Don't save</value>
|
||||
</data>
|
||||
<data name="YesNoCancelDialogTitle" xml:space="preserve">
|
||||
<value>Registry Preview</value>
|
||||
</data>
|
||||
<data name="ZeroLength" xml:space="preserve">
|
||||
<value>(zero-length binary value)</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="RegistryPreview.app"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||