From 9af41c7562f9a6b0fa4458d8cff62388494aa501 Mon Sep 17 00:00:00 2001 From: "karmanov.m@aicrobotics.ru" Date: Wed, 16 Aug 2023 23:39:56 +0300 Subject: [PATCH] Initial commit --- .gitattributes | 63 +++ .github/workflows/produce_vsix_release.yml | 111 ++++++ .gitignore | 369 ++++++++++++++++++ CHANGELOG | 6 + HexVisualizer.sln | 37 ++ HexVisualizer/ByteArrayVisualizer.cs | 55 +++ HexVisualizer/HexHelper.cs | 55 +++ HexVisualizer/HexVisualizer.csproj | 84 ++++ HexVisualizer/HexVisualizer.ico | Bin 0 -> 7886 bytes HexVisualizer/Properties/AssemblyInfo.cs | 36 ++ HexVisualizer/RadioButtonEx.cs | 18 + HexVisualizer/StringTypeChooser.cs | 94 +++++ HexVisualizer/StringTypeChooser.designer.cs | 140 +++++++ HexVisualizer/StringTypeChooser.resx | 120 ++++++ HexVisualizer/StringTypeChooserResult.cs | 17 + HexVisualizer/StringVisualizer.cs | 65 +++ HexVisualizer/frmEditor.cs | 284 ++++++++++++++ HexVisualizer/frmEditor.designer.cs | 232 +++++++++++ HexVisualizer/frmEditor.resx | 282 +++++++++++++ HexVisualizer/packages.config | 4 + LICENSE | 21 + README.md | 55 +++ TestHexVisualizer/App.config | 6 + TestHexVisualizer/Program.cs | 39 ++ TestHexVisualizer/Properties/AssemblyInfo.cs | 36 ++ TestHexVisualizer/TestHexVisualizer.csproj | 60 +++ VsixHexVisualizer/Properties/AssemblyInfo.cs | 16 + .../Properties/Resources.Designer.cs | 73 ++++ VsixHexVisualizer/Properties/Resources.resx | 124 ++++++ .../Resources/VisualizerPackage.ico | Bin 0 -> 428446 bytes VsixHexVisualizer/Resources/script_binary.ico | Bin 0 -> 4286 bytes VsixHexVisualizer/VSPackage.resx | 263 +++++++++++++ VsixHexVisualizer/VisualizerPackage.cs | 109 ++++++ VsixHexVisualizer/VsixHexVisualizer.csproj | 111 ++++++ VsixHexVisualizer/index.html | 26 ++ .../source.extension.vsixmanifest | 32 ++ VsixHexVisualizer/stylesheet.css | 129 ++++++ img/HexVisualizer.png | Bin 0 -> 42173 bytes img/TypeChooser.png | Bin 0 -> 3763 bytes img/WatchWindow.png | Bin 0 -> 12245 bytes vsixsigntool.exe | Bin 0 -> 64512 bytes 41 files changed, 3172 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/workflows/produce_vsix_release.yml create mode 100644 .gitignore create mode 100644 CHANGELOG create mode 100644 HexVisualizer.sln create mode 100644 HexVisualizer/ByteArrayVisualizer.cs create mode 100644 HexVisualizer/HexHelper.cs create mode 100644 HexVisualizer/HexVisualizer.csproj create mode 100644 HexVisualizer/HexVisualizer.ico create mode 100644 HexVisualizer/Properties/AssemblyInfo.cs create mode 100644 HexVisualizer/RadioButtonEx.cs create mode 100644 HexVisualizer/StringTypeChooser.cs create mode 100644 HexVisualizer/StringTypeChooser.designer.cs create mode 100644 HexVisualizer/StringTypeChooser.resx create mode 100644 HexVisualizer/StringTypeChooserResult.cs create mode 100644 HexVisualizer/StringVisualizer.cs create mode 100644 HexVisualizer/frmEditor.cs create mode 100644 HexVisualizer/frmEditor.designer.cs create mode 100644 HexVisualizer/frmEditor.resx create mode 100644 HexVisualizer/packages.config create mode 100644 LICENSE create mode 100644 README.md create mode 100644 TestHexVisualizer/App.config create mode 100644 TestHexVisualizer/Program.cs create mode 100644 TestHexVisualizer/Properties/AssemblyInfo.cs create mode 100644 TestHexVisualizer/TestHexVisualizer.csproj create mode 100644 VsixHexVisualizer/Properties/AssemblyInfo.cs create mode 100644 VsixHexVisualizer/Properties/Resources.Designer.cs create mode 100644 VsixHexVisualizer/Properties/Resources.resx create mode 100644 VsixHexVisualizer/Resources/VisualizerPackage.ico create mode 100644 VsixHexVisualizer/Resources/script_binary.ico create mode 100644 VsixHexVisualizer/VSPackage.resx create mode 100644 VsixHexVisualizer/VisualizerPackage.cs create mode 100644 VsixHexVisualizer/VsixHexVisualizer.csproj create mode 100644 VsixHexVisualizer/index.html create mode 100644 VsixHexVisualizer/source.extension.vsixmanifest create mode 100644 VsixHexVisualizer/stylesheet.css create mode 100644 img/HexVisualizer.png create mode 100644 img/TypeChooser.png create mode 100644 img/WatchWindow.png create mode 100644 vsixsigntool.exe diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/workflows/produce_vsix_release.yml b/.github/workflows/produce_vsix_release.yml new file mode 100644 index 0000000..3e8aba6 --- /dev/null +++ b/.github/workflows/produce_vsix_release.yml @@ -0,0 +1,111 @@ +name: Build, pack and release + +on: + push: + branches: + - master + paths: + - "**/*.cs" + - "**/*.csproj" + - "**/*.vsixmanifest" + - ".github/workflows/**" + +concurrency: + group: proj-${{ github.head_ref }} + cancel-in-progress: true + +jobs: + + build_sign_vsix: + name: Build, pack and sign VSIX + runs-on: windows-latest + outputs: + release_ver: ${{ steps.proj_version.outputs.newVersion }} + + steps: + - uses: actions/checkout@v3 + - uses: nuget/setup-nuget@v1 + - uses: microsoft/setup-msbuild@v1.1 + with: + vs-version: '[17.0,18.0)' + msbuild-architecture: x64 + + - name: Parse project assembly version + id: proj_version + uses: vers-one/dotnet-project-version-updater@v1.3 + with: + file: "VsixHexVisualizer/Properties/AssemblyInfo.cs" + version: '*.*.*.*' + + - name: Download NuGet dependencies + run: nuget restore + + - name: Build VSIX + id: build_vsix + run: msbuild .\HexVisualizer.sln /p:Configuration=Release /p:DeployExtension=false /p:ZipPackageCompressionLevel=normal + + - name: Upload unsigned VSIX + uses: actions/upload-artifact@v2 + with: + name: uploaded_unsigned_vsix + path: .\build\VsixHexVisualizer\Release\VsixHexVisualizer.vsix + + - name: Checkout private key repo + uses: actions/checkout@v3 + with: + repository: ${{ secrets.KEYSTORE_GIT_REPOSITORY }} + token: ${{ secrets.KEYSTORE_ACCESS_TOKEN }} + path: .\private + + - name: Sign VSIX + run: .\vsixsigntool.exe sign /f private\private.pfx /p ${{ secrets.PRIVATE_SIGN_KEY_PASSWORD }} /fd sha256 /v build\VsixHexVisualizer\Release\VsixHexVisualizer.vsix + + - name: Upload signed VSIX + uses: actions/upload-artifact@v2 + with: + name: uploaded_signed_vsix + path: .\build\VsixHexVisualizer\Release\VsixHexVisualizer.vsix + + release: + name: Make Github release draft with built artifact + needs: build_sign_vsix + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_BUILD_TOKEN }} + RELEASE_VERSION: ${{ needs.build_sign_vsix.outputs.release_ver }} + + steps: + - name: Create Release + id: create_release + uses: actions/create-release@v1 + + with: + tag_name: ${{ env.RELEASE_VERSION }} + release_name: ${{ github.event.repository.name }} ${{ env.RELEASE_VERSION }} + draft: true + + - name: Download unsigned artifact + uses: actions/download-artifact@v2 + with: + name: uploaded_unsigned_vsix + + - name: Upload unsigned artifact to release assets + uses: actions/upload-release-asset@v1.0.1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: VsixHexVisualizer.vsix + asset_name: ${{ github.event.repository.name }} ${{ env.RELEASE_VERSION }}-unsigned.vsix + asset_content_type: application/zip + + - name: Download signed artifact + uses: actions/download-artifact@v2 + with: + name: uploaded_signed_vsix + + - name: Upload signed artifact to release assets + uses: actions/upload-release-asset@v1.0.1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: VsixHexVisualizer.vsix + asset_name: ${{ github.event.repository.name }} ${{ env.RELEASE_VERSION }}-signed.vsix + asset_content_type: application/zip \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..91b8a1f --- /dev/null +++ b/.gitignore @@ -0,0 +1,369 @@ +# Custom (user-defined) +private/ +private/* +build/ +build/* + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..a6eff8f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,6 @@ +## Version 1.5.0.5 +**13.08.23** + +- Add LICENSE +- Updating project dependencies +- VS 2022 support (Community & Pro) \ No newline at end of file diff --git a/HexVisualizer.sln b/HexVisualizer.sln new file mode 100644 index 0000000..e5a5575 --- /dev/null +++ b/HexVisualizer.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33205.214 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexVisualizer", "HexVisualizer\HexVisualizer.csproj", "{80073486-57A2-4B96-B730-C3DF0792F766}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestHexVisualizer", "TestHexVisualizer\TestHexVisualizer.csproj", "{88EC115A-C8AC-402E-B4DF-0642DAE5CCF0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VsixHexVisualizer", "VsixHexVisualizer\VsixHexVisualizer.csproj", "{59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {80073486-57A2-4B96-B730-C3DF0792F766}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80073486-57A2-4B96-B730-C3DF0792F766}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80073486-57A2-4B96-B730-C3DF0792F766}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80073486-57A2-4B96-B730-C3DF0792F766}.Release|Any CPU.Build.0 = Release|Any CPU + {88EC115A-C8AC-402E-B4DF-0642DAE5CCF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {88EC115A-C8AC-402E-B4DF-0642DAE5CCF0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {88EC115A-C8AC-402E-B4DF-0642DAE5CCF0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {88EC115A-C8AC-402E-B4DF-0642DAE5CCF0}.Release|Any CPU.Build.0 = Release|Any CPU + {59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {29A1D7F8-CAE4-485E-A28A-286B92F5FD53} + EndGlobalSection +EndGlobal diff --git a/HexVisualizer/ByteArrayVisualizer.cs b/HexVisualizer/ByteArrayVisualizer.cs new file mode 100644 index 0000000..1acebf2 --- /dev/null +++ b/HexVisualizer/ByteArrayVisualizer.cs @@ -0,0 +1,55 @@ +using System; +using System.Windows.Forms; +using Microsoft.VisualStudio.DebuggerVisualizers; + +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof(HexVisualizer.ByteArrayVisualizer), + typeof(VisualizerObjectSource), + Target = typeof(WeakReference), + Description = "Hex Visualizer")] +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof(HexVisualizer.ByteArrayVisualizer), + typeof(VisualizerObjectSource), + Target = typeof(WeakReference), + Description = "Hex Visualizer")] +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof(HexVisualizer.ByteArrayVisualizer), + typeof(VisualizerObjectSource), + Target = typeof(byte[]), + Description = "Hex Visualizer")] +namespace HexVisualizer +{ + public class ByteArrayVisualizer : DialogDebuggerVisualizer + { + protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider) + { + byte[] obj = null; + + if (objectProvider.GetObject() is WeakReference) + { + (objectProvider.GetObject() as WeakReference).TryGetTarget(out obj); + } + + if (objectProvider.GetObject() is WeakReference) + obj = (objectProvider.GetObject() as WeakReference).Target as byte[]; + + else if (objectProvider.GetObject() is byte[]) + obj = objectProvider.GetObject() as byte[]; + + if(obj != null) + { + frmEditor.Visualize(obj); + } + else + { + MessageBox.Show("Only WeakReference of byte[] allowed"); + } + } + + public static void TestShowVisualizer(object objectToVisualize) + { + VisualizerDevelopmentHost visualizerHost = new VisualizerDevelopmentHost(objectToVisualize, typeof(ByteArrayVisualizer)); + visualizerHost.ShowVisualizer(); + } + } +} diff --git a/HexVisualizer/HexHelper.cs b/HexVisualizer/HexHelper.cs new file mode 100644 index 0000000..7c77351 --- /dev/null +++ b/HexVisualizer/HexHelper.cs @@ -0,0 +1,55 @@ +using System; +using System.Text.RegularExpressions; + +namespace HexVisualizer +{ + public static class HexHelper + { + static Regex regexHex = new Regex(@"\A\b(0[xX]){0,1}[0-9a-fA-F]+\b\Z", RegexOptions.Compiled); //@"\A\b(0[xX])?[0-9a-fA-F]+\b\Z" + public static byte[] ToByteArray(this string hex) + { + if(hex.Length % 2 == 1) + { + throw new ArgumentOutOfRangeException("hex", "The hex string cannot have an odd number of digits"); + } + + if(!regexHex.IsMatch(hex)) + { + throw new ArgumentOutOfRangeException("hex", "The hex string contains non hex values"); + } + + if (hex.Substring(0,2).ToLower() == "0x") + { + hex = hex.Remove(0, 2); + } + + byte[] arr = new byte[hex.Length >> 1]; + + for(int i = 0; i < hex.Length >> 1; ++i) + { + arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); + } + + return arr; + } + + public static string ToHexString(this byte[] data) + { + return BitConverter.ToString(data); + } + + private static int GetHexVal(char hex) + { + int val = (int)hex; + //For uppercase A-F letters: + //return val - (val < 58 ? 48 : 55); + + //For lowercase a-f letters: + //return val - (val < 58 ? 48 : 87); + + //Or the two combined, but a bit slower: + return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); + } + + } +} diff --git a/HexVisualizer/HexVisualizer.csproj b/HexVisualizer/HexVisualizer.csproj new file mode 100644 index 0000000..1dedd2f --- /dev/null +++ b/HexVisualizer/HexVisualizer.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {80073486-57A2-4B96-B730-C3DF0792F766} + Library + Properties + HexVisualizer + HexVisualizer + v4.8 + 512 + true + + + true + full + false + ..\build\HexVisualizer\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\build\HexVisualizer\Release\ + TRACE + prompt + 4 + + + + ..\packages\Be.Windows.Forms.HexBox.1.6.1\lib\net40\Be.Windows.Forms.HexBox.dll + + + + + + + + + + + + + + + + + Form + + + frmEditor.cs + + + + + + Form + + + StringTypeChooser.cs + + + + + + + + + + + + + frmEditor.cs + + + StringTypeChooser.cs + + + + \ No newline at end of file diff --git a/HexVisualizer/HexVisualizer.ico b/HexVisualizer/HexVisualizer.ico new file mode 100644 index 0000000000000000000000000000000000000000..710eb36b13dd9346803457ed6cfb7570b55d287d GIT binary patch literal 7886 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 H^8UX8w5rC^ literal 0 HcmV?d00001 diff --git a/HexVisualizer/Properties/AssemblyInfo.cs b/HexVisualizer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bbb5b58 --- /dev/null +++ b/HexVisualizer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Общие сведения об этой сборке предоставляются следующим набором +// набора атрибутов. Измените значения этих атрибутов для изменения сведений, +// связанные со сборкой. +[assembly: AssemblyTitle("HexVisualizer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HexVisualizer")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("80073486-57a2-4b96-b730-c3df0792f766")] + +// Сведения о версии сборки состоят из указанных ниже четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.5.0.5")] +[assembly: AssemblyFileVersion("1.5.0.5")] diff --git a/HexVisualizer/RadioButtonEx.cs b/HexVisualizer/RadioButtonEx.cs new file mode 100644 index 0000000..133043b --- /dev/null +++ b/HexVisualizer/RadioButtonEx.cs @@ -0,0 +1,18 @@ +using System.Windows.Forms; + +namespace HexVisualizer +{ + public static class RadioButtonEx + { + public static void AllowDoubleClick(this RadioButton rb, MouseEventHandler MouseDoubleClick) + { + // + // Allow double clicking of radios + System.Reflection.MethodInfo m = typeof(RadioButton).GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); + if(m != null) + m.Invoke(rb, new object[] { ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true }); + + rb.MouseDoubleClick += MouseDoubleClick; + } + } +} diff --git a/HexVisualizer/StringTypeChooser.cs b/HexVisualizer/StringTypeChooser.cs new file mode 100644 index 0000000..5ffe29d --- /dev/null +++ b/HexVisualizer/StringTypeChooser.cs @@ -0,0 +1,94 @@ +using System; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace HexVisualizer +{ + public partial class StringTypeChooser : Form + { + public StringTypeChooser() + { + InitializeComponent(); + + var encodings = (from enc in Encoding.GetEncodings() + select new + { + DisplayName = $"{enc.CodePage} - {enc.DisplayName}", + EncodingInfo = enc, + enc.CodePage + }) + .ToList(); + + uiEncoding.DisplayMember = "DisplayName"; + uiEncoding.ValueMember = "CodePage"; + uiEncoding.DataSource = encodings; + uiEncoding.SelectedValue = Encoding.Default.CodePage; + uiEncoding.Enabled = false; + + uiRadio_Hex.AllowDoubleClick(DoubleClickRadioButton); + uiRadio_Base64.AllowDoubleClick(DoubleClickRadioButton); + uiRadio_Encoding.AllowDoubleClick(DoubleClickRadioButton); + } + + private void StringTypeChooser_Load(object sender, EventArgs e) + { + + } + + public static StringTypeChooserResult GetStringType(string objString) + { + Regex rHexString = new Regex("^(0x){0,1}[0-9a-fA-F]+$", RegexOptions.Compiled); + Regex rBase64 = new Regex("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$", RegexOptions.Compiled); + + var f = new StringTypeChooser(); + + //try be clever about a default chosen option + if(rHexString.IsMatch(objString)) + { + f.uiRadio_Hex.Checked = true; + } + else if(rBase64.IsMatch(objString)) + { + f.uiRadio_Base64.Checked = true; + } + else + { + f.uiRadio_Encoding.Checked = true; + } + + + var r = f.ShowDialog(); + + if(r == DialogResult.OK) + { + return new StringTypeChooserResult() + { + ResultType = f.uiRadio_Hex.Checked + ? StringTypeChooserResult.ResultTypeEnum.HexString + : f.uiRadio_Base64.Checked ? StringTypeChooserResult.ResultTypeEnum.Base64String + : StringTypeChooserResult.ResultTypeEnum.Encoding, + Encoding = f.uiRadio_Encoding.Checked ? Encoding.GetEncoding((int)f.uiEncoding.SelectedValue) : null + }; + } + else + { + return null; + } + } + + private void uiRadio_CheckedChanged(object sender, EventArgs e) + { + uiEncoding.Enabled = uiRadio_Encoding.Checked; + uiOkButton.Enabled = uiRadio_Base64.Checked || uiRadio_Hex.Checked || uiRadio_Encoding.Checked; + } + + private void DoubleClickRadioButton(object sender, MouseEventArgs e) + { + (sender as RadioButton).Select(); + uiOkButton.PerformClick(); + } + } +} diff --git a/HexVisualizer/StringTypeChooser.designer.cs b/HexVisualizer/StringTypeChooser.designer.cs new file mode 100644 index 0000000..bfae5c4 --- /dev/null +++ b/HexVisualizer/StringTypeChooser.designer.cs @@ -0,0 +1,140 @@ +namespace HexVisualizer +{ + partial class StringTypeChooser + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.uiRadio_Hex = new System.Windows.Forms.RadioButton(); + this.uiRadio_Base64 = new System.Windows.Forms.RadioButton(); + this.uiRadio_Encoding = new System.Windows.Forms.RadioButton(); + this.uiEncoding = new System.Windows.Forms.ComboBox(); + this.uiCancelButton = new System.Windows.Forms.Button(); + this.uiOkButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // uiRadio_Hex + // + this.uiRadio_Hex.AutoSize = true; + this.uiRadio_Hex.Location = new System.Drawing.Point(12, 12); + this.uiRadio_Hex.Name = "uiRadio_Hex"; + this.uiRadio_Hex.Size = new System.Drawing.Size(72, 17); + this.uiRadio_Hex.TabIndex = 0; + this.uiRadio_Hex.TabStop = true; + this.uiRadio_Hex.Text = "Hex string"; + this.uiRadio_Hex.UseVisualStyleBackColor = true; + this.uiRadio_Hex.CheckedChanged += new System.EventHandler(this.uiRadio_CheckedChanged); + // + // uiRadio_Base64 + // + this.uiRadio_Base64.AutoSize = true; + this.uiRadio_Base64.Location = new System.Drawing.Point(12, 53); + this.uiRadio_Base64.Name = "uiRadio_Base64"; + this.uiRadio_Base64.Size = new System.Drawing.Size(91, 17); + this.uiRadio_Base64.TabIndex = 1; + this.uiRadio_Base64.TabStop = true; + this.uiRadio_Base64.Text = "Base64 String"; + this.uiRadio_Base64.UseVisualStyleBackColor = true; + this.uiRadio_Base64.CheckedChanged += new System.EventHandler(this.uiRadio_CheckedChanged); + // + // uiRadio_Encoding + // + this.uiRadio_Encoding.AutoSize = true; + this.uiRadio_Encoding.Location = new System.Drawing.Point(12, 92); + this.uiRadio_Encoding.Name = "uiRadio_Encoding"; + this.uiRadio_Encoding.Size = new System.Drawing.Size(98, 17); + this.uiRadio_Encoding.TabIndex = 2; + this.uiRadio_Encoding.TabStop = true; + this.uiRadio_Encoding.Text = "Encoded String"; + this.uiRadio_Encoding.UseVisualStyleBackColor = true; + this.uiRadio_Encoding.CheckedChanged += new System.EventHandler(this.uiRadio_CheckedChanged); + // + // uiEncoding + // + this.uiEncoding.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.uiEncoding.FormattingEnabled = true; + this.uiEncoding.Location = new System.Drawing.Point(31, 115); + this.uiEncoding.Name = "uiEncoding"; + this.uiEncoding.Size = new System.Drawing.Size(241, 21); + this.uiEncoding.TabIndex = 3; + // + // uiCancelButton + // + this.uiCancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.uiCancelButton.Location = new System.Drawing.Point(116, 173); + this.uiCancelButton.Name = "uiCancelButton"; + this.uiCancelButton.Size = new System.Drawing.Size(75, 23); + this.uiCancelButton.TabIndex = 4; + this.uiCancelButton.Text = "C&ancel"; + this.uiCancelButton.UseVisualStyleBackColor = true; + // + // uiOkButton + // + this.uiOkButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.uiOkButton.Enabled = false; + this.uiOkButton.Location = new System.Drawing.Point(197, 173); + this.uiOkButton.Name = "uiOkButton"; + this.uiOkButton.Size = new System.Drawing.Size(75, 23); + this.uiOkButton.TabIndex = 5; + this.uiOkButton.Text = "&Ok"; + this.uiOkButton.UseVisualStyleBackColor = true; + // + // StringTypeChooser + // + this.AcceptButton = this.uiOkButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.uiCancelButton; + this.ClientSize = new System.Drawing.Size(284, 209); + this.ControlBox = false; + this.Controls.Add(this.uiOkButton); + this.Controls.Add(this.uiCancelButton); + this.Controls.Add(this.uiEncoding); + this.Controls.Add(this.uiRadio_Encoding); + this.Controls.Add(this.uiRadio_Base64); + this.Controls.Add(this.uiRadio_Hex); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "StringTypeChooser"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "StringTypeChooser"; + this.Load += new System.EventHandler(this.StringTypeChooser_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.RadioButton uiRadio_Hex; + private System.Windows.Forms.RadioButton uiRadio_Base64; + private System.Windows.Forms.RadioButton uiRadio_Encoding; + private System.Windows.Forms.ComboBox uiEncoding; + private System.Windows.Forms.Button uiCancelButton; + private System.Windows.Forms.Button uiOkButton; + } +} \ No newline at end of file diff --git a/HexVisualizer/StringTypeChooser.resx b/HexVisualizer/StringTypeChooser.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/HexVisualizer/StringTypeChooser.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/HexVisualizer/StringTypeChooserResult.cs b/HexVisualizer/StringTypeChooserResult.cs new file mode 100644 index 0000000..16fdb11 --- /dev/null +++ b/HexVisualizer/StringTypeChooserResult.cs @@ -0,0 +1,17 @@ +using System.Text; + +namespace HexVisualizer +{ + public class StringTypeChooserResult + { + public enum ResultTypeEnum + { + HexString, + Base64String, + Encoding + } + + public ResultTypeEnum ResultType { get; set; } + public Encoding Encoding { get; set; } + } +} diff --git a/HexVisualizer/StringVisualizer.cs b/HexVisualizer/StringVisualizer.cs new file mode 100644 index 0000000..098fd58 --- /dev/null +++ b/HexVisualizer/StringVisualizer.cs @@ -0,0 +1,65 @@ +using System; +using System.Windows.Forms; +using Microsoft.VisualStudio.DebuggerVisualizers; + +[assembly: System.Diagnostics.DebuggerVisualizer( + typeof(HexVisualizer.StringVisualizer), + typeof(VisualizerObjectSource), + Target = typeof(string), + Description = "Hex Visualizer (String)")] +namespace HexVisualizer +{ + public class StringVisualizer : DialogDebuggerVisualizer + { + protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider) + { + try + { + byte[] obj = null; + + string objectString = objectProvider.GetObject() as string; + + var r = StringTypeChooser.GetStringType(objectString); + + if(r == null) return; + + + switch(r.ResultType) + { + case StringTypeChooserResult.ResultTypeEnum.HexString: + obj = objectString.ToByteArray(); + break; + + case StringTypeChooserResult.ResultTypeEnum.Base64String: + obj = Convert.FromBase64String(objectString); + break; + + case StringTypeChooserResult.ResultTypeEnum.Encoding: + obj = r.Encoding.GetBytes(objectString); + break; + + } + + if(obj != null) + { + frmEditor.Visualize(obj); + } + else + { + MessageBox.Show("String could not be converted"); + } + } + catch (Exception ex) + { + MessageBox.Show($"Error converting string: {ex.Message}"); + + } + } + + public static void TestShowVisualizer(object objectToVisualize) + { + VisualizerDevelopmentHost visualizerHost = new VisualizerDevelopmentHost(objectToVisualize, typeof(StringVisualizer)); + visualizerHost.ShowVisualizer(); + } + } +} diff --git a/HexVisualizer/frmEditor.cs b/HexVisualizer/frmEditor.cs new file mode 100644 index 0000000..7ffe72f --- /dev/null +++ b/HexVisualizer/frmEditor.cs @@ -0,0 +1,284 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Be.Windows.Forms; + +namespace HexVisualizer +{ + public partial class frmEditor : Form + { + bool newFind = true; + public frmEditor() + { + InitializeComponent(); + } + + internal static void Visualize(byte[] p) + { + var frm = new frmEditor(); + + var provider = new DynamicByteProvider(p); + + frm.textBox1.ByteProvider = provider; + + frm.ShowDialog(); + } + + private void textBox1_SelectionLengthChanged(object sender, EventArgs e) + { + UpdateStatusBar(); + ShowInfo(); + + } + + private void textBox1_SelectionStartChanged(object sender, EventArgs e) + { + UpdateStatusBar(); + ShowInfo(); + } + + private void ShowInfo() + { + listView1.BeginUpdate(); + listView1.Items.Clear(); + + try + { + switch(textBox1.SelectionLength) + { + case 1: + { + // byte + var item = listView1.Items.Add("Type", "Type"); + item.SubItems.Add("Byte"); + + break; + } + case 2: + { + // short + var item = listView1.Items.Add("Type", "Type"); + item.SubItems.Add("Short/UShort (2 Bytes)"); + + var bytes = getSelectedBytes(2); + + item = listView1.Items.Add("Short (Big Endian)"); + item.SubItems.Add(BitConverter.ToInt16(bytes, 0).ToString()); + + item = listView1.Items.Add("UShort (Big Endian)"); + item.SubItems.Add(BitConverter.ToUInt16(bytes, 0).ToString()); + + Array.Reverse(bytes); + + item = listView1.Items.Add("Short (Little Endian)"); + item.SubItems.Add(BitConverter.ToInt16(bytes, 0).ToString()); + + item = listView1.Items.Add("UShort (Little Endian)"); + item.SubItems.Add(BitConverter.ToUInt16(bytes, 0).ToString()); + + + break; + } + case 4: + { + // int/uint + var item = listView1.Items.Add("Type", "Type"); + item.SubItems.Add("Int/Uint (4 Bytes)"); + + var bytes = getSelectedBytes(4); + + item = listView1.Items.Add("Int (Big Endian)"); + item.SubItems.Add(BitConverter.ToInt32(bytes, 0).ToString()); + + item = listView1.Items.Add("UInt (Big Endian)"); + item.SubItems.Add(BitConverter.ToUInt32(bytes, 0).ToString()); + + Array.Reverse(bytes); + + item = listView1.Items.Add("Int (Little Endian)"); + item.SubItems.Add(BitConverter.ToInt32(bytes, 0).ToString()); + + item = listView1.Items.Add("UInt (Litle Endian)"); + item.SubItems.Add(BitConverter.ToUInt32(bytes, 0).ToString()); + + break; + } + case 8: + { + // long/ulong + var item = listView1.Items.Add("Type", "Type"); + item.SubItems.Add("Long/ULong (8 Bytes)"); + + var bytes = getSelectedBytes(8); + + item = listView1.Items.Add("Long (Big Endian)"); + item.SubItems.Add(BitConverter.ToInt64(bytes, 0).ToString()); + + item = listView1.Items.Add("ULong (Big Endian)"); + item.SubItems.Add(BitConverter.ToUInt64(bytes, 0).ToString()); + + Array.Reverse(bytes); + + item = listView1.Items.Add("Long (Little Endian)"); + item.SubItems.Add(BitConverter.ToInt64(bytes, 0).ToString()); + + item = listView1.Items.Add("ULong (Little Endian)"); + item.SubItems.Add(BitConverter.ToUInt64(bytes, 0).ToString()); + + break; + } + + default: + { + var item = listView1.Items.Add("Type", "Type"); + item.SubItems.Add(string.Format("Unknown ({0} Bytes)", textBox1.SelectionLength)); + + break; + } + } + + var b = getSelectedBytes((int)textBox1.SelectionLength); + + var i = listView1.Items.Add("ASCII", "ASCII"); + i.SubItems.Add(ASCIIEncoding.Default.GetString(b)); + + i = listView1.Items.Add("UTF8", "UTF8"); + i.SubItems.Add(UTF8Encoding.UTF8.GetString(b)); + + i = listView1.Items.Add("UTF32", "UTF32"); + i.SubItems.Add(UTF32Encoding.UTF32.GetString(b)); + + i = listView1.Items.Add("Bytes", "Bytes"); + i.SubItems.Add("0x" + BitConverter.ToString(b).Replace("-", "")); + } + catch(Exception ex) + { + listView1.Items.Add("Error", "Error: " + ex.Message); + } + + listView1.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.HeaderSize); + listView1.EndUpdate(); + + } + + private byte[] getSelectedBytes(int len) + { + var p = textBox1.ByteProvider; + + var b = new byte[len]; + + for(int i = 0; i < len; i++) + { + b[i] = p.ReadByte(textBox1.SelectionStart + i); + } + + return b; + } + + private void UpdateStatusBar() + { + var sb = new StringBuilder(); + + if(textBox1.SelectionLength > 0) + { + sb.AppendFormat("Selected index {0} to {1}, ", textBox1.SelectionStart, textBox1.SelectionStart + textBox1.SelectionLength - 1); + } + sb.AppendFormat("Current index {0} (Line {1} Column {2})", (textBox1.CurrentLine - 1) * 16 + textBox1.CurrentPositionInLine - 1, textBox1.CurrentLine, textBox1.CurrentPositionInLine); + + uiPosition.Text = sb.ToString(); + } + + + private void textBox1_CurrentLineChanged(object sender, EventArgs e) + { + UpdateStatusBar(); + } + + + private void textBox1_CurrentPositionInLineChanged(object sender, EventArgs e) + { + UpdateStatusBar(); + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + if(listView1.SelectedItems.Count > 0) + { + Clipboard.SetText(listView1.SelectedItems[0].SubItems[1].Text); + } + } + + private void uiFindButton_Click(object sender, EventArgs e) + { + if(string.IsNullOrWhiteSpace(uiFindText.Text)) return; + + if(newFind) + { + textBox1.AbortFind(); + textBox1.Select(0, 0); //remove any selection + } + + Regex rBytes = new Regex("0x[0-9a-fA-F]+", RegexOptions.Compiled); + + if(rBytes.IsMatch(uiFindText.Text) && uiFindText.Text.Length % 2 == 0) + { + var bytes = uiFindText.Text.ToByteArray(); + var r = textBox1.Find(new FindOptions() + { + Hex = bytes, + Type = FindType.Hex, + + }); + } + else + { + var r = textBox1.Find(new FindOptions() + { + Text = uiFindText.Text, + Type = FindType.Text, + MatchCase = false, + }); + } + + newFind = false; + } + + private void frmEditor_KeyUp(object sender, KeyEventArgs e) + { + if(e.KeyCode == Keys.F && e.Control) + { + uiFindText.Focus(); + e.Handled = true; + e.SuppressKeyPress = true; + } + + if(e.KeyCode == Keys.Enter) + { + e.SuppressKeyPress = true; + } + } + + private void uiFindText_KeyPress(object sender, KeyPressEventArgs e) + { + if(e.KeyChar == (char)Keys.Enter) + { + uiFindButton.PerformClick(); + e.Handled = true; + } + } + + private void uiFindText_KeyDown(object sender, KeyEventArgs e) + { + if(e.Control && e.KeyCode == Keys.F) + { + e.SuppressKeyPress = true; // stop the annoying beep + } + } + + private void uiFindText_TextChanged(object sender, EventArgs e) + { + newFind = true; + } + } +} diff --git a/HexVisualizer/frmEditor.designer.cs b/HexVisualizer/frmEditor.designer.cs new file mode 100644 index 0000000..b0b715f --- /dev/null +++ b/HexVisualizer/frmEditor.designer.cs @@ -0,0 +1,232 @@ +namespace HexVisualizer +{ + partial class frmEditor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmEditor)); + this.textBox1 = new Be.Windows.Forms.HexBox(); + this.listView1 = new System.Windows.Forms.ListView(); + this.colType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.uiFindText = new System.Windows.Forms.ToolStripTextBox(); + this.uiFindButton = new System.Windows.Forms.ToolStripButton(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.uiPosition = new System.Windows.Forms.ToolStripStatusLabel(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.statusStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.textBox1.ColumnInfoVisible = true; + this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBox1.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox1.GroupSeparatorVisible = true; + this.textBox1.InfoForeColor = System.Drawing.Color.Empty; + this.textBox1.LineInfoVisible = true; + this.textBox1.Location = new System.Drawing.Point(0, 25); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.ShadowSelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(60)))), ((int)(((byte)(188)))), ((int)(((byte)(255))))); + this.textBox1.Size = new System.Drawing.Size(570, 162); + this.textBox1.StringViewVisible = true; + this.textBox1.TabIndex = 0; + this.textBox1.UseFixedBytesPerLine = true; + this.textBox1.VScrollBarVisible = true; + this.textBox1.SelectionStartChanged += new System.EventHandler(this.textBox1_SelectionStartChanged); + this.textBox1.SelectionLengthChanged += new System.EventHandler(this.textBox1_SelectionLengthChanged); + this.textBox1.CurrentLineChanged += new System.EventHandler(this.textBox1_CurrentLineChanged); + this.textBox1.CurrentPositionInLineChanged += new System.EventHandler(this.textBox1_CurrentPositionInLineChanged); + // + // listView1 + // + this.listView1.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.colType, + this.colValue}); + this.listView1.ContextMenuStrip = this.contextMenuStrip1; + this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView1.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView1.Location = new System.Drawing.Point(0, 0); + this.listView1.MultiSelect = false; + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(570, 160); + this.listView1.TabIndex = 1; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + // + // colType + // + this.colType.Text = "Type"; + this.colType.Width = 163; + // + // colValue + // + this.colValue.Text = "Value"; + this.colValue.Width = 232; + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(103, 26); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(102, 22); + this.toolStripMenuItem1.Text = "&Copy"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.textBox1); + this.splitContainer1.Panel1.Controls.Add(this.toolStrip1); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.listView1); + this.splitContainer1.Size = new System.Drawing.Size(570, 351); + this.splitContainer1.SplitterDistance = 187; + this.splitContainer1.TabIndex = 2; + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.uiFindText, + this.uiFindButton}); + this.toolStrip1.Location = new System.Drawing.Point(0, 0); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(570, 25); + this.toolStrip1.TabIndex = 1; + this.toolStrip1.Text = "toolStrip1"; + // + // uiFindText + // + this.uiFindText.CausesValidation = false; + this.uiFindText.Name = "uiFindText"; + this.uiFindText.Size = new System.Drawing.Size(300, 25); + this.uiFindText.ToolTipText = "Type bytes string 0x... to search bytes, otherwise will search text"; + this.uiFindText.KeyDown += new System.Windows.Forms.KeyEventHandler(this.uiFindText_KeyDown); + this.uiFindText.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.uiFindText_KeyPress); + this.uiFindText.TextChanged += new System.EventHandler(this.uiFindText_TextChanged); + // + // uiFindButton + // + this.uiFindButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.uiFindButton.Image = ((System.Drawing.Image)(resources.GetObject("uiFindButton.Image"))); + this.uiFindButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.uiFindButton.Name = "uiFindButton"; + this.uiFindButton.Size = new System.Drawing.Size(23, 22); + this.uiFindButton.Text = "Find"; + this.uiFindButton.Click += new System.EventHandler(this.uiFindButton_Click); + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.uiPosition}); + this.statusStrip1.Location = new System.Drawing.Point(0, 351); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(570, 22); + this.statusStrip1.TabIndex = 3; + this.statusStrip1.Text = "statusStrip1"; + // + // uiPosition + // + this.uiPosition.Name = "uiPosition"; + this.uiPosition.Size = new System.Drawing.Size(555, 17); + this.uiPosition.Spring = true; + this.uiPosition.Text = "toolStripStatusLabel1"; + this.uiPosition.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // frmEditor + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(570, 373); + this.Controls.Add(this.splitContainer1); + this.Controls.Add(this.statusStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; + this.Name = "frmEditor"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Hex Visualizer"; + this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.frmEditor_KeyUp); + this.contextMenuStrip1.ResumeLayout(false); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private Be.Windows.Forms.HexBox textBox1; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader colType; + private System.Windows.Forms.ColumnHeader colValue; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel uiPosition; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripTextBox uiFindText; + private System.Windows.Forms.ToolStripButton uiFindButton; + } +} \ No newline at end of file diff --git a/HexVisualizer/frmEditor.resx b/HexVisualizer/frmEditor.resx new file mode 100644 index 0000000..48bf65a --- /dev/null +++ b/HexVisualizer/frmEditor.resx @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 133, 17 + + + 288, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIuSURBVDhPhVPrThNBGO278Ah9B+JfFel92223Lb2xlu1u + b7bRGGMKpRZNUKyJWtAYElaIMbS0JhATekPaSMSg4n/DQxxnZrctpRC+ZLLJd86cOeebHUO/4sk0xKiE + QCgCry8AzumGDo1hTpdngA1KSaaQXywiXyiCF7xwcPyAJMeTmF8oYPHJEgTfzOUCpIwxOYFGu4OVlyUi + MHRA+/vNNpafv4Dd4aJ9o4boJSeSamQ2qtsT2Oabt6bWddjgDwTXQ2GR4R7BD97tpS5UHdZOqNa+oHNw + iPLqO6TvZWG1caDZXW4BspJEpVZn+Orae2Sy9/tOtJJicXzermK/0cLrN2Wk0hmYzXbMkb7DyYPhlSFO + DxgTqOzU0e58Gzi4M23B0Y9j5PJ5zEkKtgneah/gbXmN4Ta7UxNQEimEIiLJ5WOqVjsHq5XD5OSNUu/7 + ER7n5uHk3aWZYBguXmDXS13RW7Jz/AcDtXl6+hf/zs5w8us3mq02qjs13J4yaQ4W8ohKMv5c4NTqdTYn + IqBA3fyEBmlubGyiUFwi2WWYzDbyVdhp9Ptxa5QjybIW4zyoqlsoPn2GmBKHhcSg8egtSHL8Ug4b5Ii6 + OnRABciI6A9jPC8w4PQdULDb7eL45wkOuz00mk3s7X3tC7DSOL0xDpsBtZnJPsDyyis8fJRDWIxi2mQZ + ueerOOy9hERxl8YIR+4iECSvzR+A2+MjBOuuvv9azgRZLOuFRfv9uoJjmPgPsUMKlzDcCeoAAAAASUVO + RK5CYII= + + + + 17, 17 + + + + AAABAAMAICAAAAEAIACoEAAANgAAABgYAAABACAAiAkAAN4QAAAQEAAAAQAgAGgEAABmGgAAKAAAACAA + AABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA + AAkAAAASAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA + ABYAAAAWAAAAFgAAABYAAAAUAAAACwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAJAAAAIgAAADoAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAA + AEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAD0AAAArAAAAEwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAABAAAABtzUhB2t4AT/LZ+D/+2fg3/tn0N/7Z9Df+2fQ3/tn0N/7Z9Df+2fQ3/tn0N/7Z9 + Df+2fQ3/tn0N/7Z+Df+2fg7/tn8P/7d/Ef+3fxH/t38R/5BmEagAAAAvAAAADwAAAAEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAANJhsFO7mFG//l06n/8urW//Lp1P/x6dP/8enT//Hp0//x6dP/8enT//Hp + 0//x6dP/8enT//Hp0//x6dP/8unU//Lq1v/07tz/38mX/+fWsf/069n/07Ju/6FxEMEAAAAgAAAABgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSjcxG+4syh//r37v/48+X/9/Hj//fx4//38eP/9/Hj//fx + 4//38eP/9/Hj//fx4//38eP/9/Hj//fx4//38uT/+fXq/+jWsf/GmkL/697A/+/ky///////xZg+/2hK + DlwAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAELZ/Efn///////////////////////////// + ////////////////////////////////////////////////////////yqJR/+LNn//r3r//6dq4//39 + +//fxZP/o3IQvQAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGuYQZ/7Z/D/+1fAr/tHoI/7J4 + A/+wcwD/r3EA/69yAP+vcgD/r3IA/69yAP+vcgD/r3IA/69yAP+vcgD/r3IA/7BzAP+zeQb/7uTJ/+zf + wP/q3Lv/+PPo//Pq2P+0fQ74AAAAGAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAJxUQ87tXwM///////v5cz/8ObO//Hnz//y6M//8ujP//Hnz//x587/8ObO//Dmzv/x58//8enP//Hn + zP/u48f/7OHD/+vfwP/z69n//vz5/7V8Cv8AAAAeAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAXFRETO1fAv//////+/lyv/w5Mj/9urN//nsz//57M//9urN//Hlyv/v48j/8OTJ//To + zP/3687/9+rN//Pnyv/v48f/7eDD//Dn0P//////s3oG/3hVEVIAAAAHAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAFLV9DP/38OP/9O3a//Poy/9fYmj/aGpu/2lqb/9gYmn/9OnM//Dl + yf/06cz/uLOj/2VnbP9kZmz/r6me//brzf/w5Mj/7eHF///////JoE7/fVkQZgAAAAsAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARsHoO5vHm0P/38eP/8ufN//7x1f9/fn3/bW5x//bs + 0f/06c//8ebN//nt0v9wcnP/kpCL//7y1f9maGz/zca0//Tqz//v5cr//////9Syb/+ZaxGaAAAADwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2vehDX4suf//v69P/y587/+u/U/5mX + kP9sbXD/2dG+//Xr0v/y6ND//PHW/2lrbv+JiIX///zg/2psb/+Eg4L/+e7V//Hmzv//////3cOQ/6h1 + EMoAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZ5vEJLbwYv//v36//Lo + 0v/579f/tLGm/2xtb/+zsKX/+O7X//Tr1P/989v/amtu/2xtb////uP/bG1v/2lrbv/889r/8+nS//v4 + 8f/z6df/qnYN2AAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFnnASgMym + Wf//////8+vV//rx2v/f2Mb/bW5x/5mYkf/789z/9e3X//zz3f97e3r/amtu////5/+KiYb/aWpt//71 + 3v/069X/9/Lm//37+P+1fAr/AAAAGAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAGHYBFGyJ1H///////07Nj/8OnW/29vcf9vb3H/fH19//714P/17dr/+fDd/9DLvf9mZ2r///nl/5OR + jv9xcHL//fTh//Ts2f/38eT//////7R6B/8AAAAfAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAABW5gRX///////Xu2//68t//0cu//2Znav9iZGf//fXj//bv3f/2797//fXj/7Kv + pv9jZGf/ZGVo/7y4rv/68+H/9e3c//Tt2///////xJc7/3NSD1IAAAAJAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAErR7CP//////9/Li//fx4P/79eT///ro///56P/69OT/9/Hh//bw + 4P/48uH//Pbl///66P//+un//ffm//nz4v/28N//9e/f///////NqFz/lGgRiQAAAA0AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPrHYK1ffx4//69+//9vDi//nz5f//+Or///zt///7 + 7f/+9+n/+fPk//jx4//79Ob///vs///+7////u////nr//rz5f/28OL//////93EkP+WaQ6aAAAAEQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAurdw3G8ebS//379f/48+b//vnr/7az + rP9SUFH/UE9Q/6yoof//++//+vXp//757f9KSUv/VVRV/1ZUVf9LSkz///ns//jz5//+/vz/7eDE/6x3 + DdoAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6BwDpLizJ////////r2 + 6/////P/aGVk/4+MiP////j/W1pa/9LOxv/++u///fru////+f94dXT/Y2Fh///88f/++u//+fTp//37 + 9//38eX/r3gL5wAAABcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEi2EOW9zC + jf//////+/jv//v37f9nZmT/ioiF//////9oZmX/hIKA////9f/8+O/////2/5uYlP9paGf/4N7V///7 + 8f/59ez//Pr1//////+zegf/AAAAGwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAGIYA9IyJ5K///////8+vL////6/3BubP9xcG7//////3Fvbv9vbWz////6//368v////b/vLm2/3Fv + bv+7uLX///71//v48f/6+PL//////8SXO/9TOwpFAAAAGAAAABYAAAARAAAABgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAABTIn0z///////389/////z/h4WC/3h2df//////l5OQ/3d1c/////7//vz2//// + +v/o5+H/enl3/6ajof////z//Pr0//v69f//////x51I/0IuBmQAAABEAAAAQwAAADIAAAAQAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAADrN5B/f//////v38/////P/c2tf/fHl4//////+moqH/hYKA//// + /////vn/+vj0/4SBf/+EgID/kY6M///////+/ff//Pz3///////cwYz/vIgg/8SYPf/FmkH/uYMX/wAA + ABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGq3YOs+fWsv/////////8///////Fw7//gn58/4N/ + ff/Ny8n////+///++/////7/3t7a/4WBf/+BfXz///////79/P/9/Pv///////Dkzf/Elz3/8+3a//Hp + 0v+3gBP5AAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVahJAyaBO//////////////////// + /////////////////////////////////////////////////////////////////////////////76L + J//79/D/6Ne0/696E7IAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwew+w1LJv//// + //////////////////////////////////////////////////////////////////////////////// + ////////+/nz/8qiUv+3fxH/akwPFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAOyfBKJtXwL/7R6CP+0egf/tHoH/7R6B/+0egf/tHoH/7R6B/+0egf/tHoH/7R6B/+0egf/tHoH/7R6 + B/+0egf/tHoI/7V8Cv+2fg//uIIW+qx7Gk8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////4AA + AP+AAAB/AAAAPwAAAD8AAAA/AAAAPwAAAB/gAAAf4AAAH/AAAB/wAAAf8AAAH/AAAB/wAAAP8AAAD/gA + AA/4AAAP+AAAD/gAAA/4AAAH+AAAB/gAAAD8AAAA/AAAAPwAAAD8AAAA/gAAAf8AAAH//////////ygA + AAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAAALAAAACwAAAAsAAAALAAAACwAAAAsAAAALAAAACwAA + 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 + r/+Ni4X///fd/2dnav//++D/bGxs//ju0///////xJg+/6FyFD0AAAAAAAAAAAAAAAAAAAAAsHoMwfry + 4v/Mx7v/hoOB///54P97enn///3j/3Jyc//x6NL//////9Gwaf+AWg9FAAAAAAAAAAAAAAAAAAAAAKp3 + Donz58//0tDM/358fv//+OP/0Mq+/4B+gP+QjYv//PTg///////Zu3//qHURjwAAAAAAAAAAAAAAAAAA + AACsdxBg4smZ/////f///e3///zs///66v//++r///3s///56f////7/6di1/5xtDZIAAAAAAAAAAAAA + AAAAAAAAuIETM93DjP//////aWhn/1NRUv/EwLf////z/2ZkY/9lZGP////9//Hky/+veQzVAAAAAAAA + AAAAAAAAAAAAAAAAAADJnUX//////2NiYv//////bGtp////+//MyML/jIqH////////////qXQIzgAA + ADMAAAAzAAAAAAAAAAAAAAAAyqBM//////95eHf//////3Fvbv//////0s7L/4SBgP///////////7J3 + Af+6hRz/vIki/wAAAAAAAAAAAAAAALN7CuX/////1tbY/398fP+QjYz//////9TT0f97eHj///////// + ///GmUL/7N/C/8GSNP8AAAAAAAAAAAAAAAC3gBKD5tGp//////////////////////////////////// + ////////6dq6/+7iyf+2fxS/AAAAAAAAAAAAAAAAAAAAALZ+D+rFmDz/yZ9K/8SWOf+zeQX/tXsI/7V7 + Cf+1ewj/tXwK/7Z/D/+4gRT/uoUbIwAPrEEAB6xBAAesQQAHrEEAB6xBwAOsQcADrEHAA6xBwAOsQcAD + rEHAA6xB4ACsQeAArEHgAKxB4ACsQfAArEE= + + + \ No newline at end of file diff --git a/HexVisualizer/packages.config b/HexVisualizer/packages.config new file mode 100644 index 0000000..d524e65 --- /dev/null +++ b/HexVisualizer/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5a663e3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 HexVisualizer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d26c3b4 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ + +# HexVisualizer + +[Mladen Mihajlovic Hex Visualizer](https://bitbucket.org/mmihajlovic/hex-visualizer/src/master/) fork + +HexVisualizer provides a viewer for byte arrays so as to display them in a mini hex window. Very useful for debugging network packets and binary files. + +Supports VS 2022 Community or Pro edition. Older [VS 2019](https://marketplace.visualstudio.com/items?itemName=Mika76.HexVisualizer2019&ssr=false#overview), [VS 2017 extension](https://marketplace.visualstudio.com/items?itemName=Mika76.HexVisualizer2017) extensions + +Additional features: +- Visualizing string variables +- String and byte search +- Copy value to clipboard (right click on value in bottom panel) + +## Install + +- Visual studio marketplace [installation link](https://marketplace.visualstudio.com/items?itemName=Michael-Krmeine.HexVisualizer-2022) +- Signed VSIX from repo releases + +## Use + +on VS 2022 it's pretty straight forward. Just explore a byte array + +![Watch.png](./img/WatchWindow.png) + +If you select a string a dialog will pop up... + +![Type chooser.png](./img/TypeChooser.png) + +On choice or if just a byte array... + +![Visualizer.png](./img/HexVisualizer.png) + +## Setup your own build + +May be useful for maintaining new Visual Studio IDE releases + +Newer VS IDE releases and product types support is achieved by updating [VSIX manifest](./VsixHexVisualizer/source.extension.vsixmanifest) and building extension on new IDE + +### Updating VSIX manifest + +1. Update IDE install targets and its' version range +2. Update *Visual Studio MPF* dependency version range +3. Update IDE version ranges for prerequisites: .NET Framework & Visual Studio core editor +4. Build and pack VSIX project release +5. Generate pfx, if doesn't exist, for signing +6. Sign VSIX package +``` +vsixsigntool.exe sign /f /p /fd sha256 /v +``` +7. VSIX ready for install on Visual Studio. Profit + +## Credit + +Uses the Be.Hex control from [Be.HexEditor (.NET C# hex edit control)](http://sourceforge.net/projects/hexbox/) \ No newline at end of file diff --git a/TestHexVisualizer/App.config b/TestHexVisualizer/App.config new file mode 100644 index 0000000..193aecc --- /dev/null +++ b/TestHexVisualizer/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TestHexVisualizer/Program.cs b/TestHexVisualizer/Program.cs new file mode 100644 index 0000000..290b8d4 --- /dev/null +++ b/TestHexVisualizer/Program.cs @@ -0,0 +1,39 @@ +using System; +using HexVisualizer; + +namespace TestHexVisualizer +{ + class Program + { + [STAThread] + + static void Main(string[] args) + { + byte[] b = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + Console.WriteLine("Testing basic byte array"); + ByteArrayVisualizer.TestShowVisualizer(b); + + string s1 = "Some string"; + Console.WriteLine("Testing basic string"); + StringVisualizer.TestShowVisualizer(s1); + + string s2 = "000102030405060708090A0B0C0D0E0F101A1B1C1D1E1F"; + Console.WriteLine("Testing hex string"); + StringVisualizer.TestShowVisualizer(s2); + + string s3 = "0x000102030405060708090A0B0C0D0E0F101A1B1C1D1E1F"; + Console.WriteLine("Testing hex string with 0x prefix"); + StringVisualizer.TestShowVisualizer(s3); + + string s4 = Convert.ToBase64String(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }); + Console.WriteLine("Testing base64"); + StringVisualizer.TestShowVisualizer(s4); + + string s5 = "ЁЂЃЄЅІЇЈЉЊЋЌЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзи"; + + Console.WriteLine("Testing encoding"); + StringVisualizer.TestShowVisualizer(s5); + + } + } +} diff --git a/TestHexVisualizer/Properties/AssemblyInfo.cs b/TestHexVisualizer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..db5513a --- /dev/null +++ b/TestHexVisualizer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Общие сведения об этой сборке предоставляются следующим набором +// набора атрибутов. Измените значения этих атрибутов для изменения сведений, +// связанные с этой сборкой. +[assembly: AssemblyTitle("TestHexVisualizer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TestHexVisualizer")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// из модели COM задайте для атрибута ComVisible этого типа значение true. +[assembly: ComVisible(false)] + +// Следующий GUID представляет идентификатор typelib, если этот проект доступен из модели COM +[assembly: Guid("88ec115a-c8ac-402e-b4df-0642dae5ccf0")] + +// Сведения о версии сборки состоят из указанных ниже четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Номер редакции +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestHexVisualizer/TestHexVisualizer.csproj b/TestHexVisualizer/TestHexVisualizer.csproj new file mode 100644 index 0000000..092137d --- /dev/null +++ b/TestHexVisualizer/TestHexVisualizer.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + {88EC115A-C8AC-402E-B4DF-0642DAE5CCF0} + Exe + TestHexVisualizer + TestHexVisualizer + v4.8 + 512 + true + true + + + AnyCPU + true + full + false + ..\build\TestHexVisualizer\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + ..\build\TestHexVisualizer\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + {80073486-57a2-4b96-b730-c3df0792f766} + HexVisualizer + + + + \ No newline at end of file diff --git a/VsixHexVisualizer/Properties/AssemblyInfo.cs b/VsixHexVisualizer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9e9527e --- /dev/null +++ b/VsixHexVisualizer/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("VsixHexVisualizer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("VsixHexVisualizer")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: AssemblyVersion("1.5.0.5")] +[assembly: AssemblyFileVersion("1.5.0.5")] diff --git a/VsixHexVisualizer/Properties/Resources.Designer.cs b/VsixHexVisualizer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..683df77 --- /dev/null +++ b/VsixHexVisualizer/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// Этот код создан программой. +// Исполняемая версия:4.0.30319.42000 +// +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. +// +//------------------------------------------------------------------------------ + +namespace VsixHexVisualizer.Properties { + using System; + + + /// + /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д. + /// + // Этот класс создан автоматически классом StronglyTypedResourceBuilder + // с помощью такого средства, как ResGen или Visual Studio. + // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen + // с параметром /str или перестройте свой проект VS. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VsixHexVisualizer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Перезаписывает свойство CurrentUICulture текущего потока для всех + /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Поиск локализованного ресурса типа System.Drawing.Icon, аналогичного (Значок). + /// + internal static System.Drawing.Icon script_binary { + get { + object obj = ResourceManager.GetObject("script_binary", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/VsixHexVisualizer/Properties/Resources.resx b/VsixHexVisualizer/Properties/Resources.resx new file mode 100644 index 0000000..b4ed4a3 --- /dev/null +++ b/VsixHexVisualizer/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\script_binary.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/VsixHexVisualizer/Resources/VisualizerPackage.ico b/VsixHexVisualizer/Resources/VisualizerPackage.ico new file mode 100644 index 0000000000000000000000000000000000000000..d323b07fb8d8b417bfc12e7c46dea88bee17760c GIT binary patch literal 428446 zcmeHwzmFYBl3qPFmz*Euki&m~ZRmipgt26b1bqtY(xX9RJvsvBK&Ri~Ag*@=9a#iM za>RpVtU*8~r_ZFd4k7cV&(R$~0mE^Iv%p}VGO8-7vf^b_R#j%ytLpdl?(59T$c&8m z;`{Q|D|Yu3#iqDf6vb`VUM>Fc--_b@xT|l!t*@^Y#ee+oMR9ssUH{vaqWB-L-R#@d z^*5WM_=o@L7PzlX@mcZBzuOf5`+w2;>iQqQDvE#p^Tw^OuRkk_=l{HM>#OTO{H`ee z{l7XV<@(d&o71bsfBk=(;{JWIyXyx<@%F~G+TUsMkAG7X|Mx##tNpoa=jR{(^R?RF zY4L}vMe!g0%eCU0%3)Escqy;)Yg;w@-<^SM+ilgj@2=}!+v5EE+!=P||BKy@dhX@^ zM?>_@`*PQ_e0}ux^t-cc?l!^xKI&~B_|Jm?_}6mI@6Cfg^bh{|tZVz=UxmPTMqi9? zjDJSke~0}m1b~05dB4Z}0RLI$w$J#4Fk>6H{v7J_xNQA-Yy(8M+kIUAd$2Q>KV(#}CpAcqj~A*v73thx$A&TYnzg zfPag*-(!42n6Zspe-8C|T(S-Mz(SfY3FNy9*<%Fw&s41 z@d;tZHg5en)aP;8`t#TZ{C(8hKI0R@jBVWdbEwbbvi0Y&4fwa1`#r`dgc;ko_2*EZ z$7So!V;k`IQE&Thrj4{dsHy{w?NykMRj%#x`#KIn?KI+4}R?2K;^0+dktH!i;U)`g5qyxb^2ypT}kE&tn_#_fc>Aj86zNwsGsvp+1kx)}O~V;NN2I_ZXiLW^Ciu zpF@2fm#sgKZNT40z3nqTAX^?6*j{yeq; ze;@U>&-nP5j>fKMmdfyYJ5Aj@|1?`~Nz8`|rMc(cMs7P1=9V_WH-+GLk9#4=#Qc zXDSE2S$VEq1Lv#0rjbl&CY{YMtRidLt<*!@3M4#$2!^HT0~ zNA5qN_*JMH1xD^aHt%+RC+qfN-2Rh_U&WwMVATGf+H}VE&f28C-kAL-7rzQNNP#i? zkI%Wg!b`j9YWvfj$gO5p*-0pV6^Ece-`3@gPIIL-IHw{bNf(BIE?e}ug5kM587yKBFHC$=9@{OUgY)BbjQBSR?A zjd6(A;rq)^1c3^4w;xhfzQx+hHZ<^}>whl*fquxv-dK(5kVksH z?FAMZ=%)b3HO6Ceha1{%f2@v{cj{Dt2dj2i@momu_X>{a6cFeKSMLut34PkP1xLDB zwiFQC?}k;sePbJlmta8qYrx&O+|{sz+GW9P<)DDyt*$B1`e}MYGCFH!4~lnx`#J!L ze&se^gHiiS?5j;m3WWEM=hUVje-8>J@77loR04?9pp#Jqt={b&3;a~Pey`UvZ(=`K zok+b^-U*~Y(5C~>k?Tsbd)Kk#%P^DxdTKCq|3TZ2ufbV&e+{Vt*mD^a2o%pEEd?ks zi(_t&Uf!HqC4jJNcEzn%@U}Z@dlvya6Ky~TXJSf70VA+y7!(NhYcOE{vB{S)C;{x% zK&HR1z)9N=tw8|VZjk~L%8(i8o>qaNQ-eMD#e4SD+T(uB4L!tc>u;*CXteTyu!! z>aMr&Xm?KVN))m?=d5(w9rLeXCxCoJx_#gSe87*cCj2Yt1NwkId_{Eo&7Kp$OA_*c-!WzffN>({jHZzwtX zYKOYL%DVflJKA2|t0w%~j&yr>EBi%vw7t4s+0WaNZttYBcL)8e(*9R}q}xBE32Jyn zahL2p|Dsj?YuI_$r+-xjxb;W6eL}b=yrMYU>FAQHd%fY6|73d6-LiY-5Z-o2x>qj1 z?tr}N56=bIgD&~H8?*PqLjax2ko;>`fZh%6#_{jlpsa7t2F`u&24`f~H>mloZg96; zt~2PYvTGaE?p26t_nizj+ZJAS?`PoI8~6SOC+E%j#=XCRXK&qm8(hEO^`3iggIkSS zJ@?)Qt=)IuZqV?t7eaNlgecHzF+fb}Td^9Hqj&wagt z)AN=9+;d-V;MSd!ecyd$sOxa;bxBR<43O&w=DK=#Wt z?xX4Fm1`V$(!EF*&FMHhG@BnqFMr^<(b1=Ni!(Qi$2-5i@S+`WXH%~lcXF(qpM9$A zZVTtgojld$cQ2Zb(>1BLzUJS7a2r$$DuY{II;3HDHk8K!jhvM~OI^la4p%?m_G|fD zo#hWwm(f=yx77Khy=ouz3OZV<1EzA#!=*3UsqsoM6=C;rv%N*_Zzt#XsNMbjKT(P3edg4??z?A0%^RDZYQjLwhp^r+677tVpJms?NYs&j`1{z%vLrQ-t?mdfh7)z>Y$ zcD~)$g=6a+uXCq{t)nvSRo;?qw!7WG{BcJ-zwKV9?!`Rcx_Q(Xj_3Przn>WSVw{MGg@7@*f-@h*|E-s1>A3hX6|Mao=<(FUBGg=@31Xh4R zdA=!e-nndFN}k&AWlR5#mZ&n0{4W^-N}aXgOP2i|@L#KRcpUY=WC(=Itd3r??4f_P z(qRMYf5{LCmsuUXWZ6UiYNf*l)c=wp5H7PiDzo3L>`TU%*D4(zm-umgWSgsA>^GM`89(YD zuCq2O@#Ff)HdnpaZ!Ui_e$-#9ba-6i$MunIu6nWGT>fPIsDHT5+Ni{j>m%D-^GJe!wt8{o=;>Y!oZLWH;-(3D={HTAp&f2KNkLx4bT=inVx%|oa zQGcz{;ccxI@`IGUZ{^2@nqY^)^k8E?*i~Z*EC*w!`wMvJ_C4O8V+2*Pj z`_1J~#*g}k>#U7R{J1`{%~dbUl>L0GNHY)Ms z`p7m{z1VLqe=>g5U#oO@T;j*|k!`MevEN+&Wc;XqxX#+B#E2bflMQk@2JcN}-iuiQh7-tVbo|NBxyTE5i~$4e4C}Uc>%# z`IGTm)jwCf$iG4$7oMoUKtR#CHY`@F|NfDyUf@6YPYC4VljJYXe@*G(afu)6Q?|M4 z#eQ@7lkube;W}%h5GJe!w zt8{o=;>Y!oZLWH;-(3D={HTAp&f2KNkLx4bT=inVx%|oaQGcz{;ccxI@ z`IGUZ{^2@nqY^)^k8E?*i~Z*EC*w!`wMvJ_C4O8V+2*Pj`_1J~#*g}k>#U7R{J1`{ z%~dbUl>L0GNHY)Ms`p7m{z1VLqe=>g5U#oO@ zT;j*|k!`MevEN+&Wc;XqxX#+B#EhwH43O8mG!vdvX5 z_M6L}j34#aDjgn|_;G#K(#rU)>c3PxkiS46OmlTqtX6;i9ra%(0LE^W} zD(g|n_)-60nbkpwpN{l0Ei!)8UoCaeAn{vfmG!7({HTAh%<7=TPe*#078yV4ua-J! zkoYaL%6e2Xe$+o$W_3{Frz5>gi;N%jS4$lK+QC47?5*2W!~aXqd+)Kb+k<`-kZDllPI8O8aBkU z<{5`5{sany(^N+}yJ&lu;*Y0*nrYY&&AXa#xZ;ncKse3#XfF`S#Xm`XP!Rc07|$;< zqc8mo#lLx@s$;_U{ttzb^djcI?C&HOf3vxE=g#jEQm>ZUQJ^pV48`AExpn8xt>pYS z8ygDrWuK$?b=;q40KkF*ed*^Y{$_JhZgD&H2rTi-O@Y4b^Avxxxmj(JegqN%c`4AB zexBl&hhMc#`Vp9!0)5%%Dt>wRRU73v0&`NJFa2D_?;P4Wj=*db=*vD^@%iwpHp_Da z=Al4e`uU3A9Ddbyd5*vg6zI!7WAVMiui7!w5tvGWzVvez-#h%OEpr`#NfhYIK5Owi zhhMd8wj*#l1^Uv@TKw+eS8bc`2%JcPzU=SZx&38Eg^I(k+BxG9=uVd}`_tL~X^_Z# zXTJ4$mK${{kNeoW|CJ5klP}!I%Gg);gMVyxZNGW_O3ALoZ}hQu|0~ZCc;))g9~AKr z*bhb<$)W@0vs#8DFv@#BuNDA*G}=$rLG`hBf1lJNa1igkZQJ~d!W$mYP18aBv3Gx; zlp}CB@9Ta2?92XsJUt@`ItU(q)mD>_z)`$+d+jA(4fG_uZ;TO*Tj&}qep7%)*v^oeKewAy# z^mU()z=iNW34%%o;lob@pgaPX#QP)!NC)A=Ps{(#=gZ@L5(KvcBySz=8$n6TvXFuTRl4ipG+U1Ni zLH2h-0r#(Htf8fg8fzl$>4XCAnckQ}>lQfH#H)0|AuE%c;qamvQ=7r? zngx$Gk?(c1p!X&=1KNs(k2mpmI(pEZY0ZT`fBBXs39q9^?M-UB`s|fhnoR0WU)W>j z_W2oZ+wFGxQ$A7bajZX2GlA@a~y*jyBqb@!WQzgJE8RkPo%>=&B- zdSyS?>?f67GuHwBRkxp!12w#&xJ&kr`ubaBKiBPLfLq;82=|0n9^fjv3GdqNP!*c=lpi7?b#_YZD5J2aB0lEV8Zg4k_f8PdWeS0==?t3>l zBfGvq&2M#syXA77L1&d++n{!@LR7o&WU$$`aI7F;J?R)O)4V<301mK?gdIPuaob3DVD?@D$xUV*F=gEaz9&lf6P}@W9%MILl zK73d_dGe%q`t)h>?Af#8`Sa(+%a<>U*RNj}Z{EBq-oAZXynFYqc>n%=adB}`eE9I8 z`1z-g#V^17QvCX>D&=YedPpFY1seDLkEFXy{!_x0J{ z-zB{AS!HqGJLf-*-n=Tk()HDw^$IzE-+8s1x9HCAI=_C+->TYz=YLK6b)8@N>Z?vB z)fQiuE6V7;@ZGsTqv{-VN4_Yhxdo;7+qb{^%=@dASIOvIpM3UJIsJCEL%rli^H&~k zkoC)YgDcm|%iHzjGNyXP?Jvq-SifF5D^vbm6-Z~czr@9L#clqz^YGOb5l1=C`^Kp_ z_eJ5p)rG2p_U5%+j*CXBp!}%Yd0vl}lpdRoXDo{HlgnMSV{y136t5S>IkhK6v8C31 zp8QDdt)eKO7u<6X(zb5cJ#5>3+-z@A``gL+J!*G<|4(%LNuN_s-Rr)4HJ?+jx(oga zd`^Az=+WM1)mN`xsh?HxIhDag3k24OK>azjKJWugl~TY^53#-bmdaOrCvp2Wk96Bn z_Uf*f95lVo`et;Y_HOFsRVV&b`_l7|#h03Y?|P!Ef1k;>uFPL&7Pp1f-Ed=X7B~O> zwbDgt?<~H-cYm7=xo{KQ_xg6vg?R1u?dDGvl{b9kfo`Cx+fKT}`-(C-`J8Svn;W+B z_RQU8mQj6n<$8HT*I3Ia$|FKB@P5LhV!)qTnh?~4-g z{^;F}>iWws-RVo;23|Ms8TEX5o#^kz4SJT~9s}H{{L_d2YwpAT@4l$6Z@B*F?r%3< zt*(n3H?Cc~dGp$}YPw75CiQOIxJlWayU&7CUKj4Ocj)>b z2&*CM@9y6{Kx%2_`hcUAA9W3KkomJT?5CQKlBg%A2a`tJ$L9I`agCJ9CQBAKlFdh z{6F^Gp?~QA*fns>`9uHE|1tCb*mH;eq5osoz%l0!{X_r9%>QH09r}m|JZYf{-OV4*T6C7 z5B)>`$ISm@&mH=Q{*PS)$DBX(5B(oA|BpR)=zrPz|M{nnyEVTKt*

N3mPu2mM3; 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 L+;|ap*3-WLvDtBi literal 0 HcmV?d00001 diff --git a/VsixHexVisualizer/VSPackage.resx b/VsixHexVisualizer/VSPackage.resx new file mode 100644 index 0000000..21f3374 --- /dev/null +++ b/VsixHexVisualizer/VSPackage.resx @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + VisualizerPackage Extension + + + VisualizerPackage Visual Studio Extension Detailed Info + + + + + AAABAAMAICAAAAEAIACoEAAANgAAABgYAAABACAAiAkAAN4QAAAQEAAAAQAgAGgEAABmGgAAKAAAACAA + AABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA + AAkAAAASAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAA + ABYAAAAWAAAAFgAAABYAAAAUAAAACwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAJAAAAIgAAADoAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAEMAAABDAAAAQwAA + AEMAAABDAAAAQwAAAEMAAABDAAAAQwAAAD0AAAArAAAAEwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAABAAAABtzUhB2t4AT/LZ+D/+2fg3/tn0N/7Z9Df+2fQ3/tn0N/7Z9Df+2fQ3/tn0N/7Z9 + Df+2fQ3/tn0N/7Z+Df+2fg7/tn8P/7d/Ef+3fxH/t38R/5BmEagAAAAvAAAADwAAAAEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAANJhsFO7mFG//l06n/8urW//Lp1P/x6dP/8enT//Hp0//x6dP/8enT//Hp + 0//x6dP/8enT//Hp0//x6dP/8unU//Lq1v/07tz/38mX/+fWsf/069n/07Ju/6FxEMEAAAAgAAAABgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSjcxG+4syh//r37v/48+X/9/Hj//fx4//38eP/9/Hj//fx + 4//38eP/9/Hj//fx4//38eP/9/Hj//fx4//38uT/+fXq/+jWsf/GmkL/697A/+/ky///////xZg+/2hK + DlwAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAELZ/Efn///////////////////////////// + ////////////////////////////////////////////////////////yqJR/+LNn//r3r//6dq4//39 + +//fxZP/o3IQvQAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGuYQZ/7Z/D/+1fAr/tHoI/7J4 + A/+wcwD/r3EA/69yAP+vcgD/r3IA/69yAP+vcgD/r3IA/69yAP+vcgD/r3IA/7BzAP+zeQb/7uTJ/+zf + wP/q3Lv/+PPo//Pq2P+0fQ74AAAAGAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAJxUQ87tXwM///////v5cz/8ObO//Hnz//y6M//8ujP//Hnz//x587/8ObO//Dmzv/x58//8enP//Hn + zP/u48f/7OHD/+vfwP/z69n//vz5/7V8Cv8AAAAeAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAXFRETO1fAv//////+/lyv/w5Mj/9urN//nsz//57M//9urN//Hlyv/v48j/8OTJ//To + zP/3687/9+rN//Pnyv/v48f/7eDD//Dn0P//////s3oG/3hVEVIAAAAHAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAFLV9DP/38OP/9O3a//Poy/9fYmj/aGpu/2lqb/9gYmn/9OnM//Dl + yf/06cz/uLOj/2VnbP9kZmz/r6me//brzf/w5Mj/7eHF///////JoE7/fVkQZgAAAAsAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARsHoO5vHm0P/38eP/8ufN//7x1f9/fn3/bW5x//bs + 0f/06c//8ebN//nt0v9wcnP/kpCL//7y1f9maGz/zca0//Tqz//v5cr//////9Syb/+ZaxGaAAAADwAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2vehDX4suf//v69P/y587/+u/U/5mX + kP9sbXD/2dG+//Xr0v/y6ND//PHW/2lrbv+JiIX///zg/2psb/+Eg4L/+e7V//Hmzv//////3cOQ/6h1 + EMoAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZ5vEJLbwYv//v36//Lo + 0v/579f/tLGm/2xtb/+zsKX/+O7X//Tr1P/989v/amtu/2xtb////uP/bG1v/2lrbv/889r/8+nS//v4 + 8f/z6df/qnYN2AAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFnnASgMym + Wf//////8+vV//rx2v/f2Mb/bW5x/5mYkf/789z/9e3X//zz3f97e3r/amtu////5/+KiYb/aWpt//71 + 3v/069X/9/Lm//37+P+1fAr/AAAAGAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAGHYBFGyJ1H///////07Nj/8OnW/29vcf9vb3H/fH19//714P/17dr/+fDd/9DLvf9mZ2r///nl/5OR + jv9xcHL//fTh//Ts2f/38eT//////7R6B/8AAAAfAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAABW5gRX///////Xu2//68t//0cu//2Znav9iZGf//fXj//bv3f/2797//fXj/7Kv + pv9jZGf/ZGVo/7y4rv/68+H/9e3c//Tt2///////xJc7/3NSD1IAAAAJAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAErR7CP//////9/Li//fx4P/79eT///ro///56P/69OT/9/Hh//bw + 4P/48uH//Pbl///66P//+un//ffm//nz4v/28N//9e/f///////NqFz/lGgRiQAAAA0AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPrHYK1ffx4//69+//9vDi//nz5f//+Or///zt///7 + 7f/+9+n/+fPk//jx4//79Ob///vs///+7////u////nr//rz5f/28OL//////93EkP+WaQ6aAAAAEQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAurdw3G8ebS//379f/48+b//vnr/7az + rP9SUFH/UE9Q/6yoof//++//+vXp//757f9KSUv/VVRV/1ZUVf9LSkz///ns//jz5//+/vz/7eDE/6x3 + DdoAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6BwDpLizJ////////r2 + 6/////P/aGVk/4+MiP////j/W1pa/9LOxv/++u///fru////+f94dXT/Y2Fh///88f/++u//+fTp//37 + 9//38eX/r3gL5wAAABcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEi2EOW9zC + jf//////+/jv//v37f9nZmT/ioiF//////9oZmX/hIKA////9f/8+O/////2/5uYlP9paGf/4N7V///7 + 8f/59ez//Pr1//////+zegf/AAAAGwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAGIYA9IyJ5K///////8+vL////6/3BubP9xcG7//////3Fvbv9vbWz////6//368v////b/vLm2/3Fv + bv+7uLX///71//v48f/6+PL//////8SXO/9TOwpFAAAAGAAAABYAAAARAAAABgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAABTIn0z///////389/////z/h4WC/3h2df//////l5OQ/3d1c/////7//vz2//// + +v/o5+H/enl3/6ajof////z//Pr0//v69f//////x51I/0IuBmQAAABEAAAAQwAAADIAAAAQAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAADrN5B/f//////v38/////P/c2tf/fHl4//////+moqH/hYKA//// + /////vn/+vj0/4SBf/+EgID/kY6M///////+/ff//Pz3///////cwYz/vIgg/8SYPf/FmkH/uYMX/wAA + ABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGq3YOs+fWsv/////////8///////Fw7//gn58/4N/ + ff/Ny8n////+///++/////7/3t7a/4WBf/+BfXz///////79/P/9/Pv///////Dkzf/Elz3/8+3a//Hp + 0v+3gBP5AAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVahJAyaBO//////////////////// + /////////////////////////////////////////////////////////////////////////////76L + J//79/D/6Ne0/696E7IAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASwew+w1LJv//// + //////////////////////////////////////////////////////////////////////////////// + ////////+/nz/8qiUv+3fxH/akwPFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAOyfBKJtXwL/7R6CP+0egf/tHoH/7R6B/+0egf/tHoH/7R6B/+0egf/tHoH/7R6B/+0egf/tHoH/7R6 + B/+0egf/tHoI/7V8Cv+2fg//uIIW+qx7Gk8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////4AA + AP+AAAB/AAAAPwAAAD8AAAA/AAAAPwAAAB/gAAAf4AAAH/AAAB/wAAAf8AAAH/AAAB/wAAAP8AAAD/gA + AA/4AAAP+AAAD/gAAA/4AAAH+AAAB/gAAAD8AAAA/AAAAPwAAAD8AAAA/gAAAf8AAAH//////////ygA + AAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAAALAAAACwAAAAsAAAALAAAACwAAAAsAAAALAAAACwAA + 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 + r/+Ni4X///fd/2dnav//++D/bGxs//ju0///////xJg+/6FyFD0AAAAAAAAAAAAAAAAAAAAAsHoMwfry + 4v/Mx7v/hoOB///54P97enn///3j/3Jyc//x6NL//////9Gwaf+AWg9FAAAAAAAAAAAAAAAAAAAAAKp3 + Donz58//0tDM/358fv//+OP/0Mq+/4B+gP+QjYv//PTg///////Zu3//qHURjwAAAAAAAAAAAAAAAAAA + AACsdxBg4smZ/////f///e3///zs///66v//++r///3s///56f////7/6di1/5xtDZIAAAAAAAAAAAAA + AAAAAAAAuIETM93DjP//////aWhn/1NRUv/EwLf////z/2ZkY/9lZGP////9//Hky/+veQzVAAAAAAAA + AAAAAAAAAAAAAAAAAADJnUX//////2NiYv//////bGtp////+//MyML/jIqH////////////qXQIzgAA + ADMAAAAzAAAAAAAAAAAAAAAAyqBM//////95eHf//////3Fvbv//////0s7L/4SBgP///////////7J3 + Af+6hRz/vIki/wAAAAAAAAAAAAAAALN7CuX/////1tbY/398fP+QjYz//////9TT0f97eHj///////// + ///GmUL/7N/C/8GSNP8AAAAAAAAAAAAAAAC3gBKD5tGp//////////////////////////////////// + ////////6dq6/+7iyf+2fxS/AAAAAAAAAAAAAAAAAAAAALZ+D+rFmDz/yZ9K/8SWOf+zeQX/tXsI/7V7 + Cf+1ewj/tXwK/7Z/D/+4gRT/uoUbIwAPrEEAB6xBAAesQQAHrEEAB6xBwAOsQcADrEHAA6xBwAOsQcAD + rEHAA6xB4ACsQeAArEHgAKxB4ACsQfAArEE= + + + \ No newline at end of file diff --git a/VsixHexVisualizer/VisualizerPackage.cs b/VsixHexVisualizer/VisualizerPackage.cs new file mode 100644 index 0000000..a6e3bd1 --- /dev/null +++ b/VsixHexVisualizer/VisualizerPackage.cs @@ -0,0 +1,109 @@ +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using System.IO; +using System.Collections.Generic; +using System.Threading; + + +namespace VsixHexVisualizer +{ + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About + [Guid(VisualizerPackage.PackageGuidString)] + [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] + [ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string, PackageAutoLoadFlags.BackgroundLoad)] + public sealed class VisualizerPackage : AsyncPackage + { + ///

+ /// VisualizerPackage GUID string. + /// + public const string PackageGuidString = "59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1"; + + /// + /// Initializes a new instance of the class. + /// + public VisualizerPackage() + { + } + + protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) + { + //mostly gotten from https://github.com/visualstudioextensibility/VSX-Samples/tree/master/VSIXDebuggerVisualizer + var PAYLOAD_FILE_NAMES = new List() { "HexVisualizer.dll", "Be.Windows.Forms.HexBox.dll" }; + + string sourceFolderFullName; + string destinationFolderFullName; + IVsShell shell; + object documentsFolderFullNameObject = null; + string documentsFolderFullName; + + try + { + await base.InitializeAsync(cancellationToken, progress); + + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + + // The Visualizer dll is in the same folder than the package because its project is added as reference to this project, + // so it is included inside the .vsix file. We only need to deploy it to the correct destination folder. + sourceFolderFullName = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + + // Get the destination folder for visualizers + shell = await base.GetServiceAsync(typeof(SVsShell)) as IVsShell; + shell.GetProperty((int)__VSSPROPID2.VSSPROPID_VisualStudioDir, out documentsFolderFullNameObject); + documentsFolderFullName = documentsFolderFullNameObject.ToString(); + destinationFolderFullName = Path.Combine(documentsFolderFullName, "Visualizers"); + + foreach (var payload in PAYLOAD_FILE_NAMES) + { + var sourceFileFullName = Path.Combine(sourceFolderFullName, payload); + var destinationFileFullName = Path.Combine(destinationFolderFullName, payload); + + CopyFileIfNewerVersion(sourceFileFullName, destinationFileFullName); + } + + } + catch (Exception ex) + { + Debug.WriteLine(ex.ToString()); + } + } + + private void CopyFileIfNewerVersion(string sourceFileFullName, string destinationFileFullName) + { + FileVersionInfo destinationFileVersionInfo; + FileVersionInfo sourceFileVersionInfo; + bool copy = false; + + if (File.Exists(destinationFileFullName)) + { + sourceFileVersionInfo = FileVersionInfo.GetVersionInfo(sourceFileFullName); + destinationFileVersionInfo = FileVersionInfo.GetVersionInfo(destinationFileFullName); + if (sourceFileVersionInfo.FileMajorPart > destinationFileVersionInfo.FileMajorPart) + { + copy = true; + } + else if (sourceFileVersionInfo.FileMajorPart == destinationFileVersionInfo.FileMajorPart + && sourceFileVersionInfo.FileMinorPart > destinationFileVersionInfo.FileMinorPart) + { + copy = true; + } + } + else + { + // First time + copy = true; + } + + if (copy) + { + File.Copy(sourceFileFullName, destinationFileFullName, true); + } + } + + } +} diff --git a/VsixHexVisualizer/VsixHexVisualizer.csproj b/VsixHexVisualizer/VsixHexVisualizer.csproj new file mode 100644 index 0000000..6ff8531 --- /dev/null +++ b/VsixHexVisualizer/VsixHexVisualizer.csproj @@ -0,0 +1,111 @@ + + + + 17.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + false + + + + + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {59EC5E5E-F3F3-4C8D-8DBE-4117AC415EC1} + Library + Properties + VsixHexVisualizer + VsixHexVisualizer + v4.8 + true + true + true + false + false + true + true + Program + $(DevEnvDir)devenv.exe + /rootsuffix Exp + + + true + full + false + ..\build\VsixHexVisualizer\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\build\VsixHexVisualizer\Release\ + TRACE + prompt + 4 + + + + + True + True + Resources.resx + + + + + + Designer + + + + + + + + + + + + + + true + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + {80073486-57a2-4b96-b730-c3df0792f766} + HexVisualizer + + + + + + + + + + \ No newline at end of file diff --git a/VsixHexVisualizer/index.html b/VsixHexVisualizer/index.html new file mode 100644 index 0000000..08747b6 --- /dev/null +++ b/VsixHexVisualizer/index.html @@ -0,0 +1,26 @@ + + + + + + + + Hex Visualizer + + + +
+ + +
+
+ A VS2022 Visualizer for byte arrays +
+
+
+
+
+ + diff --git a/VsixHexVisualizer/source.extension.vsixmanifest b/VsixHexVisualizer/source.extension.vsixmanifest new file mode 100644 index 0000000..2af9aff --- /dev/null +++ b/VsixHexVisualizer/source.extension.vsixmanifest @@ -0,0 +1,32 @@ + + + + + HexVisualizer VS 2022 + A hex viewer visualizer for byte arrays + https://github.com/mIwr/HexVisualizer + index.html + index.html + Resources\script_binary.ico + visualizer + + + + amd64 + + + amd64 + + + + + + + + + + + + + + diff --git a/VsixHexVisualizer/stylesheet.css b/VsixHexVisualizer/stylesheet.css new file mode 100644 index 0000000..d5e9c71 --- /dev/null +++ b/VsixHexVisualizer/stylesheet.css @@ -0,0 +1,129 @@ +body { + margin: 0; + padding: 0; + border: 0; + color: #1E1E1E; + font-size: 13px; + font-family: "Segoe UI", Helvetica, Arial, sans-serif; + line-height: 1.45; + word-wrap: break-word; +} + +/* General & 'Reset' Stuff */ + + +.container { + width: 980px; + margin: 0 auto; +} + +section { + display: block; + margin: 0; +} + +h1, h2, h3, h4, h5, h6 { + margin: 0; +} + +/* Header,
+ header - container + h1 - project name + h2 - project description +*/ + +#header { + color: #FFF; + background: #68217a; + position:relative; +} +#hangcloud { + width: 190px; + height: 160px; + background: url("../images/bannerart03.png"); + position: absolute; + top: 0; + right: -30px; +} +h1, h2 { + font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif; + line-height: 1; + margin: 0 18px; + padding: 0; +} +#header h1 { + font-size: 3.4em; + padding-top: 18px; + font-weight: normal; + margin-left: 15px; +} + +#header h2 { + font-size: 1.5em; + margin-top: 10px; + padding-bottom: 18px; + font-weight: normal; +} + + +#main_content { + width: 100%; + display: flex; + flex-direction: row; +} + + +h1, h2, h3, h4, h5, h6 { + font-weight: bolder; +} + +#main_content h1 { + font-size: 1.8em; + margin-top: 34px; +} + + #main_content h1:first-child { + margin-top: 30px; + } + +#main_content h2 { + font-size: 1.4em; + font-weight: bold; +} +p, ul { + margin: 11px 18px; +} + +#main_content a { + color: #06C; + text-decoration: none; +} +ul { + margin-top: 13px; + margin-left: 18px; + padding-left: 0; +} + ul li { + margin-left: 18px; + padding-left: 0; + } +#lpanel { + width: 620px; + float: left; +} +#rpanel ul { + list-style-type: none; + width: 300px; +} + #rpanel ul li { + line-height: 1.8em; + } +#rpanel { + background: #e7e7e7; + width: 360px; + float: right; +} + +#rpanel div { + width: 300px; +} diff --git a/img/HexVisualizer.png b/img/HexVisualizer.png new file mode 100644 index 0000000000000000000000000000000000000000..3a27041f95c6bd4aab9897bd0d19a4b567b49da3 GIT binary patch literal 42173 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 fs=hq>5%p8f-bi?^TK8iN9`I6A(o`&jng{$3L%9 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 POTWF1Gn#SY*XaKMU20k6 literal 0 HcmV?d00001 diff --git a/img/WatchWindow.png b/img/WatchWindow.png new file mode 100644 index 0000000000000000000000000000000000000000..6c64c3abaf47605eb546289afd091939e8993940 GIT binary patch literal 12245 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 literal 0 HcmV?d00001