22using Microsoft . VisualStudio . Shell ;
33using Microsoft . VisualStudio . Shell . Interop ;
44using System ;
5+ using System . ComponentModel ;
6+ using System . Diagnostics ;
57using System . Diagnostics . CodeAnalysis ;
68using System . Runtime . InteropServices ;
79using System . Threading ;
@@ -33,6 +35,8 @@ namespace GtmExtension
3335 [ ProvideAutoLoad ( UIContextGuids80 . SolutionExists , PackageAutoLoadFlags . BackgroundLoad ) ] // Load the extension when a solution is open.
3436 public sealed class GtmPackage : AsyncPackage
3537 {
38+ private string gtmExe ;
39+
3640 /// <summary>
3741 /// GtmPackage GUID string.
3842 /// </summary>
@@ -49,6 +53,32 @@ public GtmPackage()
4953 // initialization is the Initialize method.
5054 }
5155
56+ #region Helper Functions
57+
58+ /// <summary>
59+ /// Checks if executable <paramref name="exeName"/> can be found in system's PATH.
60+ /// </summary>
61+ /// <seealso href="https://stackoverflow.com/a/24405838/9080566"/>
62+ public static bool ExistsOnPath ( string exeName )
63+ {
64+ try
65+ {
66+ var p = new Process ( ) ;
67+ p . StartInfo . UseShellExecute = false ;
68+ p . StartInfo . FileName = "where" ;
69+ p . StartInfo . Arguments = exeName ;
70+ p . Start ( ) ;
71+ p . WaitForExit ( ) ;
72+ return p . ExitCode == 0 ;
73+ }
74+ catch ( Win32Exception )
75+ {
76+ throw new Exception ( "Command 'where' was not found." ) ;
77+ }
78+ }
79+
80+ #endregion
81+
5282 #region Package Members
5383
5484 /// <summary>
@@ -60,17 +90,26 @@ public GtmPackage()
6090 /// <returns>A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.</returns>
6191 protected override async Task InitializeAsync ( CancellationToken cancellationToken , IProgress < ServiceProgressData > progress )
6292 {
93+ // Try to find executable `gtm`.
94+ if ( ExistsOnPath ( "gtm" ) )
95+ {
96+ gtmExe = "gtm" ;
97+ }
98+
6399 // When initialized asynchronously, the current thread may be a background thread at this point.
64100 // Do any initialization that requires the UI thread after switching to the UI thread.
65101 await this . JoinableTaskFactory . SwitchToMainThreadAsync ( cancellationToken ) ;
66102
67- // Show test message box.
68- var uiShell = ( IVsUIShell ) await GetServiceAsync ( typeof ( SVsUIShell ) ) ;
69- if ( uiShell == null ) { return ; }
70- Guid clsid = Guid . Empty ;
71- int result ;
72- ErrorHandler . ThrowOnFailure ( uiShell . ShowMessageBox ( 0 , ref clsid , "GtmPackage" , "Initializing." , string . Empty , 0 ,
73- OLEMSGBUTTON . OLEMSGBUTTON_OK , OLEMSGDEFBUTTON . OLEMSGDEFBUTTON_FIRST , OLEMSGICON . OLEMSGICON_INFO , 0 , out result ) ) ;
103+ // Show error, if we didn't find `gtm` on PATH.
104+ if ( gtmExe == null )
105+ {
106+ var uiShell = ( IVsUIShell ) await GetServiceAsync ( typeof ( SVsUIShell ) ) ;
107+ if ( uiShell == null ) { return ; }
108+ Guid clsid = Guid . Empty ;
109+ int result ;
110+ ErrorHandler . ThrowOnFailure ( uiShell . ShowMessageBox ( 0 , ref clsid , "GtmPackage" , "We couldn't find gtm executable." , string . Empty , 0 ,
111+ OLEMSGBUTTON . OLEMSGBUTTON_OK , OLEMSGDEFBUTTON . OLEMSGDEFBUTTON_FIRST , OLEMSGICON . OLEMSGICON_CRITICAL , 0 , out result ) ) ;
112+ }
74113 }
75114
76115 #endregion
0 commit comments