@@ -12,11 +12,21 @@ import TelemetryReporter from 'vscode-extension-telemetry';
1212import { CoreClrDebugUtil } from './util' ;
1313import * as debugInstall from './install' ;
1414import { Platform , getCurrentPlatform } from './../platform' ;
15+ import * as semver from 'semver' ;
16+
17+ const MINIMUM_SUPPORTED_DOTNET_CLI : string = '1.0.0-preview2-003121' ;
1518
1619let _reporter : TelemetryReporter = null ;
1720let _channel : vscode . OutputChannel = null ;
1821let _util : CoreClrDebugUtil = null ;
1922
23+ class DotnetInfo
24+ {
25+ public Version : string ;
26+ public OsVersion : string ;
27+ public RuntimeId : string ;
28+ }
29+
2030export function activate ( context : vscode . ExtensionContext , reporter : TelemetryReporter ) {
2131 _reporter = reporter ;
2232 _channel = vscode . window . createOutputChannel ( 'coreclr-debug' ) ;
@@ -27,22 +37,7 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe
2737 return ;
2838 }
2939
30- let dotnetVersion : string = '' ;
31- let osVersion : string = '' ;
32- let osRID : string = '' ;
33- _util . spawnChildProcess ( 'dotnet' , [ '--info' ] , _util . coreClrDebugDir ( ) , ( data : Buffer ) => {
34- var lines : string [ ] = data . toString ( ) . replace ( / \r / mg, '' ) . split ( '\n' ) ;
35- lines . forEach ( line => {
36- let match : RegExpMatchArray ;
37- if ( match = / ^ \ V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
38- dotnetVersion = match [ 1 ] ;
39- } else if ( match = / ^ \ O S V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
40- osVersion = match [ 1 ] ;
41- } else if ( match = / ^ \ R I D : \s * ( [ \w \- \. ] + ) $ / . exec ( line ) ) {
42- osRID = match [ 1 ] ;
43- }
44- } ) ;
45- } ) . then ( ( ) => {
40+ checkForDotnetTools ( ) . then ( ( dotnetInfo : DotnetInfo ) => {
4641 let installer = new debugInstall . DebugInstaller ( _util ) ;
4742 _util . createInstallLog ( ) ;
4843
@@ -61,54 +56,98 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe
6156 statusBarMessage . dispose ( ) ;
6257 vscode . window . setStatusBarMessage ( 'Successfully installed .NET Core Debugger.' ) ;
6358 } ) . catch ( ( error : debugInstall . InstallError ) => {
64- const viewLogMessage = "View Log" ;
65- vscode . window . showErrorMessage ( 'Error while installing .NET Core Debugger.' , viewLogMessage ) . then ( value => {
66- if ( value === viewLogMessage ) {
67- _channel . show ( vscode . ViewColumn . Three ) ;
68- }
69- } ) ;
70- statusBarMessage . dispose ( ) ;
71-
72- installStage = error . installStage ;
73- installError = error . errorMessage ;
74- moreErrors = error . hasMoreErrors ? 'true' : 'false' ;
75- } ) . then ( ( ) => {
76- // log telemetry and delete install begin file
77- logTelemetry ( 'Acquisition' , {
78- installStage : installStage ,
79- installError : installError ,
80- moreErrors : moreErrors ,
81- dotnetVersion : dotnetVersion ,
82- osVersion : osVersion ,
83- osRID : osRID
84- } ) ;
85- try {
86- deleteInstallBeginFile ( ) ;
87- } catch ( err ) {
88- // if this throws there's really nothing we can do
59+ const viewLogMessage = "View Log" ;
60+ vscode . window . showErrorMessage ( 'Error while installing .NET Core Debugger.' , viewLogMessage ) . then ( value => {
61+ if ( value === viewLogMessage ) {
62+ _channel . show ( vscode . ViewColumn . Three ) ;
8963 }
90- _util . closeInstallLog ( ) ;
9164 } ) ;
92- } ) . catch ( ( ) => {
93- const config = vscode . workspace . getConfiguration ( 'csharp' ) ;
94- if ( ! config . get ( 'suppressDotnetInstallWarning' , false ) ) {
95- const getDotNetMessage = 'Get .NET CLI tools' ;
96- const goToSettingsMessage = 'Disable this message in user settings' ;
97- // Buttons are shown in right-to-left order, with a close button to the right of everything;
98- // getDotNetMessage will be the first button, then goToSettingsMessage, then the close button.
99- vscode . window . showErrorMessage ( 'The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.' ,
100- goToSettingsMessage , getDotNetMessage ) . then ( value => {
101- if ( value === getDotNetMessage ) {
102- let open = require ( 'open' ) ;
103- open ( 'https://www.microsoft.com/net/core' ) ;
104- } else if ( value === goToSettingsMessage ) {
105- vscode . commands . executeCommand ( 'workbench.action.openGlobalSettings' ) ;
106- }
107- } ) ;
65+ statusBarMessage . dispose ( ) ;
66+
67+ installStage = error . installStage ;
68+ installError = error . errorMessage ;
69+ moreErrors = error . hasMoreErrors ? 'true' : 'false' ;
70+ } ) . then ( ( ) => {
71+ // log telemetry and delete install begin file
72+ logTelemetry ( 'Acquisition' , {
73+ installStage : installStage ,
74+ installError : installError ,
75+ moreErrors : moreErrors ,
76+ dotnetVersion : dotnetInfo . Version ,
77+ osVersion : dotnetInfo . OsVersion ,
78+ osRID : dotnetInfo . RuntimeId
79+ } ) ;
80+ try {
81+ deleteInstallBeginFile ( ) ;
82+ } catch ( err ) {
83+ // if this throws there's really nothing we can do
84+ }
85+ _util . closeInstallLog ( ) ;
86+ } ) ;
87+ } ) . catch ( ( error ) => {
88+ // log errors from checkForDotnetTools
89+ _util . log ( error . message ) ;
90+ } ) ;
91+ }
92+
93+ // This function checks for the presence of dotnet on the path and ensures the Version
94+ // is new enough for us. Any error UI that needs to be displayed is handled by this function.
95+ // Returns: a promise that returns a DotnetInfo class
96+ // Throws: An Error() from the return promise if either dotnet does not exist or is too old.
97+ function checkForDotnetTools ( ) : Promise < DotnetInfo >
98+ {
99+ let dotnetInfo = new DotnetInfo ( ) ;
100+
101+ return _util . spawnChildProcess ( 'dotnet' , [ '--info' ] , _util . coreClrDebugDir ( ) , ( data : Buffer ) => {
102+ var lines : string [ ] = data . toString ( ) . replace ( / \r / mg, '' ) . split ( '\n' ) ;
103+ lines . forEach ( line => {
104+ let match : RegExpMatchArray ;
105+ if ( match = / ^ \ V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
106+ dotnetInfo . Version = match [ 1 ] ;
107+ } else if ( match = / ^ \ O S V e r s i o n : \s * ( [ ^ \s ] .* ) $ / . exec ( line ) ) {
108+ dotnetInfo . OsVersion = match [ 1 ] ;
109+ } else if ( match = / ^ \ R I D : \s * ( [ \w \- \. ] + ) $ / . exec ( line ) ) {
110+ dotnetInfo . RuntimeId = match [ 1 ] ;
111+ }
112+ } ) ;
113+ } ) . catch ( ( error ) => {
114+ // something went wrong with spawning 'dotnet --info'
115+ let message = 'The .NET CLI tools cannot be located. .NET Core debugging will not be enabled. Make sure .NET CLI tools are installed and are on the path.' ;
116+ showDotnetToolsWarning ( message ) ;
117+ throw new Error ( "Failed to spawn 'dotnet --info'" ) ;
118+ } ) . then ( ( ) => {
119+ // succesfully spawned 'dotnet --info', check the Version
120+ if ( semver . lt ( dotnetInfo . Version , MINIMUM_SUPPORTED_DOTNET_CLI ) )
121+ {
122+ let message = 'The .NET CLI tools on the path are too old. .NET Core debugging will not be enabled. The minimum supported version is ' + MINIMUM_SUPPORTED_DOTNET_CLI + '.' ;
123+ showDotnetToolsWarning ( message ) ;
124+ throw new Error ( "dotnet cli is too old" ) ;
108125 }
126+
127+ return dotnetInfo ;
109128 } ) ;
110129}
111130
131+ function showDotnetToolsWarning ( message : string ) : void
132+ {
133+ const config = vscode . workspace . getConfiguration ( 'csharp' ) ;
134+ if ( ! config . get ( 'suppressDotnetInstallWarning' , false ) ) {
135+ const getDotNetMessage = 'Get .NET CLI tools' ;
136+ const goToSettingsMessage = 'Disable this message in user settings' ;
137+ // Buttons are shown in right-to-left order, with a close button to the right of everything;
138+ // getDotNetMessage will be the first button, then goToSettingsMessage, then the close button.
139+ vscode . window . showErrorMessage ( message ,
140+ goToSettingsMessage , getDotNetMessage ) . then ( value => {
141+ if ( value === getDotNetMessage ) {
142+ let open = require ( 'open' ) ;
143+ open ( 'https://www.microsoft.com/net/core' ) ;
144+ } else if ( value === goToSettingsMessage ) {
145+ vscode . commands . executeCommand ( 'workbench.action.openGlobalSettings' ) ;
146+ }
147+ } ) ;
148+ }
149+ }
150+
112151function logTelemetry ( eventName : string , properties ?: { [ prop : string ] : string } ) : void {
113152 if ( _reporter !== null ) {
114153 _reporter . sendTelemetryEvent ( 'coreclr-debug/' + eventName , properties ) ;
0 commit comments