mirror of
https://github.com/microsoft/vscode.git
synced 2026-06-02 05:35:30 +01:00
add wslFeatureInstalled context key (#160424)
* add wslFeatureInstalled context key * only register the contribution when on windows * add doc * wait for LifecyclePhase#Eventually
This commit is contained in:
committed by
GitHub
parent
0dce868b85
commit
746fda3a60
@@ -121,6 +121,8 @@ export interface ICommonNativeHostService {
|
||||
|
||||
getOSColorScheme(): Promise<IColorScheme>;
|
||||
|
||||
hasWSLFeatureInstalled(): Promise<boolean>;
|
||||
|
||||
// Process
|
||||
killProcess(pid: number, code: string): Promise<void>;
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import { IWindowsMainService, OpenContext } from 'vs/platform/windows/electron-m
|
||||
import { isWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { hasWSLFeatureInstalled } from 'vs/platform/remote/node/wsl';
|
||||
|
||||
export interface INativeHostMainService extends AddFirstParameterToFunctions<ICommonNativeHostService, Promise<unknown> /* only methods, not events */, number | undefined /* window ID */> { }
|
||||
|
||||
@@ -568,6 +569,12 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
|
||||
}
|
||||
|
||||
|
||||
// WSL
|
||||
public async hasWSLFeatureInstalled(): Promise<boolean> {
|
||||
return isWindows && hasWSLFeatureInstalled();
|
||||
}
|
||||
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as os from 'os';
|
||||
import * as cp from 'child_process';
|
||||
import { promises as fs } from 'fs';
|
||||
import path = require('path');
|
||||
|
||||
let hasWSLFeaturePromise: Promise<boolean> | undefined;
|
||||
|
||||
export async function hasWSLFeatureInstalled(refresh = false): Promise<boolean> {
|
||||
if (hasWSLFeaturePromise === undefined || refresh) {
|
||||
hasWSLFeaturePromise = testWSLFeatureInstalled();
|
||||
}
|
||||
return hasWSLFeaturePromise;
|
||||
}
|
||||
|
||||
async function testWSLFeatureInstalled(): Promise<boolean> {
|
||||
const windowsBuildNumber = getWindowsBuildNumber();
|
||||
if (windowsBuildNumber === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (windowsBuildNumber >= 22000) {
|
||||
const wslExePath = getWSLExecutablePath();
|
||||
if (wslExePath) {
|
||||
return new Promise<boolean>(s => {
|
||||
cp.execFile(wslExePath, ['--status'], err => s(!err));
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const dllPath = getLxssManagerDllPath();
|
||||
if (dllPath) {
|
||||
try {
|
||||
if ((await fs.stat(dllPath)).isFile()) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getWindowsBuildNumber(): number | undefined {
|
||||
const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release());
|
||||
if (osVersion) {
|
||||
return parseInt(osVersion[3]);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSystem32Path(subPath: string): string | undefined {
|
||||
const systemRoot = process.env['SystemRoot'];
|
||||
if (systemRoot) {
|
||||
const is32ProcessOn64Windows = process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432');
|
||||
return path.join(systemRoot, is32ProcessOn64Windows ? 'Sysnative' : 'System32', subPath);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getWSLExecutablePath(): string | undefined {
|
||||
return getSystem32Path('wsl.exe');
|
||||
}
|
||||
|
||||
/**
|
||||
* In builds < 22000 this dll inidcates that WSL is installed
|
||||
*/
|
||||
function getLxssManagerDllPath(): string | undefined {
|
||||
return getSystem32Path('lxss\\LxssManager.dll');
|
||||
}
|
||||
@@ -7,11 +7,11 @@ import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchContributionsExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -27,6 +27,9 @@ import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderComman
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
class RemoteAgentDiagnosticListener implements IWorkbenchContribution {
|
||||
constructor(
|
||||
@@ -131,11 +134,49 @@ class RemoteEmptyWorkbenchPresentation extends Disposable implements IWorkbenchC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'wslFeatureInstalled' context key if the WSL feature is or was installed on this machine.
|
||||
*/
|
||||
class WSLContextKeyInitializer extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@INativeHostService nativeHostService: INativeHostService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService
|
||||
) {
|
||||
super();
|
||||
|
||||
const contextKeyId = 'wslFeatureInstalled';
|
||||
const storageKey = 'remote.wslFeatureInstalled';
|
||||
|
||||
const defaultValue = storageService.getBoolean(storageKey, StorageScope.APPLICATION, undefined);
|
||||
|
||||
const hasWSLFeatureContext = new RawContextKey<boolean>(contextKeyId, !!defaultValue, nls.localize('wslFeatureInstalled', "Whether the platform has the WSL feature installed"));
|
||||
const contextKey = hasWSLFeatureContext.bindTo(contextKeyService);
|
||||
|
||||
if (defaultValue === undefined) {
|
||||
lifecycleService.when(LifecyclePhase.Eventually).then(async () => {
|
||||
nativeHostService.hasWSLFeatureInstalled().then(res => {
|
||||
if (res) {
|
||||
contextKey.set(true);
|
||||
// once detected, set to true
|
||||
storageService.store(storageKey, true, StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchContributionsExtensions.Workbench);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteAgentDiagnosticListener, 'RemoteAgentDiagnosticListener', LifecyclePhase.Eventually);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteExtensionHostEnvironmentUpdater, 'RemoteExtensionHostEnvironmentUpdater', LifecyclePhase.Eventually);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteTelemetryEnablementUpdater, 'RemoteTelemetryEnablementUpdater', LifecyclePhase.Ready);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(RemoteEmptyWorkbenchPresentation, 'RemoteEmptyWorkbenchPresentation', LifecyclePhase.Ready);
|
||||
if (isWindows) {
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(WSLContextKeyInitializer, 'WSLContextKeyInitializer', LifecyclePhase.Ready);
|
||||
}
|
||||
|
||||
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
||||
.registerConfiguration({
|
||||
|
||||
@@ -240,6 +240,7 @@ export class TestNativeHostService implements INativeHostService {
|
||||
async getOSStatistics(): Promise<IOSStatistics> { return Object.create(null); }
|
||||
async getOSVirtualMachineHint(): Promise<number> { return 0; }
|
||||
async getOSColorScheme(): Promise<IColorScheme> { return { dark: true, highContrast: false }; }
|
||||
async hasWSLFeatureInstalled(): Promise<boolean> { return false; }
|
||||
async killProcess(): Promise<void> { }
|
||||
async setDocumentEdited(edited: boolean): Promise<void> { }
|
||||
async openExternal(url: string): Promise<boolean> { return false; }
|
||||
|
||||
Reference in New Issue
Block a user