11
2- using Microsoft . VisualStudio . Setup . Configuration ;
3- using System . Runtime . InteropServices ;
4-
52namespace BuildScripts ;
63
74[ TaskName ( "Build Windows" ) ]
@@ -52,7 +49,7 @@ private bool IsOnPATH(string process)
5249 if ( ! process . EndsWith ( ".exe" ) )
5350 process += ".exe" ;
5451
55- // check if process exist on PATH env
52+ // Check if process exist on PATH env
5653
5754 var split = Environment . GetEnvironmentVariable ( "PATH" ) ? . Split ( ';' ) ;
5855 if ( split != null )
@@ -70,86 +67,29 @@ private bool IsOnPATH(string process)
7067
7168 private string GetVisualStudioPath ( )
7269 {
73- // This code to retrieve where Visual Studio is installed is adapted from
74- // https://github.com/microsoft/MSBuildLocator
75- // Surprisingly, this package has code to retrieve a VS installation but
76- // this feature is disabled from the public nuget... so adapting it from source
77-
78- // This will only detect Visual Studio 2015 and above
79-
80- string path = string . Empty ;
81- Version version = new Version ( ) ;
82-
83- try
70+ // We can use vswhere.exe which ships with VS2017 and later.
71+ // Microsoft guarantees that it is always installed in %ProgramFiles(x86)%\Microsoft Visual Studio\Installer
72+
73+ System . Diagnostics . Process process = new System . Diagnostics . Process ( ) ;
74+ process . StartInfo . FileName = System . IO . Path . Combine ( Environment . ExpandEnvironmentVariables ( "%ProgramFiles(x86)%" ) , "Microsoft Visual Studio\\ Installer\\ vswhere.exe" ) ;
75+ process . StartInfo . Arguments = "-latest" ;
76+ process . StartInfo . UseShellExecute = false ;
77+ process . StartInfo . RedirectStandardOutput = true ;
78+ process . StartInfo . CreateNoWindow = true ;
79+ process . Start ( ) ;
80+
81+ string result = process . StandardOutput . ReadToEnd ( ) ;
82+
83+ if ( ! string . IsNullOrEmpty ( result ) )
8484 {
85- // This code is not obvious. See the sample (link above) for reference.
86- var query = ( ISetupConfiguration2 ) GetQuery ( ) ;
87- var e = query . EnumAllInstances ( ) ;
88-
89- int fetched ;
90- var instances = new ISetupInstance [ 1 ] ;
91- do
85+ var lines = result . Split ( "\r \n " ) ;
86+ foreach ( var line in lines )
9287 {
93- // Call e.Next to query for the next instance (single item or nothing returned).
94- e . Next ( 1 , instances , out fetched ) ;
95- if ( fetched <= 0 ) continue ;
96-
97- var instance = ( ISetupInstance2 ) instances [ 0 ] ;
98- InstanceState state = instance . GetState ( ) ;
99-
100- // If the install was complete
101- if ( state == InstanceState . Complete ||
102- ( state . HasFlag ( InstanceState . Registered ) && state . HasFlag ( InstanceState . NoRebootRequired ) ) )
103- {
104- if ( ! Version . TryParse ( instance . GetInstallationVersion ( ) , out var current ) )
105- continue ;
106-
107- // We want the highest version installed
108- if ( current <= version )
109- continue ;
110-
111- version = current ;
112- path = instance . GetInstallationPath ( ) ;
113- }
88+ if ( line . StartsWith ( "installationPath: " ) )
89+ return line . Substring ( 18 ) ;
11490 }
115- while ( fetched > 0 ) ;
116- }
117- catch ( COMException )
118- {
119- }
120- catch ( DllNotFoundException )
121- {
122- // This is OK, VS "15" or greater likely not installed.
12391 }
12492
125- return path ;
93+ return string . Empty ;
12694 }
127-
128- private static ISetupConfiguration GetQuery ( )
129- {
130- const int REGDB_E_CLASSNOTREG = unchecked ( ( int ) 0x80040154 ) ;
131-
132- try
133- {
134- // Try to CoCreate the class object.
135- return new SetupConfiguration ( ) ;
136- }
137-
138- catch ( COMException ex ) when ( ex . ErrorCode == REGDB_E_CLASSNOTREG )
139- {
140- // Try to get the class object using app-local call.
141- ISetupConfiguration query ;
142- var result = GetSetupConfiguration ( out query , IntPtr . Zero ) ;
143-
144- if ( result < 0 )
145- throw new COMException ( $ "Failed to get { nameof ( query ) } ", result ) ;
146-
147- return query ;
148- }
149- }
150-
151- [ DllImport ( "Microsoft.VisualStudio.Setup.Configuration.Native.dll" , ExactSpelling = true , PreserveSig = true ) ]
152- private static extern int GetSetupConfiguration (
153- [ MarshalAs ( UnmanagedType . Interface ) ] [ Out ] out ISetupConfiguration configuration ,
154- IntPtr reserved ) ;
15595}
0 commit comments