2
2
* Copyright (C) Microsoft Corporation. All rights reserved.
3
3
*--------------------------------------------------------*/
4
4
5
- import cp = require( "child_process" ) ;
6
5
import fs = require( "fs" ) ;
7
6
import net = require( "net" ) ;
8
7
import path = require( "path" ) ;
@@ -17,13 +16,13 @@ import Settings = require("./settings");
17
16
import utils = require( "./utils" ) ;
18
17
19
18
import {
20
- CloseAction , DocumentSelector , ErrorAction , Executable , LanguageClient , LanguageClientOptions ,
21
- Middleware , NotificationType , RequestType , RequestType0 ,
19
+ CloseAction , DocumentSelector , ErrorAction , LanguageClient , LanguageClientOptions ,
20
+ Middleware , NotificationType , RequestType0 ,
22
21
ResolveCodeLensSignature , RevealOutputChannelOn , StreamInfo } from "vscode-languageclient" ;
23
22
24
23
import { GitHubReleaseInformation , InvokePowerShellUpdateCheck } from "./features/UpdatePowerShell" ;
25
24
import {
26
- getPlatformDetails , IPlatformDetails ,
25
+ getPlatformDetails , IPlatformDetails , IPowerShellExeDetails ,
27
26
OperatingSystem , PowerShellExeFinder } from "./platform" ;
28
27
29
28
export enum SessionStatus {
@@ -37,9 +36,9 @@ export enum SessionStatus {
37
36
38
37
export class SessionManager implements Middleware {
39
38
public HostVersion : string ;
39
+ public PowerShellExeDetails : IPowerShellExeDetails ;
40
40
private ShowSessionMenuCommandName = "PowerShell.ShowSessionMenu" ;
41
41
private editorServicesArgs : string ;
42
- private powerShellExePath : string = "" ;
43
42
private sessionStatus : SessionStatus = SessionStatus . NeverStarted ;
44
43
private suppressRestartPrompt : boolean ;
45
44
private focusConsoleOnExecute : boolean ;
@@ -119,15 +118,17 @@ export class SessionManager implements Middleware {
119
118
120
119
this . createStatusBarItem ( ) ;
121
120
121
+ this . promptPowerShellExeSettingsCleanup ( ) ;
122
+
122
123
try {
123
- this . powerShellExePath = this . getPowerShellExePath ( ) ;
124
+ this . PowerShellExeDetails = this . powershellExeFinder . getFirstAvailablePowerShellInstallation ( ) ;
124
125
} catch ( e ) {
125
126
this . log . writeError ( `Error occurred while searching for a PowerShell executable:\n${ e } ` ) ;
126
127
}
127
128
128
129
this . suppressRestartPrompt = false ;
129
130
130
- if ( ! this . powerShellExePath ) {
131
+ if ( ! this . PowerShellExeDetails ) {
131
132
const message = "Unable to find PowerShell."
132
133
+ " Do you have PowerShell installed?"
133
134
+ " You can also configure custom PowerShell installations"
@@ -230,7 +231,7 @@ export class SessionManager implements Middleware {
230
231
231
232
this . debugSessionProcess =
232
233
new PowerShellProcess (
233
- this . powerShellExePath ,
234
+ this . PowerShellExeDetails . exePath ,
234
235
this . bundledModulesPath ,
235
236
"[TEMP] PowerShell Integrated Console" ,
236
237
this . log ,
@@ -241,51 +242,6 @@ export class SessionManager implements Middleware {
241
242
return this . debugSessionProcess ;
242
243
}
243
244
244
- public getPowerShellExePath ( ) : string {
245
- if ( ! this . sessionSettings . powerShellExePath &&
246
- this . sessionSettings . developer . powerShellExePath ) {
247
- // Show deprecation message with fix action.
248
- // We don't need to wait on this to complete
249
- // because we can finish gathering the configured
250
- // PowerShell path without the fix
251
- this . showExePathSettingDeprecationWarning ( ) ;
252
- }
253
-
254
- let powerShellExePath : string = this . getConfiguredPowerShellExePath ( ) . trim ( ) ;
255
-
256
- // New versions of PS Core uninstall the previous version
257
- // so make sure the path stored in the settings exists.
258
- if ( ! fs . existsSync ( powerShellExePath ) ) {
259
- this . log . write (
260
- `Path specified by 'powerShellExePath' setting - '${ powerShellExePath } ' - not found, ` +
261
- "reverting to default PowerShell path." ) ;
262
- powerShellExePath = "" ;
263
- }
264
-
265
- if ( powerShellExePath ) {
266
- if ( this . platformDetails . operatingSystem === OperatingSystem . Windows ) {
267
- // Check the path bitness
268
- const fixedPath = this . powershellExeFinder . fixWindowsPowerShellPath (
269
- powerShellExePath ) ;
270
-
271
- if ( fixedPath !== powerShellExePath ) {
272
- // Show deprecation message with fix action.
273
- // We don't need to wait on this to complete
274
- // because we can finish gathering the configured
275
- // PowerShell path without the fix
276
- this . showBitnessPathFixWarning ( fixedPath ) ;
277
- powerShellExePath = fixedPath ;
278
- }
279
- }
280
-
281
- return this . resolvePowerShellPath ( powerShellExePath ) ;
282
- }
283
-
284
- // No need to resolve this path, since the finder guarantees its existence
285
- const firstPowerShell = this . powershellExeFinder . getFirstAvailablePowerShellInstallation ( ) ;
286
- return firstPowerShell && firstPowerShell . exePath || null ;
287
- }
288
-
289
245
// ----- LanguageClient middleware methods -----
290
246
291
247
public resolveCodeLens (
@@ -331,64 +287,37 @@ export class SessionManager implements Middleware {
331
287
return resolvedCodeLens ;
332
288
}
333
289
334
- private async showExePathSettingDeprecationWarning ( ) : Promise < void > {
335
- const choice : string = await vscode . window . showWarningMessage (
336
- "The 'powershell.developer.powerShellExePath' setting is deprecated, use " +
337
- "'powershell.powerShellExePath' instead." ,
338
- "Fix Automatically" ) ;
339
-
340
- if ( ! choice ) {
341
- return ;
342
- }
343
-
344
- this . suppressRestartPrompt = true ;
345
- await Settings . change ( "powerShellExePath" , this . sessionSettings . developer . powerShellExePath , true ) ;
346
- await Settings . change ( "developer.powerShellExePath" , undefined , true ) ;
347
- this . suppressRestartPrompt = false ;
348
- }
349
-
350
- private async showBitnessPathFixWarning ( fixedPath : string ) : Promise < void > {
351
- const bitness = this . platformDetails . isOS64Bit ? "64" : "32" ;
290
+ private async promptPowerShellExeSettingsCleanup ( ) {
291
+ if ( this . sessionSettings . powerShellExePath ) {
292
+ let warningMessage = "The 'powerShell.powerShellExePath' setting is no longer used. " ;
293
+ warningMessage += this . sessionSettings . powerShellDefaultVersion
294
+ ? "We can automatically remove it for you."
295
+ : "We can remove it from your settings and prompt you for which PowerShell you want to use." ;
352
296
353
- const choice = await vscode . window . showWarningMessage (
354
- `The specified PowerShell path is incorrect for ${ bitness } -bit VS Code, using '${ fixedPath } ' instead.` ,
355
- "Fix Setting Automatically" ) ;
297
+ const choice = await vscode . window . showWarningMessage ( warningMessage , "Let's do it!" ) ;
356
298
357
- if ( ! choice ) {
358
- return ;
359
- }
299
+ if ( choice === "" ) {
300
+ // They hit the 'x' to close the dialog.
301
+ return ;
302
+ }
360
303
361
- this . suppressRestartPrompt = true ;
362
- await Settings . change ( "powerShellExePath" , this . sessionSettings . developer . powerShellExePath , true ) ;
363
- await Settings . change ( "developer.powerShellExePath" , undefined , true ) ;
364
- this . suppressRestartPrompt = false ;
365
- }
304
+ this . suppressRestartPrompt = true ;
305
+ try {
306
+ await Settings . change ( "powerShellExePath" , undefined , true ) ;
366
307
367
- private getConfiguredPowerShellExePath ( ) : string {
368
- // If powershell.powerShellDefaultVersion specified, attempt to find the PowerShell exe path
369
- // of the version specified by the setting.
370
- if ( this . sessionSettings . powerShellDefaultVersion && this . sessionStatus === SessionStatus . NeverStarted ) {
371
- for ( const pwshExe of this . powershellExeFinder . enumeratePowerShellInstallations ( ) ) {
372
- if ( pwshExe . displayName === this . sessionSettings . powerShellDefaultVersion ) {
373
- return pwshExe . exePath ;
308
+ // This has been deprecated for a while so siliently remove it if it's there.
309
+ if ( this . sessionSettings . developer . powerShellExePath ) {
310
+ await Settings . change ( "developer.powerShellExePath" , undefined , true ) ;
374
311
}
312
+ } finally {
313
+ this . suppressRestartPrompt = false ;
375
314
}
376
315
377
- // Default PowerShell version was configured but we didn't find it
378
- this . log . writeWarning (
379
- `Could not find powerShellDefaultVersion: '${ this . sessionSettings . powerShellDefaultVersion } '` ) ;
380
- }
381
-
382
- if ( this . sessionSettings . powerShellExePath ) {
383
- return this . sessionSettings . powerShellExePath ;
384
- }
385
-
386
- if ( this . sessionSettings . developer . powerShellExePath ) {
387
- this . showExePathSettingDeprecationWarning ( ) ;
388
- return this . sessionSettings . developer . powerShellExePath ;
316
+ // Show the session menu at the end if they don't have a PowerShellDefaultVersion.
317
+ if ( ! this . sessionSettings . powerShellDefaultVersion ) {
318
+ await vscode . commands . executeCommand ( this . ShowSessionMenuCommandName ) ;
319
+ }
389
320
}
390
-
391
- return "" ;
392
321
}
393
322
394
323
private onConfigurationUpdated ( ) {
@@ -398,11 +327,10 @@ export class SessionManager implements Middleware {
398
327
399
328
// Detect any setting changes that would affect the session
400
329
if ( ! this . suppressRestartPrompt &&
401
- ( settings . useX86Host !== this . sessionSettings . useX86Host ||
402
- settings . powerShellExePath . toLowerCase ( ) !== this . sessionSettings . powerShellExePath . toLowerCase ( ) ||
403
- ( settings . developer . powerShellExePath ? settings . developer . powerShellExePath . toLowerCase ( ) : null ) !==
404
- ( this . sessionSettings . developer . powerShellExePath
405
- ? this . sessionSettings . developer . powerShellExePath . toLowerCase ( ) : null ) ||
330
+ ( settings . useX86Host !==
331
+ this . sessionSettings . useX86Host ||
332
+ settings . powerShellDefaultVersion . toLowerCase ( ) !==
333
+ this . sessionSettings . powerShellDefaultVersion . toLowerCase ( ) ||
406
334
settings . developer . editorServicesLogLevel . toLowerCase ( ) !==
407
335
this . sessionSettings . developer . editorServicesLogLevel . toLowerCase ( ) ||
408
336
settings . developer . bundledModulesPath . toLowerCase ( ) !==
@@ -461,7 +389,7 @@ export class SessionManager implements Middleware {
461
389
462
390
this . languageServerProcess =
463
391
new PowerShellProcess (
464
- this . powerShellExePath ,
392
+ this . PowerShellExeDetails . exePath ,
465
393
this . bundledModulesPath ,
466
394
"PowerShell Integrated Console" ,
467
395
this . log ,
@@ -691,63 +619,20 @@ export class SessionManager implements Middleware {
691
619
SessionStatus . Failed ) ;
692
620
}
693
621
694
- private changePowerShellExePath ( exePath : string ) {
622
+ private changePowerShellDefaultVersion ( exePath : IPowerShellExeDetails ) {
695
623
this . suppressRestartPrompt = true ;
696
624
Settings
697
- . change ( "powerShellExePath " , exePath , true )
625
+ . change ( "powerShellDefaultVersion " , exePath . displayName , true )
698
626
. then ( ( ) => this . restartSession ( ) ) ;
699
627
}
700
628
701
- private resolvePowerShellPath ( powerShellExePath : string ) : string {
702
- const resolvedPath = path . resolve ( __dirname , powerShellExePath ) ;
703
-
704
- // If the path does not exist, show an error
705
- if ( ! utils . checkIfFileExists ( resolvedPath ) ) {
706
- const pwshPath = resolvedPath || powerShellExePath ;
707
- const pwshExeName = path . basename ( pwshPath ) || "PowerShell executable" ;
708
-
709
- this . setSessionFailure ( `${ pwshExeName } cannot be found or is not accessible at path '${ pwshPath } '` ) ;
710
-
711
- return null ;
712
- }
713
-
714
- return resolvedPath ;
715
- }
716
-
717
- private getPowerShellVersionLabel ( ) : string {
718
- if ( this . powerShellExePath ) {
719
- const powerShellCommandLine = [
720
- this . powerShellExePath ,
721
- "-NoProfile" ,
722
- "-NonInteractive" ,
723
- ] ;
724
-
725
- // Only add ExecutionPolicy param on Windows
726
- if ( utils . isWindowsOS ( ) ) {
727
- powerShellCommandLine . push ( "-ExecutionPolicy" , "Bypass" ) ;
728
- }
729
-
730
- powerShellCommandLine . push (
731
- "-Command" ,
732
- "'$PSVersionTable | ConvertTo-Json'" ) ;
733
-
734
- const powerShellOutput = cp . execSync ( powerShellCommandLine . join ( " " ) ) ;
735
- const versionDetails = JSON . parse ( powerShellOutput . toString ( ) ) ;
736
- return versionDetails . PSVersion . Label ;
737
- } else {
738
- // TODO: throw instead?
739
- return null ;
740
- }
741
- }
742
-
743
629
private showSessionConsole ( isExecute ?: boolean ) {
744
630
if ( this . languageServerProcess ) {
745
631
this . languageServerProcess . showConsole ( isExecute && ! this . focusConsoleOnExecute ) ;
746
632
}
747
633
}
748
634
749
635
private showSessionMenu ( ) {
750
- const currentExePath = ( this . powerShellExePath || "" ) . toLowerCase ( ) ;
751
636
const availablePowerShellExes = this . powershellExeFinder . getAllAvailablePowerShellInstallations ( ) ;
752
637
753
638
let sessionText : string ;
@@ -760,7 +645,7 @@ export class SessionManager implements Middleware {
760
645
case SessionStatus . Stopping :
761
646
const currentPowerShellExe =
762
647
availablePowerShellExes
763
- . find ( ( item ) => item . exePath . toLowerCase ( ) === currentExePath ) ;
648
+ . find ( ( item ) => item . displayName . toLowerCase ( ) === this . PowerShellExeDetails . displayName ) ;
764
649
765
650
const powerShellSessionName =
766
651
currentPowerShellExe ?
@@ -782,11 +667,11 @@ export class SessionManager implements Middleware {
782
667
783
668
const powerShellItems =
784
669
availablePowerShellExes
785
- . filter ( ( item ) => item . exePath . toLowerCase ( ) !== currentExePath )
670
+ . filter ( ( item ) => item . displayName . toLowerCase ( ) !== this . PowerShellExeDetails . displayName )
786
671
. map ( ( item ) => {
787
672
return new SessionMenuItem (
788
673
`Switch to: ${ item . displayName } ` ,
789
- ( ) => { this . changePowerShellExePath ( item . exePath ) ; } ) ;
674
+ ( ) => { this . changePowerShellDefaultVersion ( item ) ; } ) ;
790
675
} ) ;
791
676
792
677
const menuItems : SessionMenuItem [ ] = [
0 commit comments