From 93e28a51b98d6f4fc15780ff89292d4fb5ec1d32 Mon Sep 17 00:00:00 2001 From: Kirill Osenkov Date: Wed, 28 Jun 2017 22:36:17 -0700 Subject: [PATCH] Associate .binlog and .buildlog files with the MSBuild Structured Log Viewer. Fixes #64 --- src/StructuredLogViewer/FileAssociations.cs | 85 +++++++++++++++++++ src/StructuredLogViewer/MainWindow.xaml.cs | 1 + .../StructuredLogViewer.csproj | 1 + 3 files changed, 87 insertions(+) create mode 100644 src/StructuredLogViewer/FileAssociations.cs diff --git a/src/StructuredLogViewer/FileAssociations.cs b/src/StructuredLogViewer/FileAssociations.cs new file mode 100644 index 000000000..7889d8c65 --- /dev/null +++ b/src/StructuredLogViewer/FileAssociations.cs @@ -0,0 +1,85 @@ +using System; +using System.Diagnostics; +using Microsoft.Win32; + +namespace StructuredLogViewer +{ + public class FileAssociation + { + public string Extension { get; set; } + public string ProgId { get; set; } + public string FileTypeDescription { get; set; } + public string ExecutableFilePath { get; set; } + } + + public class FileAssociations + { + // needed so that Explorer windows get refreshed after the registry is updated + [System.Runtime.InteropServices.DllImport("Shell32.dll")] + private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); + + private const int SHCNE_ASSOCCHANGED = 0x8000000; + private const int SHCNF_FLUSH = 0x1000; + + public static void EnsureAssociationsSet() + { + var filePath = Process.GetCurrentProcess().MainModule.FileName; + EnsureAssociationsSet( + new FileAssociation + { + Extension = ".binlog", + ProgId = "MSBuildBinaryLog", + FileTypeDescription = "MSBuild Binary Log", + ExecutableFilePath = filePath + }, + new FileAssociation + { + Extension = ".buildlog", + ProgId = "MSBuildStructuredLog", + FileTypeDescription = "MSBuild Structured Log", + ExecutableFilePath = filePath + }); + } + + public static void EnsureAssociationsSet(params FileAssociation[] associations) + { + bool madeChanges = false; + foreach (var association in associations) + { + madeChanges |= SetAssociation( + association.Extension, + association.ProgId, + association.FileTypeDescription, + association.ExecutableFilePath); + } + + if (madeChanges) + { + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero); + } + } + + public static bool SetAssociation(string extension, string progId, string fileTypeDescription, string applicationFilePath) + { + bool madeChanges = false; + madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + extension, progId); + madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + progId, fileTypeDescription); + madeChanges |= SetKeyDefaultValue($@"Software\Classes\{progId}\shell\open\command", "\"" + applicationFilePath + "\" \"%1\""); + return madeChanges; + } + + private static bool SetKeyDefaultValue(string keyPath, string value) + { + using (var key = Registry.CurrentUser.CreateSubKey(keyPath)) + { + if (key.GetValue(null) as string != value) + { + key.SetValue(null, value); + return true; + } + } + + return false; + } + } +} diff --git a/src/StructuredLogViewer/MainWindow.xaml.cs b/src/StructuredLogViewer/MainWindow.xaml.cs index 15e66f18b..20cc09f9f 100644 --- a/src/StructuredLogViewer/MainWindow.xaml.cs +++ b/src/StructuredLogViewer/MainWindow.xaml.cs @@ -89,6 +89,7 @@ private async void MainWindow_Loaded(object sender, RoutedEventArgs e) if (result == null || result.Version == currentVersion) { message = "You have the latest version: " + currentVersion.ToString(); + FileAssociations.EnsureAssociationsSet(); } else if (result.Version > currentVersion) { diff --git a/src/StructuredLogViewer/StructuredLogViewer.csproj b/src/StructuredLogViewer/StructuredLogViewer.csproj index 2be902305..551020ccc 100644 --- a/src/StructuredLogViewer/StructuredLogViewer.csproj +++ b/src/StructuredLogViewer/StructuredLogViewer.csproj @@ -83,6 +83,7 @@ +