From ebea50afee41aef65b3989fc08eb720752d9d60f Mon Sep 17 00:00:00 2001 From: Robo Date: Sat, 22 Oct 2022 03:17:30 +0900 Subject: [PATCH] feat: bundle sparse package to integrate with windows context menu (#151186) * chore: bundle and sign explorer appx * chore: bump vscode-explorer-command@3.0.1 * chore: explorer install/uninstall stage for appx * chore: fix format for cmd exec * chore: cmd file path needs triple quotes * chore: update vscode-explorer-command@3.0.2 * chore: add reg key for new context menu title * chore: update vscode-explorer-command@3.0.3 * fix: guard behind insider quality * chore: fix merge conflict * fix: type mismatch * chore: restrict context menu related actions for win11 * refactor appx loading/unloading, revert inno updater * update powershell * chore: undo inno_updater changes * fix: appx install script * fix: perform install after update step * fix: mv appx install to files section * chore: additional fixes - Remove old context menu entries when updating to newer version - Remove context menu entry when reinstalling without menu action selected. * chore: update vscode-explorer-command@3.0.4 - Fixes garbled title for system installation Co-authored-by: Joao Moreno --- build/azure-pipelines/common/sign.js | 2 + build/azure-pipelines/common/sign.ts | 2 + .../win32/product-build-win32.yml | 12 +++ build/gulpfile.vscode.js | 3 + build/gulpfile.vscode.win32.js | 13 +++- build/win32/code.iss | 74 +++++++++++++++---- build/win32/explorer-appx-fetcher.js | 56 ++++++++++++++ build/win32/explorer-appx-fetcher.ts | 66 +++++++++++++++++ 8 files changed, 213 insertions(+), 15 deletions(-) create mode 100644 build/win32/explorer-appx-fetcher.js create mode 100644 build/win32/explorer-appx-fetcher.ts diff --git a/build/azure-pipelines/common/sign.js b/build/azure-pipelines/common/sign.js index 2c2168cacc3..a1ebcc90e40 100644 --- a/build/azure-pipelines/common/sign.js +++ b/build/azure-pipelines/common/sign.js @@ -13,6 +13,8 @@ function getParams(type) { switch (type) { case 'windows': return '[{"keyCode":"CP-230012","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"Append","parameterValue":"/as"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-230012","operationSetCode":"SigntoolVerify","parameters":[{"parameterName":"VerifyAll","parameterValue":"/all"}],"toolName":"sign","toolVersion":"1.0"}]'; + case 'windows-appx': + return '[{"keyCode":"CP-229979","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-229979","operationSetCode":"SigntoolVerify","parameters":[],"toolName":"sign","toolVersion":"1.0"}]'; case 'rpm': return '[{ "keyCode": "CP-450779-Pgp", "operationSetCode": "LinuxSign", "parameters": [], "toolName": "sign", "toolVersion": "1.0" }]'; case 'darwin-sign': diff --git a/build/azure-pipelines/common/sign.ts b/build/azure-pipelines/common/sign.ts index a50ca698dfd..7f1916d26a2 100644 --- a/build/azure-pipelines/common/sign.ts +++ b/build/azure-pipelines/common/sign.ts @@ -12,6 +12,8 @@ function getParams(type: string): string { switch (type) { case 'windows': return '[{"keyCode":"CP-230012","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"Append","parameterValue":"/as"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-230012","operationSetCode":"SigntoolVerify","parameters":[{"parameterName":"VerifyAll","parameterValue":"/all"}],"toolName":"sign","toolVersion":"1.0"}]'; + case 'windows-appx': + return '[{"keyCode":"CP-229979","operationSetCode":"SigntoolSign","parameters":[{"parameterName":"OpusName","parameterValue":"VS Code"},{"parameterName":"OpusInfo","parameterValue":"https://code.visualstudio.com/"},{"parameterName":"FileDigest","parameterValue":"/fd \\"SHA256\\""},{"parameterName":"PageHash","parameterValue":"/NPH"},{"parameterName":"TimeStamp","parameterValue":"/tr \\"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\\" /td sha256"}],"toolName":"sign","toolVersion":"1.0"},{"keyCode":"CP-229979","operationSetCode":"SigntoolVerify","parameters":[],"toolName":"sign","toolVersion":"1.0"}]'; case 'rpm': return '[{ "keyCode": "CP-450779-Pgp", "operationSetCode": "LinuxSign", "parameters": [], "toolName": "sign", "toolVersion": "1.0" }]'; case 'darwin-sign': diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 374ce89941b..7b7f2f5cad8 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -169,6 +169,17 @@ steps: exec { yarn gulp "transpile-client-swc" "transpile-extensions" } displayName: Transpile + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - powershell: | + . build/azure-pipelines/win32/exec.ps1 + $ErrorActionPreference = "Stop" + $env:VSCODE_EXPLORER_APPX_DIR=$(Join-Path $pwd.Path ".build/win32/appx") + exec { node build/win32/explorer-appx-fetcher } + env: + VSCODE_ARCH: "$(VSCODE_ARCH)" + displayName: Download Explorer Sparse Package + condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false')) + - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}: - powershell: | . build/azure-pipelines/win32/exec.ps1 @@ -279,6 +290,7 @@ steps: . build/azure-pipelines/win32/exec.ps1 $ErrorActionPreference = "Stop" exec { node build\azure-pipelines\common\sign $env:EsrpCliDllPath windows $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(CodeSigningFolderPath) '*.dll,*.exe,*.node' } + exec { node build\azure-pipelines\common\sign $env:EsrpCliDllPath windows-appx $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(CodeSigningFolderPath) '*.appx' } displayName: Codesign - ${{ if eq(parameters.VSCODE_PUBLISH, true) }}: diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 3e099471a34..3f94607dfee 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -371,6 +371,9 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op result = es.merge(result, gulp.src('.build/policies/win32/**', { base: '.build/policies/win32' }) .pipe(rename(f => f.dirname = `policies/${f.dirname}`))); + if (quality === 'insider') { + result = es.merge(result, gulp.src('.build/win32/appx/**', { base: '.build/win32' })); + } } else if (platform === 'linux') { result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' }) .pipe(replace('@@PRODNAME@@', product.nameLong)) diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js index 81ba5095816..9117a021b5a 100644 --- a/build/gulpfile.vscode.win32.js +++ b/build/gulpfile.vscode.win32.js @@ -87,6 +87,7 @@ function buildWin32Setup(arch, target) { productJson['target'] = target; fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t')); + const quality = product.quality; const definitions = { NameLong: product.nameLong, NameShort: product.nameShort, @@ -109,9 +110,19 @@ function buildWin32Setup(arch, target) { RepoDir: repoPath, OutputDir: outputPath, InstallTarget: target, - ProductJsonPath: productJsonPath + ProductJsonPath: productJsonPath, + Quality: quality }; + if (quality === 'insider') { + const appxPackagePrefix = 'code_insiders'; + definitions['AppxPackage'] = `${appxPackagePrefix}_explorer_${arch}.appx`; + if (arch === 'ia32') { + definitions['AppxPackage'] = `${appxPackagePrefix}_explorer_x86.appx`; + } + definitions['AppxPackageFullname'] = `Microsoft.${product.win32RegValueName}_1.0.0.0_neutral__8wekyb3d8bbwe`; + } + packageInnoSetup(issPath, { definitions }, cb); }; } diff --git a/build/win32/code.iss b/build/win32/code.iss index 648a126f167..cc693c24ac4 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -34,6 +34,7 @@ ShowLanguageDialog=auto ArchitecturesAllowed={#ArchitecturesAllowed} ArchitecturesInstallIn64BitMode={#ArchitecturesInstallIn64BitMode} WizardStyle=modern +SetupLogging=yes #ifdef Sign SignTool=esrp @@ -77,7 +78,7 @@ Type: filesandordirs; Name: "{app}\_" Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 Name: "addcontextmenufiles"; Description: "{cm:AddContextMenuFiles,{#NameShort}}"; GroupDescription: "{cm:Other}"; Flags: unchecked -Name: "addcontextmenufolders"; Description: "{cm:AddContextMenuFolders,{#NameShort}}"; GroupDescription: "{cm:Other}"; Flags: unchecked +Name: "addcontextmenufolders"; Description: "{cm:AddContextMenuFolders,{#NameShort}}"; GroupDescription: "{cm:Other}"; Flags: unchecked; Check: not (IsWindows11OrLater and QualityIsInsiders) Name: "associatewithfiles"; Description: "{cm:AssociateWithFiles,{#NameShort}}"; GroupDescription: "{cm:Other}" Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}" Name: "runcode"; Description: "{cm:RunAfter,{#NameShort}}"; GroupDescription: "{cm:Other}"; Check: WizardSilent @@ -86,8 +87,9 @@ Name: "runcode"; Description: "{cm:RunAfter,{#NameShort}}"; GroupDescription: "{ Name: "{app}"; AfterInstall: DisableAppDirInheritance [Files] -Source: "*"; Excludes: "\CodeSignSummary*.md,\tools,\tools\*,\resources\app\product.json"; DestDir: "{code:GetDestDir}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "*"; Excludes: "\CodeSignSummary*.md,\tools,\tools\*,\appx,\appx\*,\resources\app\product.json"; DestDir: "{code:GetDestDir}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "tools\*"; DestDir: "{app}\tools"; Flags: ignoreversion +Source: "appx\*"; DestDir: "{app}\appx"; BeforeInstall: RemoveAppxPackage; AfterInstall: AddAppxPackage; Flags: ignoreversion Source: "{#ProductJsonPath}"; DestDir: "{code:GetDestDir}\resources\app"; Flags: ignoreversion [Icons] @@ -99,6 +101,9 @@ Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#NameLong}"; File Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong}}"; Tasks: runcode; Flags: nowait postinstall; Check: ShouldRunAfterUpdate Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong}}"; Flags: nowait postinstall; Check: WizardNotSilent +[UninstallRun] +Filename: "powershell.exe"; Parameters: "Invoke-Command -ScriptBlock {{Remove-AppxPackage -Package ""{#AppxPackageFullname}""}"; Check: IsWindows11OrLater and QualityIsInsiders; Flags: shellexec waituntilterminated runhidden + [Registry] #if "user" == InstallTarget #define SoftwareClassesRootKey "HKCU" @@ -1261,18 +1266,19 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Applications\{#ExeBas Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Applications\{#ExeBasename}.exe\shell\open"; ValueType: string; ValueName: "Icon"; ValueData: """{app}\{#ExeBasename}.exe""" Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Applications\{#ExeBasename}.exe\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1""" -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufiles; Flags: uninsdeletekey -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufiles -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: addcontextmenufiles -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}ContextMenu"; ValueType: expandsz; ValueName: "Title"; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufiles; Flags: uninsdeletekey; Check: IsWindows11OrLater and QualityIsInsiders +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufiles; Flags: uninsdeletekey; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufiles; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: addcontextmenufiles; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders; Check: not (IsWindows11OrLater and QualityIsInsiders) +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders; Check: not (IsWindows11OrLater and QualityIsInsiders) ; Environment #if "user" == InstallTarget @@ -1376,6 +1382,11 @@ begin Result := True; end; +function IsWindows11OrLater(): Boolean; +begin + Result := (GetWindowsVersion >= $0A0055F0); +end; + function GetAppMutex(Value: string): string; begin if IsBackgroundUpdate() then @@ -1400,6 +1411,41 @@ begin Result := 'false'; end; +function QualityIsInsiders(): boolean; +begin + if '{#Quality}' = 'insider' then + Result := True + else + Result := False; +end; + +procedure AddAppxPackage(); +var + AddAppxPackageResultCode: Integer; +begin + if IsWindows11OrLater() and QualityIsInsiders() then begin + if WizardIsTaskSelected('addcontextmenufiles') then begin + ShellExec('', 'powershell.exe', '-Command ' + AddQuotes('Add-AppxPackage -Path ''' + ExpandConstant('{app}\appx\{#AppxPackage}') + ''' -ExternalLocation ''' + ExpandConstant('{app}\appx') + ''''), '', SW_HIDE, ewWaitUntilTerminated, AddAppxPackageResultCode); + RegDeleteKeyIncludingSubkeys({#EnvironmentRootKey}, 'Software\Classes\*\shell\{#RegValueName}'); + RegDeleteKeyIncludingSubkeys({#EnvironmentRootKey}, 'Software\Classes\directory\shell\{#RegValueName}'); + RegDeleteKeyIncludingSubkeys({#EnvironmentRootKey}, 'Software\Classes\directory\background\shell\{#RegValueName}'); + RegDeleteKeyIncludingSubkeys({#EnvironmentRootKey}, 'Software\Classes\Drive\shell\{#RegValueName}'); + end; + end; +end; + +procedure RemoveAppxPackage(); +var + RemoveAppxPackageResultCode: Integer; +begin + if IsWindows11OrLater() and QualityIsInsiders() then begin + ShellExec('', 'powershell.exe', '-Command ' + AddQuotes('Remove-AppxPackage -Package ''{#AppxPackageFullname}'''), '', SW_HIDE, ewWaitUntilTerminated, RemoveAppxPackageResultCode); + if not WizardIsTaskSelected('addcontextmenufiles') then begin + RegDeleteKeyIncludingSubkeys({#EnvironmentRootKey}, 'Software\Classes\{#RegValueName}ContextMenu'); + end; + end; +end; + procedure CurStepChanged(CurStep: TSetupStep); var UpdateResultCode: Integer; diff --git a/build/win32/explorer-appx-fetcher.js b/build/win32/explorer-appx-fetcher.js new file mode 100644 index 00000000000..64b5ce9c117 --- /dev/null +++ b/build/win32/explorer-appx-fetcher.js @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.downloadExplorerAppx = void 0; +const debug = require("debug"); +const extract = require("extract-zip"); +const fs = require("fs-extra"); +const path = require("path"); +const product = require("../../product.json"); +const get_1 = require("@electron/get"); +const d = debug('explorer-appx-fetcher'); +async function downloadExplorerAppx(outDir, quality = 'stable', targetArch = 'x64') { + const fileNamePrefix = quality === 'insider' ? 'code_insiders' : 'code'; + const fileName = `${fileNamePrefix}_explorer_${targetArch}.zip`; + if (await fs.pathExists(path.resolve(outDir, 'resources.pri'))) { + return; + } + if (!await fs.pathExists(outDir)) { + await fs.mkdirp(outDir); + } + d(`downloading ${fileName}`); + const artifact = await (0, get_1.downloadArtifact)({ + isGeneric: true, + version: '3.0.4', + artifactName: fileName, + unsafelyDisableChecksums: true, + mirrorOptions: { + mirror: 'https://github.com/microsoft/vscode-explorer-command/releases/download/', + customDir: '3.0.4', + customFilename: fileName + } + }); + d(`unpacking from ${fileName}`); + await extract(artifact, { dir: outDir }); +} +exports.downloadExplorerAppx = downloadExplorerAppx; +async function main() { + const outputDir = process.env['VSCODE_EXPLORER_APPX_DIR']; + let arch = process.env['VSCODE_ARCH']; + if (!outputDir) { + throw new Error('Required build env not set'); + } + if (arch === 'ia32') { + arch = 'x86'; + } + await downloadExplorerAppx(outputDir, product.quality, arch); +} +if (require.main === module) { + main().catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/build/win32/explorer-appx-fetcher.ts b/build/win32/explorer-appx-fetcher.ts new file mode 100644 index 00000000000..9f49d954474 --- /dev/null +++ b/build/win32/explorer-appx-fetcher.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as debug from 'debug'; +import * as extract from 'extract-zip'; +import * as fs from 'fs-extra'; +import * as path from 'path'; +import * as product from '../../product.json'; +import { downloadArtifact } from '@electron/get'; + +const d = debug('explorer-appx-fetcher'); + +export async function downloadExplorerAppx(outDir: string, quality: string = 'stable', targetArch: string = 'x64'): Promise { + const fileNamePrefix = quality === 'insider' ? 'code_insiders' : 'code'; + const fileName = `${fileNamePrefix}_explorer_${targetArch}.zip`; + + if (await fs.pathExists(path.resolve(outDir, 'resources.pri'))) { + return; + } + + if (!await fs.pathExists(outDir)) { + await fs.mkdirp(outDir); + } + + d(`downloading ${fileName}`); + const artifact = await downloadArtifact({ + isGeneric: true, + version: '3.0.4', + artifactName: fileName, + unsafelyDisableChecksums: true, + mirrorOptions: { + mirror: 'https://github.com/microsoft/vscode-explorer-command/releases/download/', + customDir: '3.0.4', + customFilename: fileName + } + }); + + d(`unpacking from ${fileName}`); + await extract(artifact, { dir: outDir }); +} + +async function main(): Promise { + const outputDir = process.env['VSCODE_EXPLORER_APPX_DIR']; + let arch = process.env['VSCODE_ARCH']; + + if (!outputDir) { + throw new Error('Required build env not set'); + } + + if (arch === 'ia32') { + arch = 'x86'; + } + + await downloadExplorerAppx(outputDir, (product as any).quality, arch); +} + +if (require.main === module) { + main().catch(err => { + console.error(err); + process.exit(1); + }); +}