mirror of https://github.com/microsoft/vscode.git
feat: support device permissions via package identity (#257741)
* feat: support device permissions via package identity * chore: update explorer dll checksums * chore: cleanup appx preparation * chore: avoid cross-device link error * chore: remove appx installation gate * chore: rm duplicate appx installation checks * chore: extract package full name from Get-AppxPackage * chore: fix remove-appxpackage command
This commit is contained in:
parent
1bd100374b
commit
f5e06c148d
|
@ -175,9 +175,9 @@ steps:
|
|||
displayName: Transpile client and extensions
|
||||
|
||||
- ${{ else }}:
|
||||
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), eq(parameters.VSCODE_QUALITY, 'insider')) }}:
|
||||
- powershell: node build/win32/explorer-appx-fetcher .build/win32/appx
|
||||
displayName: Download Explorer Sparse Package
|
||||
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'exploration')) }}:
|
||||
- powershell: node build/win32/explorer-dll-fetcher .build/win32/appx
|
||||
displayName: Download Explorer dll
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
|
@ -190,6 +190,23 @@ steps:
|
|||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||
displayName: Build client
|
||||
|
||||
# Note: the appx prepare step has to follow Build client step since build step replaces the template
|
||||
# strings in the raw manifest file at resources/win32/appx/AppxManifest.xml and places it under
|
||||
# <build-out-dir>/appx/manifest, we need a separate step to prepare the appx package with the
|
||||
# final contents. In our case only the manifest file is bundled into the appx package.
|
||||
- ${{ if and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'exploration')) }}:
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
# Add Windows SDK to path
|
||||
$sdk = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64"
|
||||
$env:PATH = "$sdk;$env:PATH"
|
||||
$AppxName = if ('$(VSCODE_QUALITY)' -eq 'stable') { 'code' } else { 'code_insider' }
|
||||
makeappx pack /d "$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)/appx/manifest" /p "$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)/appx/${AppxName}_$(VSCODE_ARCH).appx" /nv
|
||||
# Remove the raw manifest folder
|
||||
Remove-Item -Path "$(Agent.BuildDirectory)/VSCode-win32-$(VSCODE_ARCH)/appx/manifest" -Recurse -Force
|
||||
displayName: Prepare appx package
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
11b36db4f244693381e52316261ce61678286f6bdfe2614c6352f6fecf3f060d code_explorer_command_arm64.dll
|
||||
bfab3719038ca46bcd8afb9249a00f851dd08aa3cc8d13d01a917111a2a6d7c2 code_explorer_command_x64.dll
|
||||
b5cd79c1e91390bdeefaf35cc5c62a6022220832e145781e5609913fac706ad9 code_insider_explorer_command_arm64.dll
|
||||
f04335cc6fbe8425bd5516e6acbfa05ca706fd7566799a1e22fca1344c25351f code_insider_explorer_command_x64.dll
|
|
@ -404,8 +404,21 @@ 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') {
|
||||
if (quality !== 'exploration') {
|
||||
result = es.merge(result, gulp.src('.build/win32/appx/**', { base: '.build/win32' }));
|
||||
const rawVersion = version.replace(/-\w+$/, '').split('.');
|
||||
const appxVersion = `${rawVersion[0]}.0.${rawVersion[1]}.${rawVersion[2]}`;
|
||||
result = es.merge(result, gulp.src('resources/win32/appx/AppxManifest.xml', { base: '.' })
|
||||
.pipe(replace('@@AppxPackageName@@', product.win32AppUserModelId))
|
||||
.pipe(replace('@@AppxPackageVersion@@', appxVersion))
|
||||
.pipe(replace('@@AppxPackageDisplayName@@', product.nameLong))
|
||||
.pipe(replace('@@AppxPackageDescription@@', product.win32NameVersion))
|
||||
.pipe(replace('@@ApplicationIdShort@@', product.win32RegValueName))
|
||||
.pipe(replace('@@ApplicationExe@@', product.nameShort + '.exe'))
|
||||
.pipe(replace('@@FileExplorerContextMenuID@@', quality === 'stable' ? 'OpenWithCode' : 'OpenWithCodeInsiders'))
|
||||
.pipe(replace('@@FileExplorerContextMenuCLSID@@', product.win32ContextMenu[arch].clsid))
|
||||
.pipe(replace('@@FileExplorerContextMenuDLL@@', `${quality === 'stable' ? 'code' : 'code_insider'}_explorer_command_${arch}.dll`))
|
||||
.pipe(rename(f => f.dirname = `appx/manifest`)));
|
||||
}
|
||||
} else if (platform === 'linux') {
|
||||
result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
|
||||
|
|
|
@ -112,10 +112,9 @@ function buildWin32Setup(arch, target) {
|
|||
Quality: quality
|
||||
};
|
||||
|
||||
if (quality === 'insider') {
|
||||
definitions['AppxPackage'] = `code_insiders_explorer_${arch}.appx`;
|
||||
definitions['AppxPackageFullname'] = `Microsoft.${product.win32RegValueName}_1.0.0.0_neutral__8wekyb3d8bbwe`;
|
||||
definitions['AppxPackageName'] = `Microsoft.${product.win32RegValueName}`;
|
||||
if (quality !== 'exploration') {
|
||||
definitions['AppxPackage'] = `${quality === 'stable' ? 'code' : 'code_insider'}_${arch}.appx`;
|
||||
definitions['AppxPackageName'] = `${product.win32AppUserModelId}`;
|
||||
}
|
||||
|
||||
packageInnoSetup(issPath, { definitions }, cb);
|
||||
|
|
|
@ -94,8 +94,8 @@ Name: "{app}"; AfterInstall: DisableAppDirInheritance
|
|||
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: "{#ProductJsonPath}"; DestDir: "{code:GetDestDir}\resources\app"; Flags: ignoreversion
|
||||
#ifdef AppxPackageFullname
|
||||
Source: "appx\*"; DestDir: "{app}\appx"; BeforeInstall: RemoveAppxPackage; AfterInstall: AddAppxPackage; Flags: ignoreversion; Check: IsWindows11OrLater and QualityIsInsiders
|
||||
#ifdef AppxPackageName
|
||||
Source: "appx\*"; DestDir: "{app}\appx"; BeforeInstall: RemoveAppxPackage; AfterInstall: AddAppxPackage; Flags: ignoreversion; Check: IsWindows11OrLater
|
||||
#endif
|
||||
|
||||
[Icons]
|
||||
|
@ -1466,26 +1466,26 @@ begin
|
|||
Result := False;
|
||||
end;
|
||||
|
||||
#ifdef AppxPackageFullname
|
||||
#ifdef AppxPackageName
|
||||
var
|
||||
Line: String;
|
||||
AppxPackageFullname: String;
|
||||
|
||||
procedure ExecAndGetFirstLineLog(const S: String; const Error, FirstLine: Boolean);
|
||||
begin
|
||||
if not Error and (Line = '') and (Trim(S) <> '') then
|
||||
Line := S;
|
||||
if not Error and (AppxPackageFullname = '') and (Trim(S) <> '') then
|
||||
AppxPackageFullname := S;
|
||||
Log(S);
|
||||
end;
|
||||
|
||||
function AppxPackageInstalled(var ResultCode: Integer): Boolean;
|
||||
begin
|
||||
Line := '';
|
||||
AppxPackageFullname := '';
|
||||
try
|
||||
ExecAndLogOutput('powershell.exe', '-Command ' + AddQuotes('Get-AppxPackage -Name ''{#AppxPackageName}'''), '', SW_HIDE, ewWaitUntilTerminated, ResultCode, @ExecAndGetFirstLineLog);
|
||||
ExecAndLogOutput('powershell.exe', '-Command ' + AddQuotes('Get-AppxPackage -Name ''{#AppxPackageName}'' | Select-Object -ExpandProperty PackageFullName'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode, @ExecAndGetFirstLineLog);
|
||||
except
|
||||
Log(GetExceptionMessage);
|
||||
end;
|
||||
if (Line <> '') then
|
||||
if (AppxPackageFullname <> '') then
|
||||
Result := True
|
||||
else
|
||||
Result := False
|
||||
|
@ -1495,7 +1495,7 @@ procedure AddAppxPackage();
|
|||
var
|
||||
AddAppxPackageResultCode: Integer;
|
||||
begin
|
||||
if not AppxPackageInstalled(AddAppxPackageResultCode) and WizardIsTaskSelected('addcontextmenufiles') then begin
|
||||
if not AppxPackageInstalled(AddAppxPackageResultCode) then begin
|
||||
ShellExec('', 'powershell.exe', '-Command ' + AddQuotes('Add-AppxPackage -Path ''' + ExpandConstant('{app}\appx\{#AppxPackage}') + ''' -ExternalLocation ''' + ExpandConstant('{app}\appx') + ''''), '', SW_HIDE, ewWaitUntilTerminated, AddAppxPackageResultCode);
|
||||
end;
|
||||
end;
|
||||
|
@ -1505,7 +1505,7 @@ var
|
|||
RemoveAppxPackageResultCode: Integer;
|
||||
begin
|
||||
if AppxPackageInstalled(RemoveAppxPackageResultCode) then begin
|
||||
ShellExec('', 'powershell.exe', '-Command ' + AddQuotes('Remove-AppxPackage -Package ''{#AppxPackageFullname}'''), '', SW_HIDE, ewWaitUntilTerminated, RemoveAppxPackageResultCode);
|
||||
ShellExec('', 'powershell.exe', '-Command ' + AddQuotes('Remove-AppxPackage -Package ''' + AppxPackageFullname + ''''), '', SW_HIDE, ewWaitUntilTerminated, RemoveAppxPackageResultCode);
|
||||
end;
|
||||
end;
|
||||
#endif
|
||||
|
@ -1517,7 +1517,7 @@ var
|
|||
begin
|
||||
if CurStep = ssPostInstall then
|
||||
begin
|
||||
#ifdef AppxPackageFullname
|
||||
#ifdef AppxPackageName
|
||||
if not WizardIsTaskSelected('addcontextmenufiles') then begin
|
||||
RegDeleteKeyIncludingSubkeys({#EnvironmentRootKey}, 'Software\Classes\{#RegValueName}ContextMenu');
|
||||
end else begin
|
||||
|
@ -1606,15 +1606,12 @@ var
|
|||
Parts: TArrayOfString;
|
||||
NewPath: string;
|
||||
i: Integer;
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
if not CurUninstallStep = usUninstall then begin
|
||||
exit;
|
||||
end;
|
||||
#ifdef AppxPackageFullname
|
||||
if AppxPackageInstalled(ResultCode) then begin
|
||||
RemoveAppxPackage();
|
||||
end;
|
||||
#ifdef AppxPackageName
|
||||
RemoveAppxPackage();
|
||||
#endif
|
||||
if not RegQueryStringValue({#EnvironmentRootKey}, '{#EnvironmentKey}', 'Path', Path)
|
||||
then begin
|
||||
|
|
|
@ -7,45 +7,53 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.downloadExplorerAppx = downloadExplorerAppx;
|
||||
exports.downloadExplorerDll = downloadExplorerDll;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const debug_1 = __importDefault(require("debug"));
|
||||
const extract_zip_1 = __importDefault(require("extract-zip"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const get_1 = require("@electron/get");
|
||||
const root = path_1.default.dirname(path_1.default.dirname(__dirname));
|
||||
const d = (0, debug_1.default)('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_1.default.existsSync(path_1.default.resolve(outDir, 'resources.pri'))) {
|
||||
return;
|
||||
}
|
||||
const product_json_1 = __importDefault(require("../../product.json"));
|
||||
const d = (0, debug_1.default)('explorer-dll-fetcher');
|
||||
async function downloadExplorerDll(outDir, quality = 'stable', targetArch = 'x64') {
|
||||
const fileNamePrefix = quality === 'insider' ? 'code_insider' : 'code';
|
||||
const fileName = `${fileNamePrefix}_explorer_command_${targetArch}.dll`;
|
||||
if (!await fs_1.default.existsSync(outDir)) {
|
||||
await fs_1.default.mkdirSync(outDir, { recursive: true });
|
||||
}
|
||||
// Read and parse checksums file
|
||||
const checksumsFilePath = path_1.default.join(path_1.default.dirname(__dirname), 'checksums', 'explorer-dll.txt');
|
||||
const checksumsContent = fs_1.default.readFileSync(checksumsFilePath, 'utf8');
|
||||
const checksums = {};
|
||||
checksumsContent.split('\n').forEach(line => {
|
||||
const trimmedLine = line.trim();
|
||||
if (trimmedLine) {
|
||||
const [checksum, filename] = trimmedLine.split(/\s+/);
|
||||
if (checksum && filename) {
|
||||
checksums[filename] = checksum;
|
||||
}
|
||||
}
|
||||
});
|
||||
d(`downloading ${fileName}`);
|
||||
const artifact = await (0, get_1.downloadArtifact)({
|
||||
isGeneric: true,
|
||||
version: '3.0.4',
|
||||
version: 'v4.0.0-350164',
|
||||
artifactName: fileName,
|
||||
unsafelyDisableChecksums: true,
|
||||
checksums,
|
||||
mirrorOptions: {
|
||||
mirror: 'https://github.com/microsoft/vscode-explorer-command/releases/download/',
|
||||
customDir: '3.0.4',
|
||||
customDir: 'v4.0.0-350164',
|
||||
customFilename: fileName
|
||||
}
|
||||
});
|
||||
d(`unpacking from ${fileName}`);
|
||||
await (0, extract_zip_1.default)(artifact, { dir: fs_1.default.realpathSync(outDir) });
|
||||
d(`moving ${artifact} to ${outDir}`);
|
||||
await fs_1.default.copyFileSync(artifact, path_1.default.join(outDir, fileName));
|
||||
}
|
||||
async function main(outputDir) {
|
||||
const arch = process.env['VSCODE_ARCH'];
|
||||
if (!outputDir) {
|
||||
throw new Error('Required build env not set');
|
||||
}
|
||||
const product = JSON.parse(fs_1.default.readFileSync(path_1.default.join(root, 'product.json'), 'utf8'));
|
||||
await downloadExplorerAppx(outputDir, product.quality, arch);
|
||||
await downloadExplorerDll(outputDir, product_json_1.default.quality, arch);
|
||||
}
|
||||
if (require.main === module) {
|
||||
main(process.argv[2]).catch(err => {
|
||||
|
@ -53,4 +61,4 @@ if (require.main === module) {
|
|||
process.exit(1);
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=explorer-appx-fetcher.js.map
|
||||
//# sourceMappingURL=explorer-dll-fetcher.js.map
|
|
@ -7,41 +7,50 @@
|
|||
|
||||
import fs from 'fs';
|
||||
import debug from 'debug';
|
||||
import extract from 'extract-zip';
|
||||
import path from 'path';
|
||||
import { downloadArtifact } from '@electron/get';
|
||||
import product from '../../product.json';
|
||||
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const d = debug('explorer-dll-fetcher');
|
||||
|
||||
const d = debug('explorer-appx-fetcher');
|
||||
|
||||
export async function downloadExplorerAppx(outDir: string, quality: string = 'stable', targetArch: string = 'x64'): Promise<void> {
|
||||
const fileNamePrefix = quality === 'insider' ? 'code_insiders' : 'code';
|
||||
const fileName = `${fileNamePrefix}_explorer_${targetArch}.zip`;
|
||||
|
||||
if (await fs.existsSync(path.resolve(outDir, 'resources.pri'))) {
|
||||
return;
|
||||
}
|
||||
export async function downloadExplorerDll(outDir: string, quality: string = 'stable', targetArch: string = 'x64'): Promise<void> {
|
||||
const fileNamePrefix = quality === 'insider' ? 'code_insider' : 'code';
|
||||
const fileName = `${fileNamePrefix}_explorer_command_${targetArch}.dll`;
|
||||
|
||||
if (!await fs.existsSync(outDir)) {
|
||||
await fs.mkdirSync(outDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Read and parse checksums file
|
||||
const checksumsFilePath = path.join(path.dirname(__dirname), 'checksums', 'explorer-dll.txt');
|
||||
const checksumsContent = fs.readFileSync(checksumsFilePath, 'utf8');
|
||||
const checksums: Record<string, string> = {};
|
||||
|
||||
checksumsContent.split('\n').forEach(line => {
|
||||
const trimmedLine = line.trim();
|
||||
if (trimmedLine) {
|
||||
const [checksum, filename] = trimmedLine.split(/\s+/);
|
||||
if (checksum && filename) {
|
||||
checksums[filename] = checksum;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
d(`downloading ${fileName}`);
|
||||
const artifact = await downloadArtifact({
|
||||
isGeneric: true,
|
||||
version: '3.0.4',
|
||||
version: 'v4.0.0-350164',
|
||||
artifactName: fileName,
|
||||
unsafelyDisableChecksums: true,
|
||||
checksums,
|
||||
mirrorOptions: {
|
||||
mirror: 'https://github.com/microsoft/vscode-explorer-command/releases/download/',
|
||||
customDir: '3.0.4',
|
||||
customDir: 'v4.0.0-350164',
|
||||
customFilename: fileName
|
||||
}
|
||||
});
|
||||
|
||||
d(`unpacking from ${fileName}`);
|
||||
await extract(artifact, { dir: fs.realpathSync(outDir) });
|
||||
d(`moving ${artifact} to ${outDir}`);
|
||||
await fs.copyFileSync(artifact, path.join(outDir, fileName));
|
||||
}
|
||||
|
||||
async function main(outputDir?: string): Promise<void> {
|
||||
|
@ -51,8 +60,7 @@ async function main(outputDir?: string): Promise<void> {
|
|||
throw new Error('Required build env not set');
|
||||
}
|
||||
|
||||
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
|
||||
await downloadExplorerAppx(outputDir, (product as any).quality, arch);
|
||||
await downloadExplorerDll(outputDir, (product as any).quality, arch);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
|
||||
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
|
||||
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
|
||||
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
|
||||
xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
|
||||
xmlns:desktop10="http://schemas.microsoft.com/appx/manifest/desktop/windows10/10"
|
||||
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
|
||||
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
|
||||
IgnorableNamespaces="uap uap2 uap3 rescap desktop desktop4 desktop5 desktop6 desktop10 uap10 com">
|
||||
<Identity
|
||||
Name="@@AppxPackageName@@"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="@@AppxPackageVersion@@"
|
||||
ProcessorArchitecture="neutral" />
|
||||
<Properties>
|
||||
<DisplayName>@@AppxPackageDisplayName@@</DisplayName>
|
||||
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
|
||||
<Logo>resources\app\resources\win32\code_150x150.png</Logo>
|
||||
<uap10:AllowExternalContent>true</uap10:AllowExternalContent>
|
||||
<desktop6:RegistryWriteVirtualization>disabled</desktop6:RegistryWriteVirtualization>
|
||||
<desktop6:FileSystemWriteVirtualization>disabled</desktop6:FileSystemWriteVirtualization>
|
||||
</Properties>
|
||||
<Resources>
|
||||
<Resource Language="en-us" />
|
||||
<Resource Language="es-es" />
|
||||
<Resource Language="de-de" />
|
||||
<Resource Language="fr-fr" />
|
||||
<Resource Language="hu-hu" />
|
||||
<Resource Language="it-it" />
|
||||
<Resource Language="ja-jp" />
|
||||
<Resource Language="ko-kr" />
|
||||
<Resource Language="pt-br" />
|
||||
<Resource Language="ru-ru" />
|
||||
<Resource Language="tr-tr" />
|
||||
<Resource Language="zh-cn" />
|
||||
<Resource Language="zh-tw" />
|
||||
</Resources>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.26100.0" />
|
||||
</Dependencies>
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="unvirtualizedResources"/>
|
||||
<DeviceCapability Name="microphone"/>
|
||||
</Capabilities>
|
||||
<Applications>
|
||||
<Application Id="@@ApplicationIdShort@@"
|
||||
Executable="@@ApplicationExe@@"
|
||||
uap10:TrustLevel="mediumIL"
|
||||
uap10:RuntimeBehavior="win32App">
|
||||
<uap:VisualElements
|
||||
AppListEntry="none"
|
||||
DisplayName="@@AppxPackageDisplayName@@"
|
||||
Description="@@AppxPackageDescription@@"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="resources\app\resources\win32\code_150x150.png"
|
||||
Square44x44Logo="resources\app\resources\win32\code_70x70.png">
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
<desktop4:Extension Category="windows.fileExplorerContextMenus">
|
||||
<desktop4:FileExplorerContextMenus>
|
||||
<desktop5:ItemType Type="Directory">
|
||||
<desktop5:Verb Id="@@FileExplorerContextMenuID@@" Clsid="@@FileExplorerContextMenuCLSID@@" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="Directory\Background">
|
||||
<desktop5:Verb Id="@@FileExplorerContextMenuID@@" Clsid="@@FileExplorerContextMenuCLSID@@" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="*">
|
||||
<desktop5:Verb Id="@@FileExplorerContextMenuID@@" Clsid="@@FileExplorerContextMenuCLSID@@" />
|
||||
</desktop5:ItemType>
|
||||
</desktop4:FileExplorerContextMenus>
|
||||
</desktop4:Extension>
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:SurrogateServer DisplayName="@@AppxPackageDisplayName@@">
|
||||
<com:Class Id="@@FileExplorerContextMenuCLSID@@" Path="@@FileExplorerContextMenuDLL@@" ThreadingModel="STA"/>
|
||||
</com:SurrogateServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
</Package>
|
Loading…
Reference in New Issue