@@ -19,7 +19,7 @@ import { getLanguageConfig } from './languageConfig';
1919import { getCustomConfigProviders } from './customProviders' ;
2020import { PlatformInformation } from '../platform' ;
2121import { Range } from 'vscode-languageclient' ;
22- import { execSync } from 'child_process' ;
22+ import { ChildProcess , spawn , execSync } from 'child_process' ;
2323import * as tmp from 'tmp' ;
2424import { getTargetBuildInfo } from '../githubAPI' ;
2525
@@ -235,8 +235,7 @@ async function installVsix(vsixLocation: string, updateChannel: string): Promise
235235const vsCodeScriptPath :string = function ( platformInfo ) :string {
236236if ( platformInfo . platform === 'win32' ) {
237237const vsCodeBinName :string = path . basename ( process . execPath ) ;
238- // Windows VS Code Insiders breaks VS Code naming conventions
239- let cmdFile :string ;
238+ let cmdFile :string ; // Windows VS Code Insiders breaks VS Code naming conventions
240239if ( vsCodeBinName === 'Code - Insiders.exe' ) {
241240cmdFile = 'code-insiders.cmd' ;
242241} else {
@@ -249,27 +248,45 @@ async function installVsix(vsixLocation: string, updateChannel: string): Promise
249248'Resources' , 'app' , 'bin' , 'code' ) + '"' ;
250249} else {
251250const vsCodeBinName :string = path . basename ( process . execPath ) ;
252- const stdout :Buffer = execSync ( 'which ' + vsCodeBinName ) ;
253- return stdout . toString ( ) . trim ( ) ;
251+ try {
252+ const stdout :Buffer = execSync ( 'which ' + vsCodeBinName ) ;
253+ return stdout . toString ( ) . trim ( ) ;
254+ } catch ( error ) {
255+ return undefined ;
256+ }
254257}
255258} ( platformInfo ) ;
256259if ( ! vsCodeScriptPath ) {
257260return Promise . reject ( new Error ( 'Failed to find VS Code script' ) ) ;
258261}
259262
260263// Install the VSIX
261- const installCommand :string = vsCodeScriptPath + ' --install-extension ' + vsixLocation ;
262- try {
263- if ( updateChannel === 'Default' ) {
264- // Uninstall the current version, as the version to install is a previous version
265- const uninstallCommand :string = vsCodeScriptPath + ' --uninstall-extension ms-vscode.cpptools' ;
266- execSync ( uninstallCommand ) ;
264+ return new Promise < void > ( ( resolve , reject ) => {
265+ let process :ChildProcess = spawn ( vsCodeScriptPath , [ '--install-extension' , vsixLocation ] ) ;
266+ if ( process . pid === undefined ) {
267+ reject ( new Error ( 'Failed to launch VS Code script process for installation' ) ) ;
268+ return ;
267269}
268- execSync ( installCommand ) ;
269- return Promise . resolve ( ) ;
270- } catch ( error ) {
271- return Promise . reject ( new Error ( 'Failed to install VSIX' ) ) ;
272- }
270+
271+ // Timeout the process if no response is sent back. Ensures this Promise resolves/rejects
272+ const timer :NodeJS . Timer = setTimeout ( ( ) => {
273+ process . kill ( ) ;
274+ reject ( new Error ( 'Failed to receive response from VS Code script process for installation within 10s.' ) ) ;
275+ } , 10000 ) ;
276+
277+ // If downgrading, the VS Code CLI will prompt whether the user is sure they would like to downgrade.
278+ // Respond to this by writing 0 to stdin (the option to override and install the VSIX package)
279+ let sentOverride :boolean = false ;
280+ process . stdout . on ( 'data' , ( ) => {
281+ if ( sentOverride ) {
282+ return ;
283+ }
284+ process . stdin . write ( '0\n' ) ;
285+ sentOverride = true ;
286+ clearInterval ( timer ) ;
287+ resolve ( ) ;
288+ } ) ;
289+ } ) ;
273290} ) ;
274291}
275292
@@ -313,8 +330,9 @@ async function checkAndApplyUpdate(updateChannel: string): Promise<void> {
313330return ;
314331}
315332clearInterval ( insiderUpdateTimer ) ;
316- util . promptReloadWindow ( `The C/C++ Extension has been updated to version${ buildInfo . name } . \
317- Please reload the window for the changes to take effect.` ) ;
333+ const message :string =
334+ `The C/C++ Extension has been updated to version${ buildInfo . name } . Please reload the window for the changes to take effect.` ;
335+ util . promptReloadWindow ( message ) ;
318336telemetry . logLanguageServerEvent ( 'installVsix' , { 'success' :'true' } ) ;
319337
320338resolve ( ) ;