├── _config.yml
├── wv2util
├── .gitignore
├── logo.ico
├── assets
│ ├── toolbox.ico
│ ├── toolbox.pdn
│ ├── toolbox.png
│ ├── wrench.ico
│ ├── wrench.pdn
│ ├── wrench.png
│ └── attributions.txt
├── wv2util_TemporaryKey.pfx
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Pages
│ ├── IReloadable.cs
│ ├── IShowHostAppEntryAsAppOverrideEntry.cs
│ ├── ExperimentsPage.xaml.cs
│ ├── ReloadableHost.cs
│ ├── ExperimentsPage.xaml
│ ├── AboutPage.xaml
│ ├── RuntimesPage.xaml.cs
│ ├── RuntimesPage.xaml
│ ├── AppOverridesPage.xaml.cs
│ ├── AboutPage.xaml.cs
│ └── HostAppsPage.xaml.cs
├── App.xaml
├── NullToBooleanConverter.cs
├── TextComboBox.cs
├── App.config
├── wv2util.csproj.user
├── TraceWindow.xaml.cs
├── AppState.cs
├── TraceWindow.xaml
├── VersionUtil.cs
├── wv2util.sln
├── MainWindow.xaml.cs
├── App.xaml.cs
├── CreateReportWindow.xaml
├── RegistryUtil.cs
├── app.manifest
├── CommandLineUtil.cs
├── SortUtil.cs
├── MainWindow.xaml
├── TreeItem.cs
├── CreateReportWindow.xaml.cs
├── HwndUtil.cs
└── ObservableCollectionProjection.cs
├── .gitattributes
├── screenshot.png
├── install
├── setup.exe
├── Application Files
│ ├── WebView2Utilities_1_0_0_13
│ │ ├── logo.ico.deploy
│ │ ├── WebView2Utilities.exe.deploy
│ │ ├── WebView2Utilities.exe.config.deploy
│ │ ├── WebView2Utilities.application
│ │ └── WebView2Utilities.exe.manifest
│ ├── WebView2Utilities_1_0_0_14
│ │ ├── logo.ico.deploy
│ │ ├── WebView2Utilities.exe.deploy
│ │ ├── WebView2Utilities.exe.config.deploy
│ │ ├── WebView2Utilities.application
│ │ └── WebView2Utilities.exe.manifest
│ ├── WebView2Utilities_1_0_0_15
│ │ ├── logo.ico.deploy
│ │ ├── Validation.dll.deploy
│ │ ├── PInvoke.User32.dll.deploy
│ │ ├── System.Buffers.dll.deploy
│ │ ├── System.Memory.dll.deploy
│ │ ├── PInvoke.AdvApi32.dll.deploy
│ │ ├── PInvoke.Kernel32.dll.deploy
│ │ ├── System.Text.Json.dll.deploy
│ │ ├── System.ValueTuple.dll.deploy
│ │ ├── WebView2Utilities.exe.deploy
│ │ ├── PInvoke.Windows.Core.dll.deploy
│ │ ├── System.Numerics.Vectors.dll.deploy
│ │ ├── System.Text.Encodings.Web.dll.deploy
│ │ ├── Microsoft.Bcl.AsyncInterfaces.dll.deploy
│ │ ├── PInvoke.Windows.ShellScalingApi.dll.deploy
│ │ ├── System.Threading.Tasks.Extensions.dll.deploy
│ │ ├── System.Runtime.CompilerServices.Unsafe.dll.deploy
│ │ ├── WebView2Utilities.exe.config.deploy
│ │ └── WebView2Utilities.application
│ ├── WebView2Utilities_1_0_0_16
│ │ ├── logo.ico.deploy
│ │ ├── Validation.dll.deploy
│ │ ├── PInvoke.User32.dll.deploy
│ │ ├── System.Buffers.dll.deploy
│ │ ├── System.Memory.dll.deploy
│ │ ├── PInvoke.AdvApi32.dll.deploy
│ │ ├── PInvoke.Kernel32.dll.deploy
│ │ ├── System.Text.Json.dll.deploy
│ │ ├── System.ValueTuple.dll.deploy
│ │ ├── WebView2Utilities.exe.deploy
│ │ ├── PInvoke.Windows.Core.dll.deploy
│ │ ├── System.Numerics.Vectors.dll.deploy
│ │ ├── System.Text.Encodings.Web.dll.deploy
│ │ ├── Microsoft.Bcl.AsyncInterfaces.dll.deploy
│ │ ├── PInvoke.Windows.ShellScalingApi.dll.deploy
│ │ ├── System.Threading.Tasks.Extensions.dll.deploy
│ │ ├── System.Runtime.CompilerServices.Unsafe.dll.deploy
│ │ ├── WebView2Utilities.exe.config.deploy
│ │ └── WebView2Utilities.application
│ ├── WebView2Utilities_1_0_0_17
│ │ ├── logo.ico.deploy
│ │ ├── Validation.dll.deploy
│ │ ├── PInvoke.User32.dll.deploy
│ │ ├── System.Buffers.dll.deploy
│ │ ├── System.Memory.dll.deploy
│ │ ├── PInvoke.AdvApi32.dll.deploy
│ │ ├── PInvoke.Kernel32.dll.deploy
│ │ ├── System.Text.Json.dll.deploy
│ │ ├── System.ValueTuple.dll.deploy
│ │ ├── WebView2Utilities.exe.deploy
│ │ ├── PInvoke.Windows.Core.dll.deploy
│ │ ├── System.Numerics.Vectors.dll.deploy
│ │ ├── System.Text.Encodings.Web.dll.deploy
│ │ ├── Microsoft.Bcl.AsyncInterfaces.dll.deploy
│ │ ├── PInvoke.Windows.ShellScalingApi.dll.deploy
│ │ ├── System.Threading.Tasks.Extensions.dll.deploy
│ │ ├── System.Runtime.CompilerServices.Unsafe.dll.deploy
│ │ ├── WebView2Utilities.exe.config.deploy
│ │ └── WebView2Utilities.application
│ └── WebView2Utilities_1_0_0_18
│ │ ├── logo.ico.deploy
│ │ ├── Markdig.dll.deploy
│ │ ├── Markdig.Wpf.dll.deploy
│ │ ├── Validation.dll.deploy
│ │ ├── PInvoke.User32.dll.deploy
│ │ ├── System.Buffers.dll.deploy
│ │ ├── System.Memory.dll.deploy
│ │ ├── Newtonsoft.Json.dll.deploy
│ │ ├── PInvoke.AdvApi32.dll.deploy
│ │ ├── PInvoke.Kernel32.dll.deploy
│ │ ├── System.Text.Json.dll.deploy
│ │ ├── System.ValueTuple.dll.deploy
│ │ ├── WebView2Utilities.exe.deploy
│ │ ├── PInvoke.Windows.Core.dll.deploy
│ │ ├── System.Numerics.Vectors.dll.deploy
│ │ ├── System.Text.Encodings.Web.dll.deploy
│ │ ├── Microsoft.Bcl.AsyncInterfaces.dll.deploy
│ │ ├── PInvoke.Windows.ShellScalingApi.dll.deploy
│ │ ├── System.Threading.Tasks.Extensions.dll.deploy
│ │ ├── System.Runtime.CompilerServices.Unsafe.dll.deploy
│ │ ├── WebView2Utilities.exe.config.deploy
│ │ └── WebView2Utilities.application
└── WebView2Utilities.application
├── CODE_OF_CONDUCT.md
├── SUPPORT.md
├── wv2utilTests
├── app.config
├── Properties
│ └── AssemblyInfo.cs
├── CommandLineUtilTests.cs
├── ObservableCollectionProjectionTests.cs
├── ReportCreatorTests.cs
└── wv2utilTests.csproj
├── LICENSE
├── .github
└── workflows
│ └── ci.yml
├── SECURITY.md
├── CONTRIBUTING.md
└── README.md
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/wv2util/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | obj/
3 | bin/
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | install/* binary
2 | install/**/* binary
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/screenshot.png
--------------------------------------------------------------------------------
/wv2util/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/logo.ico
--------------------------------------------------------------------------------
/install/setup.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/setup.exe
--------------------------------------------------------------------------------
/wv2util/assets/toolbox.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/assets/toolbox.ico
--------------------------------------------------------------------------------
/wv2util/assets/toolbox.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/assets/toolbox.pdn
--------------------------------------------------------------------------------
/wv2util/assets/toolbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/assets/toolbox.png
--------------------------------------------------------------------------------
/wv2util/assets/wrench.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/assets/wrench.ico
--------------------------------------------------------------------------------
/wv2util/assets/wrench.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/assets/wrench.pdn
--------------------------------------------------------------------------------
/wv2util/assets/wrench.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/assets/wrench.png
--------------------------------------------------------------------------------
/wv2util/wv2util_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/wv2util/wv2util_TemporaryKey.pfx
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_13/logo.ico.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_13/logo.ico.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_14/logo.ico.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_14/logo.ico.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/logo.ico.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/logo.ico.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/logo.ico.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/logo.ico.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/logo.ico.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/logo.ico.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/logo.ico.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/logo.ico.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/Markdig.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/Markdig.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/Validation.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/Validation.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/Validation.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/Validation.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/Validation.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/Validation.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/Markdig.Wpf.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/Markdig.Wpf.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/Validation.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/Validation.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.User32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.User32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Buffers.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Buffers.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Memory.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Memory.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.User32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.User32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Buffers.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Buffers.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Memory.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Memory.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.User32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.User32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Buffers.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Buffers.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Memory.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Memory.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.User32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.User32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Buffers.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Buffers.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Memory.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Memory.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_13/WebView2Utilities.exe.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_13/WebView2Utilities.exe.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_14/WebView2Utilities.exe.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_14/WebView2Utilities.exe.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.AdvApi32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.AdvApi32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.Kernel32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.Kernel32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Text.Json.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Text.Json.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.ValueTuple.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.ValueTuple.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/WebView2Utilities.exe.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/WebView2Utilities.exe.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.AdvApi32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.AdvApi32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.Kernel32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.Kernel32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Text.Json.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Text.Json.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.ValueTuple.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.ValueTuple.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/WebView2Utilities.exe.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/WebView2Utilities.exe.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.AdvApi32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.AdvApi32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.Kernel32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.Kernel32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Text.Json.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Text.Json.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.ValueTuple.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.ValueTuple.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/WebView2Utilities.exe.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/WebView2Utilities.exe.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/Newtonsoft.Json.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/Newtonsoft.Json.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.AdvApi32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.AdvApi32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.Kernel32.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.Kernel32.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Text.Json.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Text.Json.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.ValueTuple.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.ValueTuple.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/WebView2Utilities.exe.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/WebView2Utilities.exe.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.Windows.Core.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.Windows.Core.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.Windows.Core.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.Windows.Core.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.Windows.Core.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.Windows.Core.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.Windows.Core.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.Windows.Core.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Numerics.Vectors.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Numerics.Vectors.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Numerics.Vectors.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Numerics.Vectors.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Numerics.Vectors.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Numerics.Vectors.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Numerics.Vectors.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Numerics.Vectors.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Text.Encodings.Web.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Text.Encodings.Web.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Text.Encodings.Web.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Text.Encodings.Web.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Text.Encodings.Web.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Text.Encodings.Web.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Text.Encodings.Web.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Text.Encodings.Web.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/Microsoft.Bcl.AsyncInterfaces.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/Microsoft.Bcl.AsyncInterfaces.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/Microsoft.Bcl.AsyncInterfaces.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/Microsoft.Bcl.AsyncInterfaces.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/Microsoft.Bcl.AsyncInterfaces.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/Microsoft.Bcl.AsyncInterfaces.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/Microsoft.Bcl.AsyncInterfaces.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/Microsoft.Bcl.AsyncInterfaces.dll.deploy
--------------------------------------------------------------------------------
/wv2util/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.Windows.ShellScalingApi.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/PInvoke.Windows.ShellScalingApi.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.Windows.ShellScalingApi.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/PInvoke.Windows.ShellScalingApi.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.Windows.ShellScalingApi.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/PInvoke.Windows.ShellScalingApi.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.Windows.ShellScalingApi.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/PInvoke.Windows.ShellScalingApi.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Threading.Tasks.Extensions.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Threading.Tasks.Extensions.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Threading.Tasks.Extensions.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Threading.Tasks.Extensions.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Threading.Tasks.Extensions.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Threading.Tasks.Extensions.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Threading.Tasks.Extensions.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Threading.Tasks.Extensions.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/System.Runtime.CompilerServices.Unsafe.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_15/System.Runtime.CompilerServices.Unsafe.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/System.Runtime.CompilerServices.Unsafe.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_16/System.Runtime.CompilerServices.Unsafe.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/System.Runtime.CompilerServices.Unsafe.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_17/System.Runtime.CompilerServices.Unsafe.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/System.Runtime.CompilerServices.Unsafe.dll.deploy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/david-risney/WebView2Utilities/HEAD/install/Application Files/WebView2Utilities_1_0_0_18/System.Runtime.CompilerServices.Unsafe.dll.deploy
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_14/WebView2Utilities.exe.config.deploy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_13/WebView2Utilities.exe.config.deploy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/wv2util/assets/attributions.txt:
--------------------------------------------------------------------------------
1 | The wrench and toolbox icons are from the Fluent UI Icons project: https://developer.microsoft.com/en-us/fluentui#/styles/web/icons
2 | The wrench icon is called "Repair" and the toolbox icon is called "Toolbox"
3 |
4 | They can also be obtained from https://github.com/microsoft/fluentui-system-icons/blob/main/icons_regular.md
--------------------------------------------------------------------------------
/wv2util/Pages/IReloadable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace wv2util
8 | {
9 | public interface IReloadable
10 | {
11 | void Reload();
12 | bool Reloading { get; }
13 |
14 | event EventHandler ReloadingChanged;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/wv2util/Pages/IShowHostAppEntryAsAppOverrideEntry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace wv2util
8 | {
9 | public interface IShowHostAppEntryAsAppOverrideEntry
10 | {
11 | void ShowHostAppEntryAsAppOverrideEntry(HostAppEntry entry);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/wv2util/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # Support
2 |
3 | ## How to file issues and get help
4 |
5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing
6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or
7 | feature request as a new Issue.
8 |
9 | For help and questions about using this project, please create a GitHub issue and add a "question" label.
10 |
11 | ## Microsoft Support Policy
12 |
13 | Support for **WebView2Utilities** is limited to the resources listed above.
--------------------------------------------------------------------------------
/wv2utilTests/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/wv2util/Pages/ExperimentsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace wv2util
17 | {
18 | ///
19 | /// Interaction logic for ExperimentsPage.xaml
20 | ///
21 | public partial class ExperimentsPage : Page
22 | {
23 | public ExperimentsPage()
24 | {
25 | InitializeComponent();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/wv2util/NullToBooleanConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows.Data;
8 |
9 | namespace wv2util
10 | {
11 | public class NullToBooleanConverter : IValueConverter
12 | {
13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
14 | {
15 | if (value == null)
16 | {
17 | return false;
18 | }
19 | return true;
20 | }
21 |
22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
23 | {
24 | throw new NotImplementedException();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/wv2util/TextComboBox.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Specialized;
2 | using System.Windows.Controls;
3 |
4 | namespace wv2util
5 | {
6 | public class TextComboBox : System.Windows.Controls.ComboBox
7 | {
8 | private bool m_ignore = false;
9 | protected override void OnSelectionChanged(SelectionChangedEventArgs e)
10 | {
11 | if (!m_ignore)
12 | {
13 | base.OnSelectionChanged(e);
14 | }
15 | }
16 |
17 | protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
18 | {
19 | m_ignore = true;
20 | try
21 | {
22 | base.OnItemsChanged(e);
23 | }
24 | finally
25 | {
26 | m_ignore = false;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/wv2util/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/wv2util/wv2util.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ..\install\
5 | https://david-risney.github.io/WebView2Utilities/install/
6 | https://github.com/david-risney/WebView2Utilities/
7 |
8 |
9 | https://david-risney.github.io/WebView2Utilities/
10 | en-US
11 | false
12 |
13 |
14 | false
15 |
16 |
--------------------------------------------------------------------------------
/wv2util/TraceWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 |
15 | namespace wv2util
16 | {
17 | ///
18 | /// Interaction logic for TraceWindow.xaml
19 | ///
20 | public partial class TraceWindow : Window
21 | {
22 | public TraceWindow()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | private void FinishButton_Click(object sender, RoutedEventArgs e)
28 | {
29 |
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/WebView2Utilities.exe.config.deploy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/WebView2Utilities.exe.config.deploy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/WebView2Utilities.exe.config.deploy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/WebView2Utilities.exe.config.deploy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 David Risney
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/wv2util/AppState.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 |
3 | namespace wv2util
4 | {
5 | public class AppState
6 | {
7 | private static AppOverrideList s_AppOverrideList = new AppOverrideList();
8 | public static AppOverrideList GetAppOverrideList() => s_AppOverrideList;
9 |
10 | private static RuntimeList s_RuntimeList = new RuntimeList();
11 | public static RuntimeList GetRuntimeList() => s_RuntimeList;
12 |
13 | private static HostAppList s_HostAppList = new HostAppList();
14 | public static HostAppList GetHostAppList() => s_HostAppList;
15 |
16 | private static ObservableCollection s_hostAppTreeItems = new ObservableCollectionProjection(
17 | GetHostAppList(),
18 | i => new HostAppEntryTreeItem(GetHostAppList(), i));
19 | public static ObservableCollection GetHostAppTree() => s_hostAppTreeItems;
20 |
21 | private static ExperimentalFeatureList s_ExperimentalFeatureList = new ExperimentalFeatureList();
22 | public static ExperimentalFeatureList GetExperimentalFeatureList() => s_ExperimentalFeatureList;
23 | }
24 | }
--------------------------------------------------------------------------------
/wv2util/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace wv2util.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/wv2util/Pages/ReloadableHost.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Controls;
7 |
8 | namespace wv2util.Pages
9 | {
10 | public class ReloadableHost
11 | {
12 | private Button m_button;
13 | private IReloadable m_reloadable;
14 |
15 | public ReloadableHost(Button button, IReloadable reloadable)
16 | {
17 | m_button = button;
18 | m_reloadable = reloadable;
19 |
20 | m_reloadable.ReloadingChanged += OnReloadingChanged;
21 | m_button.Click += OnButtonClick;
22 | }
23 |
24 | private void OnButtonClick(object sender, System.Windows.RoutedEventArgs e)
25 | {
26 | if (!m_reloadable.Reloading)
27 | {
28 | m_reloadable.Reload();
29 | }
30 | }
31 |
32 | private void OnReloadingChanged(object sender, EventArgs e)
33 | {
34 | // Get back to UI thread
35 | m_button.Dispatcher.Invoke(() =>
36 | {
37 | if (m_reloadable.Reloading)
38 | {
39 | m_button.Content = "⌚";
40 | m_button.IsEnabled = false;
41 | }
42 | else
43 | {
44 | m_button.Content = "🔃";
45 | m_button.IsEnabled = true;
46 | }
47 | });
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/wv2utilTests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("wv2utilTests")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("wv2utilTests")]
12 | [assembly: AssemblyCopyright("Copyright © 2022")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("d5570f16-2715-4559-9081-f1ef68c4a961")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/wv2util/TraceWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/wv2util/VersionUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Reflection;
4 |
5 | namespace wv2util
6 | {
7 | public static class VersionUtil
8 | {
9 | public static FileVersionInfo TryGetVersionFromFilePath(string filePath)
10 | {
11 | if (filePath != "" && filePath != null)
12 | {
13 | try
14 | {
15 | return FileVersionInfo.GetVersionInfo(filePath);
16 | }
17 | catch (Exception)
18 | {
19 | }
20 | }
21 | return null;
22 | }
23 |
24 | public static string GetVersionStringFromFilePath(string filePath)
25 | {
26 | if (filePath != "" && filePath != null)
27 | {
28 | try
29 | {
30 | return FileVersionInfo.GetVersionInfo(filePath).FileVersion;
31 | }
32 | catch (System.IO.FileNotFoundException)
33 | {
34 | return "File not found";
35 | }
36 | catch (System.ArgumentException)
37 | {
38 | return "File not found";
39 | }
40 | }
41 | return "Unknown";
42 |
43 | }
44 |
45 | public static string GetWebView2UtilitiesVersion()
46 | {
47 | return Assembly.GetExecutingAssembly().GetName().Version.ToString();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/wv2util/wv2util.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32825.248
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wv2util", "wv2util.csproj", "{3B31D688-B3A2-435A-9D52-4B089821AE6F}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wv2utilTests", "..\wv2utilTests\wv2utilTests.csproj", "{D5570F16-2715-4559-9081-F1EF68C4A961}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {3B31D688-B3A2-435A-9D52-4B089821AE6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {3B31D688-B3A2-435A-9D52-4B089821AE6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {3B31D688-B3A2-435A-9D52-4B089821AE6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {3B31D688-B3A2-435A-9D52-4B089821AE6F}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {D5570F16-2715-4559-9081-F1EF68C4A961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {D5570F16-2715-4559-9081-F1EF68C4A961}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {D5570F16-2715-4559-9081-F1EF68C4A961}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {D5570F16-2715-4559-9081-F1EF68C4A961}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {8A7C84F9-E75F-4F00-BA0C-CDB75251BFF8}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/wv2util/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Markdig.Wpf;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Net.Http;
7 | using System.Text.Json;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Automation.Peers;
12 | using System.Windows.Automation.Provider;
13 | using System.Windows.Controls;
14 | using System.Windows.Documents;
15 | using System.Windows.Navigation;
16 | using System.Windows.Threading;
17 | using Clipboard = System.Windows.Clipboard;
18 | using ElapsedEventArgs = System.Timers.ElapsedEventArgs;
19 | using FolderBrowserDialog = System.Windows.Forms.FolderBrowserDialog;
20 | using Timer = System.Timers.Timer;
21 | using System.Windows.Input;
22 | using System.Collections.ObjectModel;
23 | using wv2util.Pages;
24 |
25 | namespace wv2util
26 | {
27 | ///
28 | /// Interaction logic for AppOverride.xaml
29 | ///
30 | public partial class MainWindow : Window, IShowHostAppEntryAsAppOverrideEntry
31 | {
32 | public MainWindow()
33 | {
34 | InitializeComponent();
35 |
36 | // ReloadableHost connects up the reload button in the main page to the reloadable page
37 | new ReloadableHost(this.HostAppsReload, this.HostAppsPage);
38 | new ReloadableHost(this.RuntimesReload, this.RuntimesPage);
39 | new ReloadableHost(this.AppOverridesReload, this.AppOverridesPage);
40 | }
41 |
42 | public void ShowHostAppEntryAsAppOverrideEntry(HostAppEntry entry)
43 | {
44 | this.AppOverridesPage.ShowHostAppEntryAsAppOverrideEntry(entry);
45 | this.TabControl.SelectedItem = this.AppOverridesTab;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/wv2util/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Reflection;
4 | using System.Security.Principal;
5 | using System.Windows;
6 |
7 | namespace wv2util
8 | {
9 | ///
10 | /// Interaction logic for App.xaml
11 | ///
12 | public partial class App : Application
13 | {
14 | public App()
15 | {
16 | // ClickOnce doesn't support marking the app as requiring adminstrator in the manifest.
17 | // So we check at runtime and rerun ourselves as admin.
18 | if (!IsRunAsAdministrator())
19 | {
20 | ProcessStartInfo processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase)
21 | {
22 |
23 | // The following properties run the new process as administrator
24 | UseShellExecute = true,
25 | Verb = "runas"
26 | };
27 |
28 | // Start the new process
29 | try
30 | {
31 | Process.Start(processInfo);
32 | }
33 | catch (Exception)
34 | {
35 | // The user did not allow the application to run as administrator
36 | MessageBox.Show("Sorry, this application must be run as Administrator.");
37 | }
38 |
39 | // Shut down the current process
40 | Application.Current.Shutdown();
41 | }
42 | }
43 |
44 | private bool IsRunAsAdministrator()
45 | {
46 | WindowsIdentity wi = WindowsIdentity.GetCurrent();
47 | WindowsPrincipal wp = new WindowsPrincipal(wi);
48 |
49 | return wp.IsInRole(WindowsBuiltInRole.Administrator);
50 | }
51 | }
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # This continuous integration pipeline is triggered anytime a user pushes code to the repo.
5 | # This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
6 | name: Wpf Continuous Integration
7 |
8 | # Trigger on every main branch push and pull request
9 | on:
10 | push:
11 | branches:
12 | - main
13 | pull_request:
14 | branches:
15 | - main
16 |
17 | jobs:
18 |
19 | build:
20 |
21 | strategy:
22 | matrix:
23 | targetplatform: [x86, x64]
24 |
25 | runs-on: windows-latest
26 |
27 | env:
28 | SigningCertificate: wv2util\wv2util_TemporaryKey.pfx
29 | Solution_Path: wv2util\wv2util.sln
30 | Test_Dll_Path: wv2utilTests\bin\Debug\wv2utilTests.dll
31 | Wpf_Project_Path: wv2util\wv2util.csproj
32 | Actions_Allow_Unsecure_Commands: true # Allows AddPath and SetEnv commands
33 |
34 | steps:
35 | - name: Checkout
36 | uses: actions/checkout@v2
37 | with:
38 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
39 |
40 | # Install the .NET Core workload
41 | - name: Install .NET Core
42 | uses: actions/setup-dotnet@v3
43 | with:
44 | dotnet-version: '6.0.x'
45 |
46 | # Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
47 | - name: Setup MSBuild.exe
48 | uses: microsoft/setup-msbuild@v1.1
49 |
50 | # Restore and rebuild the application
51 | - name: Restore the Wpf application to populate the obj folder
52 | run: msbuild $env:Solution_Path /t:Restore,Rebuild /p:Configuration=$env:Configuration
53 | env:
54 | Configuration: Debug
55 | # RuntimeIdentifier: win-${{ matrix.targetplatform }}
56 |
57 | # Test
58 | - name: Execute Unit Tests
59 | run: dotnet test $env:Test_Dll_Path
60 |
--------------------------------------------------------------------------------
/wv2util/Pages/ExperimentsPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Name
19 |
20 |
21 | Enabled
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Description
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/wv2utilTests/CommandLineUtilTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 |
3 | namespace wv2util.Tests
4 | {
5 | [TestClass()]
6 | public class CommandLineUtilTests
7 | {
8 | [TestMethod()]
9 | public void ParseCommandLineRealWorldTest()
10 | {
11 | var results = (new CommandLineUtil.CommandLine("\"C:\\Program Files (x86)\\Microsoft\\EdgeWebView\\Application\\105.0.1343.42\\msedgewebview2.exe\" --embedded-browser-webview=1 --webview-exe-name=WebViewHost.exe --webview-exe-version=17.3.34-main --user-data-dir=\"C:\\Users\\dave\\AppData\\Local\\Temp\\VSWebView2Cache\\e8b5e6f0-42d7-422d-bc0c-f775d2716453\\EBWebView\" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --allow-file-access-from-files --mojo-named-platform-channel-pipe=40932.32536.5816090101267860823")).Parts;
12 |
13 | int idx = 0;
14 | Assert.AreEqual(results[idx++], "C:\\Program Files (x86)\\Microsoft\\EdgeWebView\\Application\\105.0.1343.42\\msedgewebview2.exe");
15 | Assert.AreEqual(results[idx++], "--embedded-browser-webview=1");
16 | Assert.AreEqual(results[idx++], "--webview-exe-name=WebViewHost.exe");
17 | Assert.AreEqual(results[idx++], "--webview-exe-version=17.3.34-main");
18 | Assert.AreEqual(results[idx++], "--user-data-dir=C:\\Users\\dave\\AppData\\Local\\Temp\\VSWebView2Cache\\e8b5e6f0-42d7-422d-bc0c-f775d2716453\\EBWebView");
19 | Assert.AreEqual(results[idx++], "--noerrdialogs");
20 | Assert.AreEqual(results[idx++], "--embedded-browser-webview-dpi-awareness=2");
21 | Assert.AreEqual(results[idx++], "--allow-file-access-from-files");
22 | Assert.AreEqual(results[idx++], "--mojo-named-platform-channel-pipe=40932.32536.5816090101267860823");
23 | }
24 |
25 | [TestMethod()]
26 | public void ParseCommandLineUserDataDirWithSpaceTest()
27 | {
28 | var results = (new CommandLineUtil.CommandLine("msedgewebview2.exe --user-data-dir=\"C:\\Users\\dave exa\\mple\\example\\EBWebView\"")).Parts;
29 |
30 | int idx = 0;
31 | Assert.AreEqual(results[idx++], "msedgewebview2.exe");
32 | Assert.AreEqual(results[idx++], "--user-data-dir=C:\\Users\\dave exa\\mple\\example\\EBWebView");
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/install/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 1EzHqFVMg1g3CwxzmST1sJsYGGLSlXlDkxFTIijXSkI=
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_16/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Z9b/o0tO7GhAP83wyrSaLeBf8RVXVpuf53X/F/o+Rug=
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_17/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | EkPty13BWGmJon1t+6Qf08ogIRYZltPNu7UpszSwqGE=
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_18/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 1EzHqFVMg1g3CwxzmST1sJsYGGLSlXlDkxFTIijXSkI=
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_15/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | muK26/j9osmd3UIzWrnF9EBUwnZO11HW4aX6G/KVgkA=
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/wv2util/Pages/AboutPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | vN.N.N.N
25 |
26 | This is WebView2Utilities. It helps with developing and debugging Microsoft Edge WebView2 usage.
27 |
28 |
29 | WebView2 Tools GitHub
30 |
31 |
32 |
33 | WebView2 Documentation
34 |
35 |
36 |
37 |
38 |
39 | Latest WebView2 News
40 |
41 |
42 |
43 |
44 |
45 |
46 | More news ...
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/wv2util/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using System.Windows;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("WebView2Utilities")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("WebView2Utilities")]
13 | [assembly: AssemblyCopyright("Copyright © 2021")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | //In order to begin building localizable applications, set
23 | //CultureYouAreCodingWith in your .csproj file
24 | //inside a . For example, if you are using US english
25 | //in your source files, set the to en-US. Then uncomment
26 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
27 | //the line below to match the UICulture setting in the project file.
28 |
29 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
30 |
31 |
32 | [assembly: ThemeInfo(
33 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
34 | //(used if a resource is not found in the page,
35 | // or application resource dictionaries)
36 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
37 | //(used if a resource is not found in the page,
38 | // app, or any theme specific resource dictionaries)
39 | )]
40 |
41 |
42 | // Version information for an assembly consists of the following four values:
43 | //
44 | // Major Version
45 | // Minor Version
46 | // Build Number
47 | // Revision
48 | //
49 | // You can specify all the values or you can default the Build and Revision Numbers
50 | // by using the '*' as shown below:
51 | // [assembly: AssemblyVersion("1.0.*")]
52 | [assembly: AssemblyVersion("1.0.0.18")]
53 | [assembly: AssemblyFileVersion("1.0.0.18")]
54 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).
40 |
41 |
--------------------------------------------------------------------------------
/wv2util/CreateReportWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/wv2util/RegistryUtil.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Diagnostics;
4 |
5 | namespace wv2util
6 | {
7 | internal class RegistryUtil
8 | {
9 | public static readonly string s_webView2RegKey = @"Software\Policies\Microsoft\Edge\WebView2";
10 |
11 | public static void EnsureRegistryPaths(string[] registryPaths, RegistryKey root)
12 | {
13 | foreach (string registryPath in registryPaths)
14 | {
15 | RegistryUtil.EnsureRegistryPath(root, registryPath);
16 | }
17 | }
18 |
19 | public static void EnsureRegistryPath(RegistryKey root, string registryPath)
20 | {
21 | RegistryKey parent = root;
22 | foreach (string part in registryPath.Split('\\'))
23 | {
24 | RegistryKey child = null;
25 | try
26 | {
27 | child = parent.OpenSubKey(part, true);
28 | }
29 | catch (Exception e)
30 | {
31 | Console.WriteLine("Error: " + e);
32 | }
33 | if (child == null)
34 | {
35 | child = parent.CreateSubKey(part, true);
36 | }
37 | parent = child;
38 | }
39 | }
40 |
41 | public static RegistryKey OpenRegistryPath(RegistryKey root, string registryPath, bool write)
42 | {
43 | RegistryKey parent = root;
44 | foreach (string part in registryPath.Split('\\'))
45 | {
46 | RegistryKey child = null;
47 | try
48 | {
49 | child = parent.OpenSubKey(part, write);
50 | }
51 | catch (Exception e)
52 | {
53 | Console.WriteLine("Error: " + e);
54 | }
55 | parent = child;
56 | }
57 | return parent;
58 | }
59 |
60 | public static void DeleteValueIfItExists(RegistryKey key, string valueName)
61 | {
62 | if (key != null && key.GetValue(valueName) != null)
63 | {
64 | key.DeleteValue(valueName);
65 | }
66 | }
67 |
68 | private static readonly string s_regEditKey = @"\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit";
69 | public static void LaunchRegEdit()
70 | {
71 | RegistryKey regEditKey = OpenRegistryPath(Registry.CurrentUser, s_regEditKey, true);
72 | regEditKey.SetValue("LastKey", @"Computer\HKEY_CURRENT_USER\" + s_webView2RegKey);
73 |
74 | Process.Start(@"C:\Windows\regedit.exe");
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/wv2util/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace wv2util.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("wv2util.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/wv2util/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
52 |
59 |
60 |
61 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/wv2util/CommandLineUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace wv2util
6 | {
7 | namespace CommandLineUtil
8 | {
9 | public class CommandLine
10 | {
11 | public CommandLine(string commandLine)
12 | {
13 | m_parts = ParseCommandLine(commandLine);
14 | }
15 |
16 | public string GetKeyValue(string key)
17 | {
18 | return GetKeyValue(m_parts, key);
19 | }
20 |
21 | public string[] Parts => m_parts.ToArray();
22 |
23 | public override string ToString()
24 | {
25 | return String.Join(" ",
26 | Parts.Select(part => part.Contains(" ") ? ('"' + part + '"') : part));
27 | }
28 |
29 | public bool Contains(string entry) => Parts.Contains(entry);
30 |
31 | public bool Add(string entry)
32 | {
33 | if (!m_parts.Contains(entry))
34 | {
35 | m_parts.Add(entry);
36 | return true;
37 | }
38 | return false;
39 | }
40 |
41 | public bool Remove(string entry) => m_parts.Remove(entry);
42 |
43 | private List m_parts;
44 |
45 | private static string GetKeyValue(List all, string key)
46 | {
47 | foreach (string entry in all)
48 | {
49 | if (entry.StartsWith(key + "="))
50 | {
51 | return entry.Substring(key.Length + 1);
52 | }
53 | }
54 | return null;
55 | }
56 |
57 | private static List ParseCommandLine(string commandLine)
58 | {
59 | List parts = new List();
60 | bool inQuote = false;
61 | string part = "";
62 |
63 | if (commandLine == null)
64 | {
65 | commandLine = "";
66 | }
67 |
68 | for (int curIdx = 0; curIdx < commandLine.Length; ++curIdx)
69 | {
70 | char curChar = commandLine[curIdx];
71 | if (!inQuote && Char.IsWhiteSpace(curChar))
72 | {
73 | if (part.Length > 0)
74 | {
75 | parts.Add(part);
76 | part = "";
77 | }
78 | }
79 | else if (!inQuote && curChar == '"')
80 | {
81 | inQuote = true;
82 | }
83 | else if (inQuote && curChar == '"')
84 | {
85 | inQuote = false;
86 | }
87 | else
88 | {
89 | part += curChar;
90 | }
91 | }
92 |
93 | if (part.Length > 0)
94 | {
95 | parts.Add(part);
96 | }
97 |
98 | return parts;
99 | }
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/wv2util/SortUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace wv2util
7 | {
8 | public static class SortUtil
9 | {
10 | public class SortColumnContext
11 | {
12 | private int m_columnIdx = 0;
13 | public int SortDirection { get; private set; } = 1;
14 | public void SelectColumn(int columnIdx)
15 | {
16 | if (columnIdx == m_columnIdx)
17 | {
18 | SortDirection *= -1;
19 | }
20 | else
21 | {
22 | SortDirection = 1;
23 | m_columnIdx = columnIdx;
24 | }
25 | }
26 | }
27 | public class ComparisonComparer : IComparer, IComparer
28 | {
29 | private readonly Comparison _comparison;
30 |
31 | public ComparisonComparer(Comparison comparison)
32 | {
33 | _comparison = comparison;
34 | }
35 |
36 | public int Compare(T x, T y)
37 | {
38 | return _comparison(x, y);
39 | }
40 |
41 | public int Compare(object o1, object o2)
42 | {
43 | return _comparison((T)o1, (T)o2);
44 | }
45 | }
46 |
47 | public static int CompareStrings(string left, string right)
48 | {
49 | string effectiveLeft = left;
50 | string effectiveRight = right;
51 | if (effectiveLeft == null)
52 | {
53 | effectiveLeft = "";
54 | }
55 | if (effectiveRight == null)
56 | {
57 | effectiveRight = "";
58 | }
59 | return effectiveLeft.CompareTo(effectiveRight);
60 | }
61 |
62 | public static int CompareVersionStrings(string left, string right)
63 | {
64 | // If its not a version number just give it an effective 0 version.
65 | if (!left.Contains('.'))
66 | {
67 | left = "0.0.0.0";
68 | }
69 | if (!right.Contains('.'))
70 | {
71 | right = "0.0.0.0";
72 | }
73 | IEnumerable leftParts = left.Split('.').Select(partAsString => int.Parse(partAsString));
74 | IEnumerable rightParts = right.Split('.').Select(partAsString => int.Parse(partAsString));
75 |
76 | while (leftParts.Count() < rightParts.Count())
77 | {
78 | leftParts.Append(0);
79 | }
80 | while (leftParts.Count() > rightParts.Count())
81 | {
82 | rightParts.Append(0);
83 | }
84 |
85 | IEnumerator leftEnum = leftParts.GetEnumerator();
86 | IEnumerator rightEnum = rightParts.GetEnumerator();
87 | while (leftEnum.MoveNext() && rightEnum.MoveNext())
88 | {
89 | int diff = leftEnum.Current - rightEnum.Current;
90 | if (diff != 0)
91 | {
92 | return diff;
93 | }
94 | }
95 | return 0;
96 | }
97 |
98 | public static int CompareChannelStrings(string left, string right)
99 | {
100 | string[] channels = { "Canary", "Dev", "Beta", "Stable", "Stable WebView2 Runtime" };
101 | int leftPos = Array.IndexOf(channels, left);
102 | int rightPos = Array.IndexOf(channels, right);
103 | return leftPos - rightPos;
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | One of the easiest ways to contribute is to participate in discussions on GitHub issues. You can also contribute by submitting pull requests with code changes.
4 |
5 | ## General feedback and discussions?
6 |
7 | Start a discussion on the [repository issue tracker](/issues).
8 |
9 | ## Bugs and feature requests?
10 |
11 | ❗ **IMPORTANT: If you want to report a security-related issue, please see [security.md](./SECURITY.md)**
12 |
13 | Before reporting a new issue, try to find an existing issue if one already exists. If it already exists, upvote (👍) it. Also, consider adding a comment with your unique scenarios and requirements related to that issue. Upvotes and clear details on the issue's impact help us prioritize the most important issues to be worked on sooner rather than later. If you can't find one, that's okay, we'd rather get a duplicate report than none.
14 |
15 | ## How to contribute
16 |
17 | ### Getting Started
18 |
19 | 1. Enlist (Clone the Repo):
20 | - `git clone https://github.com/david-risney/WebView2Utilities.git`
21 | - If you have a preferred method for cloning GitHub projects, feel free to use that instead.
22 |
23 | 2. Build:
24 | - Open `wv2util/wv2util.sln` in Visual Studio (VS).
25 | - Ensure the solution configurations are set to `Debug` or `Release`, and the platform is set to `Any CPU`.
26 | - Click `Build` to build the solution.
27 |
28 | 3. Debug:
29 | - Ensure that VS is running as an administrator.
30 | - Use VS to debug (F5).
31 | - If wv2util is not running as an administrator, VS will restart it as an administrator. Therefore, it is important to run VS as an administrator so that you will be debugging the correct process.
32 |
33 | 4. Test:
34 | - There are tests in the same solution, but different project (wv2utilTests), that you can run in VS (Ctrl+R).
35 |
36 | ### Submitting Code Changes
37 |
38 | 1. Create a new branch from the `main` branch.
39 | - `git checkout -b my-branch-name`
40 | - Push your code to a user branch
41 |
42 | 2. Open a pull request (PR) in GitHub.
43 | - Open a PR in GitHub and describe the changes you are making.
44 | - If you are fixing an issue, reference the issue in the PR description.
45 |
46 |
55 |
56 | 3. PR/push pipeline
57 | - PRs and push in GitHub will build the code and run the tests in GitHub Actions.
58 | - If the PR fails, you will need to address the issues and push the changes to the same branch.
59 |
60 | 4. Feedback and review
61 | - If the pull request is ready for review, the team member will assign the pull request to a reviewer. A core contributor will review your pull request and provide feedback.
62 |
63 | 5. Merge
64 | - When your pull request has had all feedback addressed, it has been signed off by one or more reviewers with commit access, and all checks are green, we will commit it.
65 |
66 | ## Code of conduct
67 |
68 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
--------------------------------------------------------------------------------
/wv2util/Pages/RuntimesPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Navigation;
15 | using System.Windows.Shapes;
16 |
17 | namespace wv2util
18 | {
19 |
20 | ///
21 | /// Interaction logic for RuntimesPage.xaml
22 | ///
23 | public partial class RuntimesPage : Page, IReloadable
24 | {
25 | private RuntimeList RuntimeListData => AppState.GetRuntimeList();
26 |
27 | private bool m_reloading = false;
28 | public bool Reloading
29 | {
30 | get => m_reloading;
31 | private set
32 | {
33 | if (value != m_reloading)
34 | {
35 | m_reloading = value;
36 | this.ReloadingChanged?.Invoke(this, new EventArgs());
37 | }
38 | }
39 | }
40 |
41 | public RuntimesPage()
42 | {
43 | InitializeComponent();
44 | }
45 |
46 | public event EventHandler ReloadingChanged;
47 |
48 | public void Reload()
49 | {
50 | _ = ReloadInternalAsync();
51 | }
52 |
53 | private async Task ReloadInternalAsync()
54 | {
55 | if (!this.Reloading)
56 | {
57 | this.Reloading = true;
58 | await RuntimeListData.FromDiskAsync();
59 | this.Reloading = false;
60 | }
61 | }
62 |
63 | private readonly SortUtil.SortColumnContext m_runtimeSortColumn = new SortUtil.SortColumnContext();
64 | private void GridViewColumnHeader_Runtime_Path_Click(object sender, RoutedEventArgs e)
65 | {
66 | m_runtimeSortColumn.SelectColumn(0);
67 |
68 | RuntimeListData.Sort((left, right) =>
69 | m_runtimeSortColumn.SortDirection * SortUtil.CompareStrings(left.RuntimeLocation, right.RuntimeLocation));
70 | }
71 |
72 | private void GridViewColumnHeader_Runtime_Version_Click(object sender, RoutedEventArgs e)
73 | {
74 | m_runtimeSortColumn.SelectColumn(2);
75 | RuntimeListData.Sort((left, right) =>
76 | m_runtimeSortColumn.SortDirection * SortUtil.CompareVersionStrings(left.Version, right.Version));
77 | }
78 |
79 | private void GridViewColumnHeader_Runtime_Channel_Click(object sender, RoutedEventArgs e)
80 | {
81 | m_runtimeSortColumn.SelectColumn(2);
82 | RuntimeListData.Sort((left, right) =>
83 | m_runtimeSortColumn.SortDirection * SortUtil.CompareChannelStrings(left.Channel, right.Channel));
84 | }
85 |
86 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
87 | {
88 | if (e.Uri.IsFile)
89 | {
90 | ProcessUtil.OpenExplorerToFile(e.Uri.LocalPath);
91 | }
92 | else
93 | {
94 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
95 | }
96 | e.Handled = true;
97 | }
98 |
99 | private void ListViewItem_PreviewMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
100 | {
101 | ListViewItem item = (ListViewItem)(sender);
102 | RuntimeEntry entry = (RuntimeEntry)item.Content;
103 | Process.Start(entry.RuntimeLocation);
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/wv2util/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/wv2utilTests/ObservableCollectionProjectionTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using wv2util;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Collections.ObjectModel;
9 | using System.Diagnostics;
10 | using System.Collections.Specialized;
11 |
12 | namespace wv2util.Tests
13 | {
14 | public class A
15 | {
16 | public int value;
17 | }
18 |
19 | public class B
20 | {
21 | public int value;
22 | }
23 |
24 | [TestClass()]
25 | public class ObservableCollectionProjectionTests
26 | {
27 | private ObservableCollection GetTestOCA()
28 | {
29 | ObservableCollection oca = new ObservableCollection();
30 | oca.Add(new A { value = 1 });
31 | oca.Add(new A { value = 2 });
32 | oca.Add(new A { value = 3 });
33 |
34 | return oca;
35 | }
36 |
37 | [TestMethod()]
38 | public void TestCount()
39 | {
40 | var oca = GetTestOCA();
41 | ObservableCollection ocb = new ObservableCollectionProjection(oca, a => new B { value = a.value + 100 });
42 |
43 | Debug.Assert(ocb.Count == oca.Count);
44 | }
45 |
46 |
47 | [TestMethod()]
48 | public void TestWrapValues()
49 | {
50 | var oca = GetTestOCA();
51 | ObservableCollection ocb = new ObservableCollectionProjection(oca, a => new B { value = a.value + 100 });
52 |
53 | Debug.Assert(ocb[0].value == 101);
54 | Debug.Assert(ocb[1].value == 102);
55 | Debug.Assert(ocb[2].value == 103);
56 | }
57 |
58 | [TestMethod()]
59 | public void TestIdentity()
60 | {
61 | var oca = GetTestOCA();
62 | ObservableCollection ocb = new ObservableCollectionProjection(oca, a => new B { value = a.value + 100 });
63 |
64 | var ocb0_1 = ocb[0];
65 | var ocb0_2 = ocb[0];
66 | Debug.Assert(ocb0_1 == ocb0_2);
67 | }
68 |
69 | [TestMethod()]
70 | public void TestAddition()
71 | {
72 | var oca = GetTestOCA();
73 | ObservableCollection ocb = new ObservableCollectionProjection(oca, a => new B { value = a.value + 100 });
74 |
75 | var ocb0_1 = ocb[0];
76 | var ocb0_2 = ocb[0];
77 | Debug.Assert(ocb0_1 == ocb0_2);
78 | }
79 |
80 | [TestMethod()]
81 | public void TestRemoval()
82 | {
83 | var oca = GetTestOCA();
84 | ObservableCollection ocb = new ObservableCollectionProjection(oca, a => new B { value = a.value + 100 });
85 |
86 | Debug.Assert(oca[1].value == 2);
87 | Debug.Assert(ocb[1].value == 102);
88 |
89 | oca.RemoveAt(1);
90 |
91 | Debug.Assert(oca[1].value == 3);
92 | Debug.Assert(ocb[1].value == 103);
93 | }
94 |
95 | [TestMethod()]
96 | public async Task TestPropertyChangedEvent()
97 | {
98 | var oca = GetTestOCA();
99 | ObservableCollection ocb = new ObservableCollectionProjection(oca, a => new B { value = a.value + 100 });
100 |
101 | TaskCompletionSource tcsa = null;
102 | TaskCompletionSource tcsb = null;
103 |
104 | tcsa = new TaskCompletionSource();
105 | tcsb = new TaskCompletionSource();
106 | oca.CollectionChanged += (object sender, NotifyCollectionChangedEventArgs e) => tcsa.TrySetResult(e);
107 | oca.CollectionChanged += (object sender, NotifyCollectionChangedEventArgs e) => tcsb.TrySetResult(e);
108 | oca.RemoveAt(0);
109 | var eventArgs = await tcsa.Task;
110 | Debug.Assert(eventArgs != null);
111 | eventArgs = await tcsb.Task;
112 | Debug.Assert(eventArgs != null);
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/wv2util/Pages/RuntimesPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Path
25 |
26 |
27 | Version
28 |
29 |
30 | Channel
31 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | Microsoft Edge release schedule
47 |
48 |
49 |
50 |
51 | WebView2 Runtime (browser release notes, SDK release notes)
52 |
53 |
54 |
55 | Microsoft Canary, Dev and Beta Channel (beta release notes)
56 |
57 |
58 |
59 | WebView2 Runtime Fixed Version
60 |
61 |
62 |
63 | Microsoft Edge older versions
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/wv2utilTests/ReportCreatorTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using wv2util;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.IO;
9 | using System.IO.Compression;
10 | using System.Diagnostics;
11 | using System.Threading;
12 |
13 | namespace wv2util.Tests
14 | {
15 | [TestClass()]
16 | public class ReportCreatorTests
17 | {
18 | ReportCreator CreateReportCreatorForTest()
19 | {
20 | return new ReportCreator(
21 | new HostAppEntry("host", "example.exe", "C:\\msedgewebview2.exe --embedded-browser-webview=1", 1, 0, "C:\\windows\\system32\\actxprxy.dll", "C:\\windows\\system32", "C:\\windows\\system32", new string[] { }, 2),
22 | new List(),
23 | new List());
24 | }
25 |
26 | [TestMethod()]
27 | public void CreateReportCreator()
28 | {
29 | var result = CreateReportCreatorForTest();
30 | }
31 |
32 | [TestMethod()]
33 | public void DestinationIsValid()
34 | {
35 | var reportCreator = CreateReportCreatorForTest();
36 | string fullPathWithFileName = reportCreator.DestinationPath;
37 | Assert.IsFalse(File.Exists(fullPathWithFileName));
38 |
39 | string parentFolderPath = Path.GetDirectoryName(fullPathWithFileName);
40 | Assert.IsTrue(Directory.Exists(parentFolderPath));
41 | }
42 |
43 | [TestMethod()]
44 | public void DefaultFilesAreThere()
45 | {
46 | var reportCreator = CreateReportCreatorForTest();
47 | Assert.IsTrue(reportCreator.ReportFilesList.Contains(new ReportCreator.FileEntry("summary.json")));
48 | }
49 |
50 | public static bool IsZipFile(string path)
51 | {
52 | try
53 | {
54 | using (var archive = System.IO.Compression.ZipFile.OpenRead(path))
55 | {
56 | return true;
57 | }
58 | }
59 | catch (Exception)
60 | {
61 | return false;
62 | }
63 | }
64 |
65 | public static bool IsFileWithMoreThanOneByteInSize(string path)
66 | {
67 | return new FileInfo(path).Length > 1;
68 | }
69 |
70 | [TestMethod()]
71 | public async Task CreatingReportWorks()
72 | {
73 | var reportCreator = CreateReportCreatorForTest();
74 | CancellationTokenSource cts = new CancellationTokenSource();
75 | await reportCreator.CreateReportAsync(cts.Token);
76 |
77 | Assert.IsTrue(File.Exists(reportCreator.DestinationPath));
78 | Assert.IsTrue(IsFileWithMoreThanOneByteInSize(reportCreator.DestinationPath));
79 | Assert.IsTrue(IsZipFile(reportCreator.DestinationPath));
80 |
81 | // Cleanup
82 | File.Delete(reportCreator.DestinationPath);
83 | }
84 |
85 | [TestMethod()]
86 | [Ignore]
87 | public async Task AddDxDiagWorksAsync()
88 | {
89 | var reportCreator = CreateReportCreatorForTest();
90 | CancellationTokenSource cts = new CancellationTokenSource();
91 | await reportCreator.AddDxDiagLogAsync(cts.Token);
92 | var dxdiagFileEntry = reportCreator.ReportFilesList.First(
93 | fileEntry => fileEntry.InputPathFileName.ToLower().Contains("dxdiag"));
94 | Assert.IsTrue(File.Exists(dxdiagFileEntry.InputPathFileName));
95 | Assert.IsTrue(IsFileWithMoreThanOneByteInSize(dxdiagFileEntry.InputPathFileName));
96 | }
97 |
98 | [TestMethod()]
99 | [Ignore]
100 | public async Task AddProcMonWorksAsync()
101 | {
102 | var reportCreator = CreateReportCreatorForTest();
103 | CancellationTokenSource cts = new CancellationTokenSource();
104 | TaskCompletionSource tcs = new TaskCompletionSource();
105 |
106 | Task addLog = reportCreator.AddScenarioLogAsync(ReportCreator.LogKind.ProcMon, tcs.Task, cts.Token);
107 |
108 | await Task.Delay(100); // Wait 0.1 seconds
109 |
110 | tcs.SetResult(true);
111 |
112 | await addLog;
113 |
114 | bool hasFile = reportCreator.ReportFilesList.Any(
115 | fileEntry => fileEntry.InputPathFileName.ToLower().Contains("procmon"));
116 |
117 | Assert.IsTrue(hasFile);
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/wv2util/Pages/AppOverridesPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Forms;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Navigation;
16 | using System.Windows.Shapes;
17 |
18 | namespace wv2util
19 | {
20 | ///
21 | /// Interaction logic for AppOverridesPage.xaml
22 | ///
23 | public partial class AppOverridesPage : Page, IReloadable, IShowHostAppEntryAsAppOverrideEntry
24 | {
25 | public AppOverridesPage()
26 | {
27 | InitializeComponent();
28 | }
29 |
30 | private void RemoveButton_Click(object sender, RoutedEventArgs e)
31 | {
32 | // We use SelectedItems to remove it by value rather than by
33 | // selected index, because the index is relative to the sorted
34 | // view, and we need to remove from the unsorted list.
35 | var selectedItems = AppOverrideListBox.SelectedItems;
36 | if (selectedItems.Count == 1)
37 | {
38 | var selectedItem = selectedItems[0];
39 | AppOverrideListData.Remove((AppOverrideEntry)selectedItem);
40 | }
41 | }
42 |
43 | private void AddNewButton_Click(object sender, RoutedEventArgs e)
44 | {
45 | AppOverrideEntry entry = new AppOverrideEntry
46 | {
47 | HostApp = "New " + (++m_NewEntriesCount),
48 | StorageKind = StorageKind.HKCU,
49 | };
50 | entry.InitializationComplete();
51 | AppOverrideListData.Add(entry);
52 | }
53 |
54 | private void RegEditButton_Click(object sender, RoutedEventArgs e)
55 | {
56 | RegistryUtil.LaunchRegEdit();
57 | }
58 |
59 | private void EnvVarButton_Click(object sender, RoutedEventArgs e)
60 | {
61 | Process.Start("rundll32.exe", "sysdm.cpl,EditEnvironmentVariables");
62 | }
63 |
64 | protected AppOverrideList AppOverrideListData => AppState.GetAppOverrideList();
65 | private uint m_NewEntriesCount = 0;
66 |
67 | private void AppOverrideRuntimePathButton_Click(object sender, RoutedEventArgs e)
68 | {
69 | FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog
70 | {
71 | Description = "Select a WebView2 Runtime folder"
72 | };
73 | if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
74 | {
75 | AppOverrideRuntimePathComboBox.Text = folderBrowserDialog.SelectedPath;
76 | }
77 | }
78 |
79 | private void AppOverrideUserDataPathButton_Click(object sender, RoutedEventArgs e)
80 | {
81 | FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog
82 | {
83 | Description = "Select the path to a user data folder"
84 | };
85 | if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
86 | {
87 | AppOverrideUserDataPathTextBox.Text = folderBrowserDialog.SelectedPath;
88 | }
89 | }
90 |
91 | private void AppOverrideBrowserArgumentsButton_Click(object sender, RoutedEventArgs e)
92 | {
93 | Process.Start("https://peter.sh/experiments/chromium-command-line-switches/");
94 | }
95 |
96 | private bool m_reloading = false;
97 | public bool Reloading
98 | {
99 | get => m_reloading;
100 | private set
101 | {
102 | if (value != m_reloading)
103 | {
104 | m_reloading = value;
105 | this.ReloadingChanged?.Invoke(this, new EventArgs());
106 | }
107 | }
108 | }
109 |
110 | public event EventHandler ReloadingChanged;
111 | public void Reload()
112 | {
113 | ReloadInternal();
114 | }
115 |
116 | private void ReloadInternal()
117 | {
118 | if (!this.Reloading)
119 | {
120 | this.Reloading = true;
121 | AppOverrideListData.FromSystem();
122 | this.Reloading = false;
123 | }
124 | }
125 |
126 | public void ShowHostAppEntryAsAppOverrideEntry(HostAppEntry hostAppEntry)
127 | {
128 | // Find the first override entry that explicitly matches the host app.
129 | // If none exist, then create and add it.
130 | // Then select that entry and show that tab.
131 | AppOverrideEntry selectedAppOverrideEntry = AppOverrideListData.FirstOrDefault(
132 | entry => entry.HostApp.ToLower() == hostAppEntry.ExecutableName.ToLower());
133 |
134 | if (selectedAppOverrideEntry == null)
135 | {
136 | selectedAppOverrideEntry = new AppOverrideEntry
137 | {
138 | HostApp = hostAppEntry.ExecutableName,
139 | StorageKind = StorageKind.HKCU,
140 | };
141 | selectedAppOverrideEntry.InitializationComplete();
142 | AppOverrideListData.Add(selectedAppOverrideEntry);
143 | }
144 |
145 | AppOverrideListBox.SelectedItem = selectedAppOverrideEntry;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/wv2util/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_13/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | tBck/6AZVb542PUTXJQ6KLjkjRie0Z0chJxngQX1uAs=
25 |
26 |
27 |
28 | oQ1AexKo+CwxvvqwXAtS1amAaVqnT6m33QVzI8UBodg=L8KvN40Y1ebMm7UjN57xRoWd6+JHd2tjwJdE/pcUE4g1JKdms2JZNvsSXvNdLgCj6QIIBaddDpJYaBkdI8TMkkjGf/5V17bSjp6GNxkcXsYIfUHt//7DmIEmM3KFuOtRY4WbhYVHma1nCKqbb6CmUWdNGndbxOPkbY13CmGvezk=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABCN=NTDEV\davrisTZ8QNNQafoMaECkWUUpqbcc6FRe302ll0V8IxaPM1oA=mw/Dyxr4qIuygOo0qDUNWbbWchdoTqvXPmsHVk5GmWCCUC1WM25lnEdJ/bw6Vegt5JMJA9xZ/732S41MAZIExnd/JkhDFQEhyMWIe/k6Y3U2vECgKzxYlHPOEA83sx+ynnWLCYNsX5+Lh6q/bxZuQGJjsCjoi+9c2PRowl6vIm0=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABMIIByTCCATKgAwIBAgIQKnRXgMgm5YNDxv8o9Im9iDANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwHhcNMjEwMzI4MDEyNTI1WhcNMjIwMzI4MDcyNTI1WjAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkNK10d4VvcZ6DzAK2Wwf/iKGA2gj3MdRrCkvOqc3tXqX32RhUUWbKrzcZfi/UmqMrD5bIflQYuFe+cOkMcvFa1G57VnzKNo54+uL66YJgHSI+cazyjKe4c+v/IudU+N/UTGsjSZfYyemm95dUA/lhPeJkSkKT3V/H07FPVn68RAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAiyG3/kh7ZFBZ6Sf+Nsc+rLFtvjgppBYasfUV2sQOfFLhoTkHJJUihNL1gV0TZnX9ZSWUMUXCkfZhHDtdllN41pospNK+D8w4aZ4wvH2FBYWBBCSSXPwIiGGVLYseTQtOzYXO5NDZHTDwGtc660um0PS0pcS884xiOXt9OUcAUmE=
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_14/WebView2Utilities.application:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | pm/1K9nsdr87nrPDg8rM1O2IBZkWb/ara+BewG42TXA=
25 |
26 |
27 |
28 | JNSb07gVmqFCWiwIVbJ64DfwzoCw8S7NhtvMYRgQzQw=haOocAkaMRC9vDpanKXVd3JJZVWuRtbCBe4aIzalYQ+blBZ7R3iuqS1mMUqM5fZAeQzf2VUTw9OwnEXEt6vYbybR7daORljfNMBqAImj9mC1SGHbWwhl35JAv/Zp7HW7N8Uwqvycn+rdSUCrn+3scPN6SjRwbARiixFef3MvrJE=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABCN=NTDEV\davrisqjylj2A973lmD/uJIuKzYHy88b80jNUne1U90SrZnTw=COPfSA09ggmmqH+CYsiKrHjIKJ4jazf54CpgmOFO2wR8Khfa0QSGswKA3Nv5ssfjvviG9XRdWTZ0tyJx54IQaN6yc4eQ23jAqCAaPZ4dT9IOFar7fAeKNcSIvs2yIHG1u0J57KAaEetFkYMbByD5EFxpLTPvuKI7vSWn1xYjYko=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABMIIByTCCATKgAwIBAgIQKnRXgMgm5YNDxv8o9Im9iDANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwHhcNMjEwMzI4MDEyNTI1WhcNMjIwMzI4MDcyNTI1WjAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkNK10d4VvcZ6DzAK2Wwf/iKGA2gj3MdRrCkvOqc3tXqX32RhUUWbKrzcZfi/UmqMrD5bIflQYuFe+cOkMcvFa1G57VnzKNo54+uL66YJgHSI+cazyjKe4c+v/IudU+N/UTGsjSZfYyemm95dUA/lhPeJkSkKT3V/H07FPVn68RAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAiyG3/kh7ZFBZ6Sf+Nsc+rLFtvjgppBYasfUV2sQOfFLhoTkHJJUihNL1gV0TZnX9ZSWUMUXCkfZhHDtdllN41pospNK+D8w4aZ4wvH2FBYWBBCSSXPwIiGGVLYseTQtOzYXO5NDZHTDwGtc660um0PS0pcS884xiOXt9OUcAUmE=
--------------------------------------------------------------------------------
/wv2util/Pages/AboutPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Markdig.Wpf;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Net.Http;
7 | using System.Text;
8 | using System.Text.Json;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Controls;
12 | using System.Windows.Data;
13 | using System.Windows.Documents;
14 | using System.Windows.Input;
15 | using System.Windows.Media;
16 | using System.Windows.Media.Imaging;
17 | using System.Windows.Navigation;
18 | using System.Windows.Shapes;
19 |
20 | namespace wv2util
21 | {
22 | ///
23 | /// Interaction logic for AboutPage.xaml
24 | ///
25 | public partial class AboutPage : Page
26 | {
27 | public AboutPage()
28 | {
29 | InitializeComponent();
30 | VersionInfo.Text = "v" + VersionUtil.GetWebView2UtilitiesVersion();
31 | GenerateNewsBlocksAsync();
32 | }
33 |
34 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
35 | {
36 | if (e.Uri.IsFile)
37 | {
38 | ProcessUtil.OpenExplorerToFile(e.Uri.LocalPath);
39 | }
40 | else
41 | {
42 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
43 | }
44 | e.Handled = true;
45 | }
46 |
47 | private void Hyperlink_ExecutedRouted(object sender, ExecutedRoutedEventArgs e)
48 | {
49 | try
50 | {
51 | Process.Start(e.Parameter.ToString());
52 | }
53 | catch (Exception ex)
54 | {
55 | Console.WriteLine($"Error: {ex.Message}");
56 | }
57 | }
58 |
59 | private static string s_newsLink = "https://api.github.com/repos/MicrosoftEdge/WebView2Announcements/issues";
60 | private async Task GetNewsDataAsync()
61 | {
62 | var client = new HttpClient();
63 | client.DefaultRequestHeaders.Accept.Clear();
64 | client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
65 | client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
66 |
67 | var response = await client.GetAsync(s_newsLink);
68 | if (response.IsSuccessStatusCode)
69 | return await response.Content.ReadAsStringAsync();
70 | else
71 | return await Task.FromResult($"{{ \"error\": \"{response.StatusCode}\" }}");
72 | }
73 |
74 | private Dictionary m_newsBodyCollapsedControllerMap = new Dictionary();
75 | private async void GenerateNewsBlocksAsync()
76 | {
77 | string newsData = await GetNewsDataAsync();
78 | var newsJson = JsonSerializer.Deserialize(newsData);
79 | int newsDisplayed = 3;
80 | int bodyFontSize = 12;
81 |
82 | if (newsJson.ValueKind != JsonValueKind.Null &&
83 | newsJson.ValueKind == JsonValueKind.Array &&
84 | newsJson.EnumerateArray().Any())
85 | {
86 | for (int i = 0; i < newsDisplayed && i < newsJson.GetArrayLength(); i++)
87 | {
88 | // Skip a newsBlock when the data is invalid.
89 | if (newsJson[i].ValueKind != JsonValueKind.Object ||
90 | !newsJson[i].TryGetProperty("title", out var title) ||
91 | !newsJson[i].TryGetProperty("body", out var body))
92 | {
93 | continue;
94 | }
95 |
96 | // Add the title to the block.
97 | TextBlock newsBlock = new TextBlock
98 | {
99 | Text = title.GetString(),
100 | FontSize = bodyFontSize + 2,
101 | Margin = new Thickness(10, 10, 0, 0),
102 | Cursor = Cursors.Hand
103 | };
104 |
105 | // Add body content to the block.
106 | MarkdownViewer bodyBlock = new MarkdownViewer
107 | {
108 | Markdown = body.GetString(),
109 | FontSize = bodyFontSize,
110 | };
111 | foreach (Block block in bodyBlock.Document.Blocks)
112 | if (block.FontSize > bodyFontSize)
113 | block.FontSize = bodyFontSize;
114 | bodyBlock.CommandBindings.Add(new CommandBinding(Commands.Hyperlink, Hyperlink_ExecutedRouted));
115 | Grid bodyGrid = new Grid
116 | {
117 | Children = { bodyBlock },
118 | Width = 500,
119 | };
120 |
121 | // Enable click to collapse function.
122 | newsBlock.MouseDown += NewsBlock_Click;
123 | m_newsBodyCollapsedControllerMap[newsBlock] = bodyGrid;
124 | bodyGrid.Visibility = Visibility.Collapsed;
125 |
126 | newsBlock.Inlines.Add(new LineBreak());
127 | newsBlock.Inlines.Add(bodyGrid);
128 | NewsPanel.Children.Add(newsBlock);
129 | }
130 | }
131 | }
132 |
133 | private void NewsBlock_Click(object sender, MouseButtonEventArgs e)
134 | {
135 | if (sender is TextBlock clickedTextBlock && m_newsBodyCollapsedControllerMap.ContainsKey(clickedTextBlock))
136 | {
137 | UIElement targetContainer = m_newsBodyCollapsedControllerMap[clickedTextBlock];
138 | targetContainer.Visibility = targetContainer.Visibility == Visibility.Visible
139 | ? Visibility.Collapsed
140 | : Visibility.Visible;
141 | }
142 | }
143 |
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/wv2utilTests/wv2utilTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {D5570F16-2715-4559-9081-F1EF68C4A961}
7 | Library
8 | Properties
9 | wv2utilTests
10 | wv2utilTests
11 | v4.7.2
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 |
22 |
23 | true
24 | full
25 | false
26 | bin\Debug\
27 | DEBUG;TRACE
28 | prompt
29 | 4
30 |
31 |
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 |
39 |
40 |
41 | ..\wv2util\packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
42 |
43 |
44 | ..\wv2util\packages\MSTest.TestFramework.2.2.7\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {3B31D688-B3A2-435A-9D52-4B089821AE6F}
71 | wv2util
72 |
73 |
74 |
75 |
76 | 2.2.7
77 |
78 |
79 | 2.2.7
80 |
81 |
82 |
83 |
84 |
85 |
86 | False
87 |
88 |
89 | False
90 |
91 |
92 | False
93 |
94 |
95 | False
96 |
97 |
98 |
99 |
100 |
101 |
102 |
109 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WebView2Utilities
2 |
3 | WebView2Utilities help you develop and debug Microsoft Edge WebView2 apps.
4 |
5 | 
6 |
7 | ## Install & Run
8 |
9 | * Install via the [ClickOnce install page](https://david-risney.github.io/WebView2Utilities/install/WebView2Utilities.application).
10 | * Or copy the binaries off the [releases page](https://github.com/david-risney/WebView2Utilities/releases/) to somewhere on your machine.
11 | * Or build [the code](https://github.com/david-risney/WebView2Utilities) yourself.
12 |
13 | ## UI details
14 |
15 | The app has three tabs for the different main WebView2Utilities features. Each tab has a `Refresh` button in the tab which you can use to force the information in that to reload.
16 |
17 | ### Host Apps tab
18 |
19 | This tab lists the running processes that are using WebView2. By default `Discover more Host Apps information (slower)` is unchecked and the processes listed will be those with a WebView2 mojo connection. Their HWND trees are examined to try to find their corresponding WebView2 runtime browser process. This may not work in some cases and you can try checking the `Discover more` checkbox. This will examine all processes, not just those with a WebView2 mojo connection, walk all HWND trees, and examine process parents. This finds more information but is slower.
20 |
21 | When selecting a Host App from the list on the left you can see details about the Host App on the right:
22 |
23 | * `IL` will report if the Host App process is running as admin, or in an app container.
24 | * `SDK version` is the version of the SDK DLLs that the Host App process has loaded.
25 | * `Probable UI framework` is WinForms, WPF, WinUI2, or WinUI3 and based on what DLLs the Host App process has loaded.
26 | * Similarly `Probable API kind` reports Win32, WinRT, or .NET also based on the DLLs loaded by the Host App process.
27 | * Both are 'probable' because its likely based on what DLLs the Host App process has loaded but not definitive.
28 | * The `Runtime path`, version, and channel are based on the WebView2 runtime DLL loaded by the Host App process. If these are Unknown then the host app is using WebView2 SDK DLLs but has not created a WebView2 yet.
29 | * The `User data folder` and `Browser process PID` are based on the browser process used by the host app process. As mentioned above, WebView2Utilities may not always be able to discover the browser process used. In that case the `Runtime path` will have a valid value, but the `User data folder` and `Browser process PID` will be listed as Unknown. You can try checking the `Discover more` checkbox in that case.
30 |
31 | There are some buttons below the detail information:
32 |
33 | * `Open Override` will create an entry for the selected app, if one doesn't already exit, in the Override tab, switch to the Override tab, and select the corresponding override entry.
34 | * `Create Report` will create a zip file containing information displayed in WebView2Utilities as well as any crash dumps or chromium logs for the selected host app. Note that personal information may be stored in the zip file as a part of the crash dump or elsewhere in the file. Only share the zip with people you trust.
35 |
36 | The `Watch for changes` checkbox is checked by default. When checked WebView2Utilities will check for changes to the set of processes with a WebView2 mojo connection every three seconds and if there is a change, the tab will be refreshed automatically. Otherwise, you can use the Refresh button in the tab title to refresh the list manually.
37 |
38 | ### Runtimes tab
39 |
40 | The Runtimes tab lists the found installed WebView2 Runtimes and non-stable Microsoft Edge browser installations. These are paths that you might use with the `Fixed Version` field in the Overrides tab.
41 |
42 | There's a section at the bottom with links to install additional versions of the WebView2 Runtime.
43 |
44 | ### Override tab
45 |
46 | This tab helps you set the [loader override policy registry keys](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.774.44#createcorewebview2environmentwithoptions).
47 |
48 | * `Host app exe` is the name of the host app's executable that the rest of the settings will apply to. It applies to future webview2 creations. The '* (All other apps)' entry applies to all apps that don't have a specific entry in this list.
49 | * `Runtime` contains three options for forcing apps to pick a WebView2 Runtime.
50 | * `Evergreen` is the usual manner of finding the WebView2 Runtime as described in the WebView2 documentation. First the WebView2 Runtime, then Beta, then Dev, then Canary channels.
51 | * `Evergreen with preview build` reverses the usual order of discovering installed WebView2 Runtimes looking for the least stable channel first.
52 | * `Fixed Version` lets you select an explicit path for a WebView2 Runtime. The path should have the msedgewebview2.exe in it. If set, the host app will use this runtime instead of whatever they requested.
53 | * `Browser arguments` is additional command line switches to be passed to the browser process created for the WebView2. If set, this is merged in with whatever the app sets. See the [list of chromium command line switches](https://peter.sh/experiments/chromium-command-line-switches/) to see what switches exist.
54 | * Common browser argument checkboxes follow. Checking these will alter the `Browser Arguments` text box to include or exclude these common browser arguments.
55 | * `Auto open DevTools` when set will cause the WebView2 to automatically open DevTools when the WebView2 is first created.
56 | * `Logging` when set will enable chromium logging to a log file in the user data folder. This log will be captured by the `Create Report` button on the Host Apps tab.
57 | * `User data path` is the path to a user data folder. If set the host app will use this user data folder instead of whatever they requested.
58 | * `Launch RegEdit` will open regedit.exe to the registry path of the override keys.
59 |
60 | You can use the `Add New` and `Remove` buttons to add and remove entries to the list. Additionally the Host app exe has a drop down of running host app executables for your convenience. Similarly, the Fixed Version has a drop down of found WebView Runtimes.
61 |
62 | ### About tab
63 |
64 | Application version and helpful links.
65 |
--------------------------------------------------------------------------------
/wv2util/TreeItem.cs:
--------------------------------------------------------------------------------
1 | using PInvoke;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.ComponentModel;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 |
14 | using System.Drawing;
15 | using System.Drawing.Imaging;
16 | using System.Reflection;
17 | using System.Windows.Interop;
18 | using System.Diagnostics;
19 |
20 | namespace wv2util
21 | {
22 | public interface ITreeItem : INotifyPropertyChanged
23 | {
24 | string Name { get; }
25 |
26 | BitmapSource IconAsBitmapSource { get; }
27 |
28 | ObservableCollection Children { get; }
29 |
30 | Object Model { get; }
31 |
32 | bool IsSelected { get; set; }
33 | bool IsExpanded { get; set; }
34 | }
35 |
36 | public class TreeItemBase : ITreeItem
37 | {
38 | public virtual string Name { get { throw new NotImplementedException(); } }
39 |
40 | public virtual BitmapSource IconAsBitmapSource => null;
41 |
42 | public virtual ObservableCollection Children { get; } = new ObservableCollection();
43 |
44 | public virtual object Model { get; } = null;
45 |
46 | public virtual event PropertyChangedEventHandler PropertyChanged;
47 | protected void OnPropertyChanged(string name)
48 | {
49 | this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
50 | }
51 |
52 | private bool m_IsSelected = false;
53 | public virtual bool IsSelected
54 | {
55 | get => m_IsSelected;
56 | set
57 | {
58 |
59 | if (m_IsSelected != value)
60 | {
61 | m_IsSelected = value;
62 | OnPropertyChanged("IsSelected");
63 | }
64 | }
65 | }
66 |
67 | private bool m_IsExpanded = false;
68 | public virtual bool IsExpanded
69 | {
70 | get => m_IsExpanded;
71 | set
72 | {
73 | if (m_IsExpanded != value)
74 | {
75 | m_IsExpanded = value;
76 | OnPropertyChanged("IsExpanded");
77 | }
78 | }
79 | }
80 | }
81 |
82 | public class HostAppEntryTreeItem : TreeItemBase
83 | {
84 | private HostAppList m_hostAppList;
85 | private HostAppEntry m_hostAppEntry;
86 | public HostAppEntryTreeItem(HostAppList hostAppList, HostAppEntry hostAppEntry)
87 | {
88 | m_hostAppList = hostAppList;
89 | m_hostAppEntry = hostAppEntry;
90 |
91 | m_hostAppList.CollectionChanged += HostAppListCollectionChanged;
92 | }
93 |
94 | private void HostAppListCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
95 | {
96 | OnPropertyChanged("Name");
97 | OnPropertyChanged("IconAsBitmapSource");
98 | OnPropertyChanged("Children");
99 | }
100 |
101 | public override string Name => m_hostAppEntry.DisplayLabel;
102 |
103 | public override BitmapSource IconAsBitmapSource => GetExecutableIcon(m_hostAppEntry);
104 |
105 | private static BitmapSource GetExecutableIcon(HostAppEntry hostAppEntry)
106 | {
107 | BitmapSource result = null;
108 |
109 | try
110 | {
111 | result = GetExecutableIcon(hostAppEntry.ExecutablePath);
112 | }
113 | catch (Exception e)
114 | {
115 | Debug.WriteLine(e.Message);
116 | }
117 |
118 | if (result == null)
119 | {
120 | try
121 | {
122 | // Load a generic system icon (e.g., application icon)
123 | Icon systemIcon = SystemIcons.Application;
124 | Bitmap systemBitmap = systemIcon.ToBitmap();
125 | MemoryStream systemStream = new MemoryStream();
126 | systemBitmap.Save(systemStream, ImageFormat.Png);
127 | systemStream.Seek(0, SeekOrigin.Begin);
128 |
129 | BitmapImage systemBitmapImage = new BitmapImage();
130 | systemBitmapImage.BeginInit();
131 | systemBitmapImage.StreamSource = systemStream;
132 | systemBitmapImage.CacheOption = BitmapCacheOption.OnLoad;
133 | systemBitmapImage.EndInit();
134 |
135 | result = systemBitmapImage;
136 | }
137 | catch (Exception e)
138 | {
139 | Debug.WriteLine(e.Message);
140 | }
141 | }
142 |
143 | return result;
144 | }
145 |
146 | private static BitmapSource GetExecutableIcon(string executablePath)
147 | {
148 | // Get the icon associated with the specified executable
149 | Icon appIcon = Icon.ExtractAssociatedIcon(executablePath);
150 |
151 | // Convert the Icon to a BitmapSource
152 | Bitmap bitmap = appIcon.ToBitmap();
153 | MemoryStream stream = new MemoryStream();
154 | bitmap.Save(stream, ImageFormat.Png);
155 | stream.Seek(0, SeekOrigin.Begin);
156 |
157 | BitmapImage bitmapImage = new BitmapImage();
158 | bitmapImage.BeginInit();
159 | bitmapImage.StreamSource = stream;
160 | bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
161 | bitmapImage.EndInit();
162 |
163 | return bitmapImage;
164 | }
165 |
166 | public override ObservableCollection Children
167 | {
168 | get
169 | {
170 | return new ObservableCollection(
171 | m_hostAppEntry.Children.Select(processEntry => new HostAppEntryTreeItem(m_hostAppList, processEntry)));
172 | }
173 | }
174 |
175 | public override Object Model => m_hostAppEntry;
176 |
177 | }
178 | }
--------------------------------------------------------------------------------
/wv2util/CreateReportWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.ObjectModel;
3 | using System.Runtime.CompilerServices;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using SaveFileDialog = System.Windows.Forms.SaveFileDialog;
8 |
9 | namespace wv2util
10 | {
11 | ///
12 | /// Interaction logic for CreateReportWindow.xaml
13 | ///
14 | public partial class CreateReportWindow : Window
15 | {
16 | public CreateReportWindow(Window parent, ReportCreator reportCreator)
17 | {
18 | base.Owner = parent;
19 | m_ReportCreator = reportCreator;
20 | InitializeComponent();
21 |
22 | InitializeDestinationPathTextBox();
23 | InitializeFilesListBox();
24 |
25 | this.Closing += CreateReportWindow_Closing;
26 | }
27 |
28 | private CancellationTokenSource m_CancellationTokenSource = new CancellationTokenSource();
29 |
30 | private void CreateReportWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
31 | {
32 | if (m_CancellationTokenSource != null)
33 | {
34 | m_CancellationTokenSource.Cancel();
35 | }
36 | m_ReportCreator.Cleanup();
37 | }
38 |
39 | private ReportCreator m_ReportCreator;
40 | public ObservableCollection ReportFilesList => m_ReportCreator.ReportFilesList;
41 | public String DestinationPath => m_ReportCreator.DestinationPath;
42 |
43 | private void DestinationPathChangeButton_Click(object sender, RoutedEventArgs e)
44 | {
45 | // Get the filename part of the DestinationPath
46 | string destinationPathFileName = System.IO.Path.GetFileName(m_ReportCreator.DestinationPath);
47 |
48 | // Prompt the user to pick a path to save the report zip
49 | SaveFileDialog saveFileDialog = new SaveFileDialog
50 | {
51 | Filter = "Zip files (*.zip)|*.zip|All files (*.*)|*.*",
52 | FileName = destinationPathFileName,
53 | RestoreDirectory = true
54 | };
55 | if (saveFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
56 | {
57 | m_ReportCreator.DestinationPath = saveFileDialog.FileName;
58 | InitializeDestinationPathTextBox();
59 | }
60 | }
61 |
62 | private void InitializeDestinationPathTextBox()
63 | {
64 | this.DestinationPathTextBox.Text = m_ReportCreator.DestinationPath;
65 | }
66 |
67 | private void InitializeFilesListBox()
68 | {
69 | this.FilesListBox.ItemsSource = ReportFilesList;
70 | }
71 |
72 | private void CancelButton_Click(object sender, RoutedEventArgs e)
73 | {
74 | this.Close();
75 | }
76 |
77 | private async void CreateReportButton_Click(object sender, RoutedEventArgs e)
78 | {
79 | this.CreateReportButton.IsEnabled = false;
80 | this.CreateReportButton.Content = "Creating Report...";
81 |
82 | try
83 | {
84 | await m_ReportCreator.CreateReportAsync(m_CancellationTokenSource.Token);
85 | // Once we've succeeded in creating the file, we no longer need to worry about cleaning it up.
86 | m_CancellationTokenSource = null;
87 |
88 | if ((bool)OpenReportInExplorerCheckBox.IsChecked)
89 | {
90 | ProcessUtil.OpenExplorerToFile(m_ReportCreator.DestinationPath);
91 | }
92 | this.Close();
93 |
94 | MessageBox.Show("The report was created.", "Report Created", MessageBoxButton.OK, MessageBoxImage.Information);
95 |
96 | }
97 | catch (Exception error)
98 | {
99 | this.CreateReportButton.IsEnabled = true;
100 | this.CreateReportButton.Content = "Create Report";
101 |
102 | MessageBox.Show(error.ToString(), "Failed to create report", MessageBoxButton.OK, MessageBoxImage.Error);
103 | }
104 | }
105 |
106 | private async void AddDxDiagLogButton_Click(object sender, RoutedEventArgs e)
107 | {
108 | AddDxDiagLogButton.IsEnabled = false;
109 | AddDxDiagLogButton.Content = "Adding DxDiag Log...";
110 |
111 | try
112 | {
113 | await m_ReportCreator.AddDxDiagLogAsync(m_CancellationTokenSource.Token);
114 | }
115 | catch (Exception error)
116 | {
117 | MessageBox.Show(error.ToString(), "Failed to add DxDiag log", MessageBoxButton.OK, MessageBoxImage.Error);
118 | }
119 | finally
120 | {
121 | AddDxDiagLogButton.IsEnabled = true;
122 | AddDxDiagLogButton.Content = "Add DxDiag Log";
123 | }
124 | }
125 |
126 | private TaskCompletionSource m_ProcMonLogScenarioTaskCompletionSource;
127 | private async void AddProcMonLogButton_Click(object sender, RoutedEventArgs e)
128 | {
129 | AddProcMonLogButton.IsEnabled = false;
130 | AddProcMonLogButton.Content = "Creating ProcMon Log...";
131 | StopProcMonLogButton.IsEnabled = true;
132 |
133 | try
134 | {
135 | m_ProcMonLogScenarioTaskCompletionSource = new TaskCompletionSource();
136 | await m_ReportCreator.AddScenarioLogAsync(
137 | ReportCreator.LogKind.ProcMon,
138 | m_ProcMonLogScenarioTaskCompletionSource.Task,
139 | m_CancellationTokenSource.Token);
140 | }
141 | catch (Exception error)
142 | {
143 | MessageBox.Show(error.ToString(), "Failed to add ProcMon log", MessageBoxButton.OK, MessageBoxImage.Error);
144 | }
145 | finally
146 | {
147 | AddProcMonLogButton.IsEnabled = true;
148 | AddProcMonLogButton.Content = "Add ProcMon Log";
149 | StopProcMonLogButton.IsEnabled = false;
150 | StopProcMonLogButton.Content = "Complete ProcMon Log";
151 | }
152 | }
153 |
154 | private void StopProcMonLogButton_Click(object sender, RoutedEventArgs e)
155 | {
156 | StopProcMonLogButton.IsEnabled = false;
157 | StopProcMonLogButton.Content = "Completing ProcMon Log...";
158 | m_ProcMonLogScenarioTaskCompletionSource?.SetResult(true);
159 | m_ProcMonLogScenarioTaskCompletionSource = null;
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/wv2util/HwndUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace wv2util
8 | {
9 | public static class HwndUtil
10 | {
11 | public static int GetWindowProcessId(IntPtr hwnd)
12 | {
13 | int processId = 0;
14 | try
15 | {
16 | PInvoke.User32.GetWindowThreadProcessId(hwnd, out processId);
17 | }
18 | catch (Exception e)
19 | {
20 | Trace.WriteLine("Exception related to GetWindowThreadProcessId " + e);
21 | }
22 | return processId;
23 | }
24 |
25 | public static IntPtr GetChildWindow(IntPtr hwnd)
26 | {
27 | IntPtr result = IntPtr.Zero;
28 | try
29 | {
30 | result = PInvoke.User32.GetWindow(hwnd, PInvoke.User32.GetWindowCommands.GW_CHILD);
31 | }
32 | catch (Exception e)
33 | {
34 | Trace.WriteLine("Exception related to GetWindow " + e);
35 | }
36 | return result;
37 | }
38 |
39 | public delegate bool HwndFilterCallback(IntPtr hwnd);
40 | public static IEnumerable GetTopLevelHwnds(HwndFilterCallback filterCallback = null, bool includeHwndMessage = false)
41 | {
42 | IntPtr child = IntPtr.Zero;
43 | var results = GetChildWindows(IntPtr.Zero, filterCallback);
44 |
45 | if (includeHwndMessage)
46 | {
47 | // HWND_MESSAGE = -3
48 | results = results.Concat(GetChildWindows((IntPtr)(-3), filterCallback));
49 | }
50 |
51 | if (filterCallback != null)
52 | {
53 | results = results.Where(hwnd => filterCallback(hwnd));
54 | }
55 |
56 | return results;
57 | }
58 |
59 | public static Dictionary> CreatePidToHwndsMapFromHwnds(IEnumerable hwnds)
60 | {
61 | Dictionary> pidToHwndMap = new Dictionary>();
62 | // Turn the list of hwnds into a dictionary of pid to hwnd list.
63 | foreach (IntPtr hwnd in hwnds)
64 | {
65 | int hwndPid = GetWindowProcessId(hwnd);
66 | if (!pidToHwndMap.TryGetValue(hwndPid, out List hwndList))
67 | {
68 | hwndList = new List();
69 | pidToHwndMap.Add(hwndPid, hwndList);
70 | }
71 | hwndList.Add(hwnd);
72 | }
73 |
74 | return pidToHwndMap;
75 | }
76 |
77 | public static Dictionary> GetPidToTopLevelHwndsMap(HwndFilterCallback filterCallback = null)
78 | {
79 | return CreatePidToHwndsMapFromHwnds(GetTopLevelHwnds(filterCallback));
80 | }
81 |
82 | public static IEnumerable GetChildWindows(IntPtr parentHwnd, HwndFilterCallback filterCallback = null)
83 | {
84 | HashSet hwnds = new HashSet();
85 |
86 | try
87 | {
88 | IntPtr child = IntPtr.Zero;
89 | while ((child = PInvoke.User32.FindWindowEx(parentHwnd, child, null, null)) != IntPtr.Zero)
90 | {
91 | hwnds.Add(child);
92 | }
93 | }
94 | catch (Exception e)
95 | {
96 | // Ignore exceptions trying to find windows.
97 | Trace.WriteLine("FindWindowEx related error: " + e);
98 | }
99 |
100 | // EnumChildWindows finds HWNDs that FindWindowEx does not and vice versa.
101 | // So we run both and collect HWNDs from both.
102 | try
103 | {
104 | HwndFilterCallback enumChildrenCallback = childHwnd =>
105 | {
106 | hwnds.Add(childHwnd);
107 | // Always return true to indicate to keep enumerating.
108 | return true;
109 | };
110 | PInvoke.User32.EnumChildWindows(parentHwnd, Marshal.GetFunctionPointerForDelegate(enumChildrenCallback), IntPtr.Zero);
111 | }
112 | catch (Exception e)
113 | {
114 | Trace.WriteLine("EnumChildWindows related exception " + e);
115 | }
116 |
117 | IEnumerable hwndsResult = hwnds;
118 | if (filterCallback != null)
119 | {
120 | hwndsResult = hwndsResult.Where(hwnd => filterCallback(hwnd));
121 | }
122 |
123 | return hwndsResult;
124 | }
125 |
126 | public static HashSet GetDescendantWindows(
127 | IntPtr parentHwnd, // Parent HWND for which to find all children and children of children
128 | HwndFilterCallback filterExploreCallback = null, // Delegate return true to explore its children
129 | HwndFilterCallback filterResultCallback = null) // Delegate return true to include in returned list
130 | {
131 | List borderHwnds = new List();
132 | HashSet resultHwnds = new HashSet();
133 |
134 | borderHwnds.Add(parentHwnd);
135 | do
136 | {
137 | // .NET doesn't want us to modify the collection while we enumerate it
138 | // so we have an expandBorderHwnds which contains the next list of border
139 | // HWNDs to examine after we're done with the current list.
140 | List expandBorderHwnds = new List();
141 | foreach (IntPtr borderHwnd in borderHwnds)
142 | {
143 | if (filterExploreCallback == null || filterExploreCallback(borderHwnd))
144 | {
145 | expandBorderHwnds.AddRange(GetChildWindows(borderHwnd));
146 | }
147 | if (filterResultCallback == null || filterResultCallback(borderHwnd))
148 | {
149 | resultHwnds.Add(borderHwnd);
150 | }
151 | }
152 | borderHwnds = expandBorderHwnds;
153 | }
154 | while (borderHwnds.Count > 0);
155 |
156 | return resultHwnds;
157 | }
158 |
159 | public static string GetClassName(IntPtr hwnd)
160 | {
161 | const int bufferSize = 256;
162 | string className = "";
163 | try
164 | {
165 | unsafe
166 | {
167 | char* buffer = stackalloc char[bufferSize];
168 | PInvoke.User32.GetClassName(hwnd, buffer, bufferSize);
169 | className = new string(buffer);
170 | }
171 | }
172 | catch (Exception e)
173 | {
174 | Trace.WriteLine("Exception related to GetClassName " + e);
175 | }
176 | return className;
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/wv2util/Pages/HostAppsPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using System.Timers;
9 | using System.Windows;
10 | using System.Windows.Automation.Peers;
11 | using System.Windows.Automation.Provider;
12 | using System.Windows.Controls;
13 | using System.Windows.Data;
14 | using System.Windows.Documents;
15 | using System.Windows.Input;
16 | using System.Windows.Media;
17 | using System.Windows.Media.Imaging;
18 | using System.Windows.Navigation;
19 | using System.Windows.Shapes;
20 | using System.Windows.Threading;
21 | using wv2util.Pages;
22 | using Timer = System.Timers.Timer;
23 |
24 | namespace wv2util
25 | {
26 | ///
27 | /// Interaction logic for HostAppsPage.xaml
28 | ///
29 | public partial class HostAppsPage : Page, IReloadable
30 | {
31 | private Timer m_watchForChangesTimer = new Timer();
32 | private IEnumerable m_previousHostAppEntries = null;
33 | private readonly SortUtil.SortColumnContext m_hostAppSortColumn = new SortUtil.SortColumnContext();
34 | private HostAppList HostAppsListData => AppState.GetHostAppList();
35 | private HostAppEntry HostAppTreeViewSelectedItem =>
36 | (HostAppEntry)(((HostAppEntryTreeItem)HostAppTreeView?.SelectedItem)?.Model);
37 |
38 | private bool m_reloading = false;
39 | public bool Reloading
40 | {
41 | get => m_reloading;
42 | private set
43 | {
44 | if (value != m_reloading)
45 | {
46 | m_reloading = value;
47 | this.ReloadingChanged?.Invoke(this, new EventArgs());
48 | }
49 | }
50 | }
51 |
52 | public HostAppsPage()
53 | {
54 | InitializeComponent();
55 |
56 | m_watchForChangesTimer.Interval = 3000;
57 | m_watchForChangesTimer.Elapsed += WatchForChangesTimer_Elapsed;
58 | m_watchForChangesTimer.Enabled = true;
59 | }
60 |
61 | private void WatchForChangesTimer_Elapsed(object sender, ElapsedEventArgs e)
62 | {
63 | // When the timer elapses we want to check if there are any new hostt apps or
64 | // old host apps removed.
65 | var currentHostAppEntries = HostAppList.GetHostAppEntriesFromMachineByPipeEnumeration();
66 | // If we haven't run before then previous host app entries is null and we just
67 | // record this run's host app entries to compare against next time's run.
68 | if (m_previousHostAppEntries != null)
69 | {
70 | int previousCount = m_previousHostAppEntries.Count();
71 | // We know there are changes if the count of host apps has changed
72 | bool changed = currentHostAppEntries.Count() != previousCount;
73 | if (!changed)
74 | {
75 | // If they're the same size, then we can check if any entry from one list
76 | // isn't in the other to know if they're equal.
77 | changed = currentHostAppEntries.Any(entry => !m_previousHostAppEntries.Contains(entry));
78 | }
79 |
80 | // If we have seen differences in the host app entries then we want to
81 | // 'click' the refresh button to update the UI.
82 | if (changed)
83 | {
84 | Reload();
85 | }
86 | }
87 | m_previousHostAppEntries = currentHostAppEntries;
88 | }
89 |
90 | private void GridViewColumnHeader_HostApps_Executable_Click(object sender, RoutedEventArgs e)
91 | {
92 | m_hostAppSortColumn.SelectColumn(0);
93 | HostAppsListData.Sort((left, right) =>
94 | m_hostAppSortColumn.SortDirection * SortUtil.CompareStrings(left.ExecutableName, right.ExecutableName));
95 | }
96 |
97 | private void GridViewColumnHeader_HostApps_PID_Click(object sender, RoutedEventArgs e)
98 | {
99 | m_hostAppSortColumn.SelectColumn(1);
100 | HostAppsListData.Sort((left, right) =>
101 | m_hostAppSortColumn.SortDirection * (left.PID - right.PID));
102 | }
103 |
104 | private void GridViewColumnHeader_HostApps_BrowserPID_Click(object sender, RoutedEventArgs e)
105 | {
106 | m_hostAppSortColumn.SelectColumn(2);
107 | HostAppsListData.Sort((left, right) =>
108 | m_hostAppSortColumn.SortDirection * (left.BrowserProcessPID - right.BrowserProcessPID));
109 | }
110 |
111 | private void GridViewColumnHeader_HostApps_StatusDescription_Click(object sender, RoutedEventArgs e)
112 | {
113 | m_hostAppSortColumn.SelectColumn(3);
114 | HostAppsListData.Sort((left, right) =>
115 | m_hostAppSortColumn.SortDirection * (left.Status - right.Status));
116 | }
117 |
118 | public event EventHandler ReloadingChanged;
119 |
120 | private void HostAppsDiscoverSlowlyCheckbox_Checked(object sender, RoutedEventArgs e)
121 | {
122 | Reload();
123 | }
124 |
125 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
126 | {
127 | if (e.Uri.IsFile)
128 | {
129 | ProcessUtil.OpenExplorerToFile(e.Uri.LocalPath);
130 | }
131 | else
132 | {
133 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
134 | }
135 | e.Handled = true;
136 | }
137 |
138 | private void HostAppsCreateReport_Click(object sender, RoutedEventArgs e)
139 | {
140 | HostAppEntry selectedHostAppEntry = HostAppTreeViewSelectedItem;
141 | if (selectedHostAppEntry != null)
142 | {
143 | ReportCreator creator = new ReportCreator(
144 | selectedHostAppEntry,
145 | AppState.GetAppOverrideList(),
146 | AppState.GetRuntimeList());
147 | CreateReportWindow createReportWindow = new CreateReportWindow(Window.GetWindow(this), creator);
148 | createReportWindow.ShowDialog();
149 | }
150 | }
151 |
152 | private void HostAppsGoToOverride_Click(object sender, RoutedEventArgs e)
153 | {
154 | HostAppEntry selectedHostAppEntry = HostAppTreeViewSelectedItem;
155 | if (selectedHostAppEntry != null)
156 | {
157 | Window parent = Window.GetWindow(this);
158 | ((IShowHostAppEntryAsAppOverrideEntry)parent).ShowHostAppEntryAsAppOverrideEntry(selectedHostAppEntry);
159 | }
160 | }
161 |
162 | public void Reload()
163 | {
164 | _ = ReloadInternalAsync();
165 | }
166 |
167 | private async Task ReloadInternalAsync()
168 | {
169 | if (!this.Reloading)
170 | {
171 | this.Reloading = true;
172 | await HostAppsListData.FromMachineAsync();
173 | this.Reloading = false;
174 | }
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/wv2util/ObservableCollectionProjection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Collections.Specialized;
5 | using System.ComponentModel;
6 | using System.Linq;
7 | using System.Runtime.InteropServices;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 |
12 | namespace wv2util
13 | {
14 | // A read only ObservableCollection that wraps an inner ObservableCollection and
15 | // projects the contents of the inner ObservableCollection to a new type.
16 | public class ObservableCollectionProjection : ObservableCollection
17 | where TOuter : class
18 | where TInner : class
19 | {
20 | private ObservableCollection m_innerCollection;
21 | private Func m_projectDelegate;
22 |
23 | private static WeakRefEqualityComparator s_WeakRefEqualityComparatorSingleton = new WeakRefEqualityComparator();
24 | private class WeakRefEqualityComparator : IEqualityComparer>
25 | {
26 | public bool Equals(WeakReference x, WeakReference y)
27 | {
28 | if (x == y)
29 | {
30 | return true;
31 | }
32 | else if (x == null && y == null)
33 | {
34 | return true;
35 | }
36 | else if (x == null || y == null)
37 | {
38 | return false;
39 | }
40 | else
41 | {
42 | TInner xInner;
43 | bool gotX = x.TryGetTarget(out xInner);
44 |
45 | TInner yInner;
46 | bool gotY = y.TryGetTarget(out yInner);
47 |
48 | if (gotX && gotY)
49 | {
50 | if (xInner == null && yInner == null)
51 | {
52 | return true;
53 | }
54 | else if (xInner == null || yInner == null)
55 | {
56 | return false;
57 | }
58 | else
59 | {
60 | return xInner.Equals(yInner);
61 | }
62 | }
63 | else
64 | {
65 | return false;
66 | }
67 | }
68 | }
69 |
70 | public int GetHashCode(WeakReference obj)
71 | {
72 | TInner target;
73 | if (obj != null && obj.TryGetTarget(out target))
74 | {
75 | return target.GetHashCode();
76 | }
77 | return 0;
78 | }
79 | }
80 |
81 | private Dictionary, TOuter> m_innerToOuterCache
82 | = new Dictionary, TOuter>(s_WeakRefEqualityComparatorSingleton);
83 |
84 | private TOuter InnerToOuter(TInner inner)
85 | {
86 | WeakReference innerWeakRef = new WeakReference(inner);
87 | TOuter result;
88 | // clean m_innerToOuterCache of all entries where the WeakReference is no long alive
89 | CleanWeakRefsFromCache();
90 |
91 | if (!m_innerToOuterCache.TryGetValue(innerWeakRef, out result))
92 | {
93 | result = m_projectDelegate.Invoke(inner);
94 | m_innerToOuterCache.Add(innerWeakRef, result);
95 | }
96 |
97 | return result;
98 | }
99 |
100 | public ObservableCollectionProjection(
101 | ObservableCollection innerCollection,
102 | Func projectDelegate)
103 | {
104 | m_innerCollection = innerCollection;
105 | m_projectDelegate = projectDelegate;
106 |
107 | m_innerCollection.CollectionChanged += InnerCollectionChanged;
108 |
109 | var outerCollection = m_innerCollection.Select(i => InnerToOuter(i)).ToArray();
110 | for (int idx = 0; idx < outerCollection.Count(); ++idx)
111 | {
112 | InsertItem(idx, outerCollection[idx]);
113 | }
114 | }
115 |
116 | private void CleanWeakRefsFromCache()
117 | {
118 | if (m_innerToOuterCache != null)
119 | {
120 | var deadWeakRefs = m_innerToOuterCache.Keys.Where(r => !r.TryGetTarget(out _)).ToArray();
121 | foreach (var deadWeakRef in deadWeakRefs)
122 | {
123 | m_innerToOuterCache.Remove(deadWeakRef);
124 | }
125 | }
126 | }
127 |
128 | private void InnerCollectionChanged(object sender, NotifyCollectionChangedEventArgs innerEventArgs)
129 | {
130 | switch (innerEventArgs.Action)
131 | {
132 | case NotifyCollectionChangedAction.Add:
133 | {
134 | var outerNewItems = innerEventArgs.NewItems.Cast().Select(i => InnerToOuter(i)).ToList();
135 | for (int idx = 0; idx < outerNewItems.Count(); ++idx)
136 | {
137 | Insert(innerEventArgs.NewStartingIndex + idx, outerNewItems[idx]);
138 | }
139 | }
140 | break;
141 |
142 | case NotifyCollectionChangedAction.Remove:
143 | {
144 | int count = innerEventArgs.OldItems.Count;
145 | for (int idx = 0; idx < count; ++idx)
146 | {
147 | RemoveAt(innerEventArgs.OldStartingIndex);
148 | }
149 | }
150 | break;
151 |
152 | case NotifyCollectionChangedAction.Move:
153 | {
154 | int count = innerEventArgs.OldItems.Count;
155 | int oldIdx = innerEventArgs.OldStartingIndex;
156 | int newIdx = innerEventArgs.NewStartingIndex;
157 |
158 | for (int idx = 0; idx < count; ++idx)
159 | {
160 | Move(oldIdx + idx, newIdx + idx);
161 | }
162 | }
163 | break;
164 |
165 | case NotifyCollectionChangedAction.Replace:
166 | {
167 | var outerNewItems = innerEventArgs.NewItems.Cast().Select(i => InnerToOuter(i)).ToList();
168 | for (int idx = 0; idx < outerNewItems.Count(); ++idx)
169 | {
170 | SetItem(innerEventArgs.NewStartingIndex + idx, outerNewItems[idx]);
171 | }
172 | }
173 | break;
174 |
175 | case NotifyCollectionChangedAction.Reset:
176 | {
177 | var outerNewItems = m_innerCollection.Cast().Select(i => InnerToOuter(i)).ToList();
178 | int commonCount = Math.Min(outerNewItems.Count, this.Count);
179 | for (int idx = 0; idx < commonCount; ++idx)
180 | {
181 | SetItem(idx, outerNewItems[idx]);
182 | }
183 | // If there are extra items in the current collection trim the end
184 | while (this.Count > outerNewItems.Count)
185 | {
186 | RemoveAt(this.Count - 1);
187 | }
188 | // If there isn't enough space in the current collection append to the end
189 | for (int idx = this.Count; idx < outerNewItems.Count; ++idx)
190 | {
191 | InsertItem(idx, outerNewItems[idx]);
192 | }
193 | }
194 | break;
195 | }
196 | }
197 | }
198 | }
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_13/WebView2Utilities.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | W6hqTXNN0rZmYx+/GYovrD7JfmN1eQLs8xSEPppeYr4=
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 4h1coqXCrwT54aRwOrkPnG+sF/nDEjNJSvVKtY58ERY=
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | R+Wg8QGvQVHX8T0ta/qbhH1bXkqY0fRnS3wBV3J0bN8=
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | OQajOQoVO6JH519bI3I0Mdg/rRw9QOTewVa1dYgXcxU=dRKTJwFwZKSCHReL77a3i0+gBe0GW0Y69JLIhwtKOzBpTrOFOfx4/dxAGsEL+KaCQrjvQ/Txzq7IKPn22SPgyYQ45dKljF82CYMmQzSF45eN+Ju2sT6ifEG4eb9PHXU9Vy03+bA9Ye+BBzxqsmPwx7fu3aBZdG3a7pi5T7KiqTA=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABCN=NTDEV\davris9UN+kyxADlCtQO9OvFqKM2G0oD0kPaXlwsfPQl4dGD0=fD7uHqZwRgpya7G021ezE/iRDp/B7sOK67FM885jfcUW0+vUSVfQGhgg4nh56RLk4eRXd0rfJK480K4sgHwUqjyhMTrdyOXcWeKqVxrRZgUxmarBJiA/eq80HLOznH+sn/sQdpTFqw97/ZOCNp4JdW2w9F/TgnWSlTUhqE+TrUs=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABMIIByTCCATKgAwIBAgIQKnRXgMgm5YNDxv8o9Im9iDANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwHhcNMjEwMzI4MDEyNTI1WhcNMjIwMzI4MDcyNTI1WjAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkNK10d4VvcZ6DzAK2Wwf/iKGA2gj3MdRrCkvOqc3tXqX32RhUUWbKrzcZfi/UmqMrD5bIflQYuFe+cOkMcvFa1G57VnzKNo54+uL66YJgHSI+cazyjKe4c+v/IudU+N/UTGsjSZfYyemm95dUA/lhPeJkSkKT3V/H07FPVn68RAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAiyG3/kh7ZFBZ6Sf+Nsc+rLFtvjgppBYasfUV2sQOfFLhoTkHJJUihNL1gV0TZnX9ZSWUMUXCkfZhHDtdllN41pospNK+D8w4aZ4wvH2FBYWBBCSSXPwIiGGVLYseTQtOzYXO5NDZHTDwGtc660um0PS0pcS884xiOXt9OUcAUmE=
--------------------------------------------------------------------------------
/install/Application Files/WebView2Utilities_1_0_0_14/WebView2Utilities.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ixxUjvRPDyBgTHticeYlLvl1Y+3PIbkpFNw8+NqbPpw=
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 4h1coqXCrwT54aRwOrkPnG+sF/nDEjNJSvVKtY58ERY=
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | X+GtgC9o18R9u9jmAWK6iKuu0WLaXTgchdPkk1MRli4=
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | LO4vAu3OawcAlmutQXgBfJgywYUAaeKk/AOainHQL94=ENNKyCd/muygzW7uRju7g5ZseeR3d3OJ1P/xEh8wNvnGpkJTW4mWKwynGDfvF/M0mlleW8svgObVe3FvBWT1f/7yIfMCvTXktiLN3S031Mm1eSY6hgddcwUAFhsLh+eUZyap1Dgw/jOcq8q8c8OnzLeeL8Ecbv89wMREZ0+kKww=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABCN=NTDEV\davrisU+m5wnDr+kBW13+8du5i+5VNpewMpy0LJD0+Fn4nypw=TY0ffCrUKyWpQYET3MHYjdOptalXNvBb8lReqKkpa6nfnn0JJtsh/hZJKHCqFF+7uFXtr2rYgf6IZcu6uibpdPLz05qcAgv8mIWXNWYSCzmJEwdbP5We0nvZtY6vnZD/KloGi64U6zAggiDgP3q8UM7FdnCbnR8389D09BY/wk0=yQ0rXR3hW9xnoPMArZbB/+IoYDaCPcx1GsKS86pze1epffZGFRRZsqvNxl+L9SaoysPlsh+VBi4V75w6Qxy8VrUbntWfMo2jnj64vrpgmAdIj5xrPKMp7hz6/8i51T439RMayNJl9jJ6ab3l1QD+WE94mRKQpPdX8fTsU9WfrxE=AQABMIIByTCCATKgAwIBAgIQKnRXgMgm5YNDxv8o9Im9iDANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwHhcNMjEwMzI4MDEyNTI1WhcNMjIwMzI4MDcyNTI1WjAjMSEwHwYDVQQDHhgATgBUAEQARQBWAFwAZABhAHYAcgBpAHMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkNK10d4VvcZ6DzAK2Wwf/iKGA2gj3MdRrCkvOqc3tXqX32RhUUWbKrzcZfi/UmqMrD5bIflQYuFe+cOkMcvFa1G57VnzKNo54+uL66YJgHSI+cazyjKe4c+v/IudU+N/UTGsjSZfYyemm95dUA/lhPeJkSkKT3V/H07FPVn68RAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAiyG3/kh7ZFBZ6Sf+Nsc+rLFtvjgppBYasfUV2sQOfFLhoTkHJJUihNL1gV0TZnX9ZSWUMUXCkfZhHDtdllN41pospNK+D8w4aZ4wvH2FBYWBBCSSXPwIiGGVLYseTQtOzYXO5NDZHTDwGtc660um0PS0pcS884xiOXt9OUcAUmE=
--------------------------------------------------------------------------------