44//
55
66using System ;
7+ using System . Management . Automation ;
8+ using System . Text ;
79using System . Threading ;
810using System . Threading . Tasks ;
911using Microsoft . Extensions . Logging ;
12+ using Microsoft . PowerShell . EditorServices . Services ;
13+ using Microsoft . PowerShell . EditorServices . Services . PowerShellContext ;
1014using Microsoft . PowerShell . EditorServices . Utility ;
15+ using OmniSharp . Extensions . LanguageServer . Protocol . Models ;
16+ using OmniSharp . Extensions . LanguageServer . Protocol . Server ;
1117
1218namespace Microsoft . PowerShell . EditorServices . Handlers
1319{
1420 internal class GetVersionHandler : IGetVersionHandler
1521 {
22+ private static readonly Version s_desiredPackageManagementVersion = new Version ( 1 , 4 , 6 ) ;
23+
1624 private readonly ILogger < GetVersionHandler > _logger ;
25+ private readonly PowerShellContextService _powerShellContextService ;
26+ private readonly ILanguageServer _languageServer ;
27+ private readonly ConfigurationService _configurationService ;
1728
18- public GetVersionHandler ( ILoggerFactory factory )
29+ public GetVersionHandler (
30+ ILoggerFactory factory ,
31+ PowerShellContextService powerShellContextService ,
32+ ILanguageServer languageServer ,
33+ ConfigurationService configurationService )
1934 {
2035 _logger = factory . CreateLogger < GetVersionHandler > ( ) ;
36+ _powerShellContextService = powerShellContextService ;
37+ _languageServer = languageServer ;
38+ _configurationService = configurationService ;
2139 }
2240
23- public Task < PowerShellVersion > Handle ( GetVersionParams request , CancellationToken cancellationToken )
41+ public async Task < PowerShellVersion > Handle ( GetVersionParams request , CancellationToken cancellationToken )
2442 {
2543 var architecture = PowerShellProcessArchitecture . Unknown ;
2644 // This should be changed to using a .NET call sometime in the future... but it's just for logging purposes.
@@ -37,13 +55,18 @@ public Task<PowerShellVersion> Handle(GetVersionParams request, CancellationToke
3755 }
3856 }
3957
40- return Task . FromResult ( new PowerShellVersion
58+ if ( VersionUtils . IsPS5 && _configurationService . CurrentSettings . PromptToUpdatePackageManagement )
59+ {
60+ await CheckPackageManagement ( ) . ConfigureAwait ( false ) ;
61+ }
62+
63+ return new PowerShellVersion
4164 {
4265 Version = VersionUtils . PSVersionString ,
4366 Edition = VersionUtils . PSEdition ,
4467 DisplayVersion = VersionUtils . PSVersion . ToString ( 2 ) ,
4568 Architecture = architecture . ToString ( )
46- } ) ;
69+ } ;
4770 }
4871
4972 private enum PowerShellProcessArchitecture
@@ -52,5 +75,68 @@ private enum PowerShellProcessArchitecture
5275 X86 ,
5376 X64
5477 }
78+
79+ private async Task CheckPackageManagement ( )
80+ {
81+ PSCommand getModule = new PSCommand ( ) . AddCommand ( "Get-Module" ) . AddParameter ( "ListAvailable" ) . AddParameter ( "Name" , "PackageManagement" ) ;
82+ foreach ( PSModuleInfo module in await _powerShellContextService . ExecuteCommandAsync < PSModuleInfo > ( getModule ) )
83+ {
84+ // The user has a good enough version of PackageManagement
85+ if ( module . Version >= s_desiredPackageManagementVersion )
86+ {
87+ break ;
88+ }
89+
90+ _logger . LogDebug ( "Old version of PackageManagement detected. Attempting to update." ) ;
91+
92+ var takeActionText = "Yes" ;
93+ MessageActionItem messageAction = await _languageServer . Window . ShowMessage ( new ShowMessageRequestParams
94+ {
95+ Message = "You have an older version of PackageManagement known to cause issues with the PowerShell extension. Would you like to update PackageManagement (You will need to restart the PowerShell extension after)?" ,
96+ Type = MessageType . Warning ,
97+ Actions = new [ ]
98+ {
99+ new MessageActionItem
100+ {
101+ Title = takeActionText
102+ } ,
103+ new MessageActionItem
104+ {
105+ Title = "Not now"
106+ }
107+ }
108+ } ) ;
109+
110+ // If the user chose "Not now" ignore it for the rest of the session.
111+ if ( messageAction ? . Title == takeActionText )
112+ {
113+ StringBuilder errors = new StringBuilder ( ) ;
114+ await _powerShellContextService . ExecuteScriptStringAsync (
115+ "powershell.exe -NoLogo -NoProfile -Command 'Install-Module -Name PackageManagement -Force -MinimumVersion 1.4.6 -Scope CurrentUser -AllowClobber'" ,
116+ errors ,
117+ writeInputToHost : true ,
118+ writeOutputToHost : true ,
119+ addToHistory : true ) . ConfigureAwait ( false ) ;
120+
121+ if ( errors . Length == 0 )
122+ {
123+ _languageServer . Window . ShowMessage ( new ShowMessageParams
124+ {
125+ Type = MessageType . Info ,
126+ Message = "PackageManagement updated, If you already had PackageManagement loaded in your session, please restart the PowerShell extension."
127+ } ) ;
128+ }
129+ else
130+ {
131+ // There were errors installing PackageManagement.
132+ _languageServer . Window . ShowMessage ( new ShowMessageParams
133+ {
134+ Type = MessageType . Error ,
135+ Message = "PackageManagement update failed. Please run the following command in a new Windows PowerShell session and then restart the PowerShell extension: `Install-Module PackageManagement -Force -AllowClobber -MinimumVersion 1.4.6`"
136+ } ) ;
137+ }
138+ }
139+ }
140+ }
55141 }
56142}
0 commit comments