Skip to content

Commit 4e59fd8

Browse files
authored
sandbox - detect windows admin crash as telemetry event (microsoft#167063)
1 parent 4222ce8 commit 4e59fd8

File tree

1 file changed

+74
-14
lines changed

1 file changed

+74
-14
lines changed

src/vs/platform/windows/electron-main/windowImpl.ts

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
3030
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol';
3131
import { resolveMarketplaceHeaders } from 'vs/platform/externalServices/common/marketplace';
3232
import { IApplicationStorageMainService, IStorageMainService } from 'vs/platform/storage/electron-main/storageMainService';
33-
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
33+
import { ITelemetryService, machineIdKey } from 'vs/platform/telemetry/common/telemetry';
3434
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
3535
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
3636
import { getMenuBarVisibility, getTitleBarStyle, IFolderToOpen, INativeWindowConfiguration, IWindowSettings, IWorkspaceToOpen, MenuBarVisibility, useWindowControlsOverlay, WindowMinimumSize, zoomLevelToZoomFactor } from 'vs/platform/window/common/window';
@@ -44,6 +44,12 @@ import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataPro
4444
import { IStateMainService } from 'vs/platform/state/electron-main/state';
4545
import { IUserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile';
4646
import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
47+
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
48+
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
49+
import { getPiiPathsFromEnvironment, isInternalTelemetry, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
50+
import { Promises } from 'vs/base/node/pfs';
51+
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
52+
import { hostname, release } from 'os';
4753

4854
export interface IWindowCreationOptions {
4955
state: IWindowState;
@@ -727,19 +733,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
727733
// we cannot detect AppLocker use currently, but make a
728734
// guess based on the reason and exit code.
729735
if (isWindows && details?.reason === 'launch-failed' && details.exitCode === 18 && await this.nativeHostMainService.isAdmin(undefined)) {
730-
await this.dialogMainService.showMessageBox({
731-
title: this.productService.nameLong,
732-
type: 'error',
733-
buttons: [
734-
mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))
735-
],
736-
message: localize('appGoneAdminMessage', "Running as administrator is not supported"),
737-
detail: localize('appGoneAdminDetail', "Please try again without administrator privileges.", this.productService.nameLong),
738-
noLink: true,
739-
defaultId: 0
740-
}, this._win);
741-
742-
await this.destroyWindow(false, false);
736+
await this.handleWindowsAdminCrash(details);
743737
}
744738

745739
// Any other crash: offer to restart
@@ -775,6 +769,72 @@ export class CodeWindow extends Disposable implements ICodeWindow {
775769
}
776770
}
777771

772+
private async handleWindowsAdminCrash(details: { reason: string; exitCode: number }) {
773+
774+
// Prepare telemetry event (TODO@bpasero remove me eventually)
775+
const appenders: OneDataSystemAppender[] = [];
776+
const isInternal = isInternalTelemetry(this.productService, this.configurationService);
777+
if (supportsTelemetry(this.productService, this.environmentMainService)) {
778+
if (this.productService.aiConfig && this.productService.aiConfig.ariaKey) {
779+
appenders.push(new OneDataSystemAppender(isInternal, 'monacoworkbench', null, this.productService.aiConfig.ariaKey));
780+
}
781+
782+
const { installSourcePath } = this.environmentMainService;
783+
784+
const config: ITelemetryServiceConfig = {
785+
appenders,
786+
sendErrorTelemetry: false,
787+
commonProperties: (async () => {
788+
let machineId: string | undefined = undefined;
789+
try {
790+
const storageContents = await Promises.readFile(this.environmentMainService.stateResource.fsPath);
791+
machineId = JSON.parse(storageContents.toString())[machineIdKey];
792+
} catch (error) {
793+
if (error.code !== 'ENOENT') {
794+
this.logService.error(error);
795+
}
796+
}
797+
798+
return resolveCommonProperties(this.fileService, release(), hostname(), process.arch, this.productService.commit, this.productService.version, machineId, isInternal, installSourcePath);
799+
})(),
800+
piiPaths: getPiiPathsFromEnvironment(this.environmentMainService)
801+
};
802+
803+
const telemetryService = new TelemetryService(config, this.configurationService, this.productService);
804+
805+
type WindowAdminErrorClassification = {
806+
reason: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The reason of the window error to understand the nature of the error better.' };
807+
code: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The exit code of the window process to understand the nature of the error better' };
808+
owner: 'bpasero';
809+
comment: 'Provides insight into reasons the vscode window had an error when running as admin.';
810+
};
811+
type WindowAdminErrorEvent = {
812+
reason: string | undefined;
813+
code: number | undefined;
814+
};
815+
telemetryService.publicLog2<WindowAdminErrorEvent, WindowAdminErrorClassification>('windowadminerror', { reason: details.reason, code: details.exitCode });
816+
}
817+
818+
// Inform user
819+
await this.dialogMainService.showMessageBox({
820+
title: this.productService.nameLong,
821+
type: 'error',
822+
buttons: [
823+
mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))
824+
],
825+
message: localize('appGoneAdminMessage', "Running as administrator is not supported"),
826+
detail: localize('appGoneAdminDetail', "Please try again without administrator privileges.", this.productService.nameLong),
827+
noLink: true,
828+
defaultId: 0
829+
}, this._win);
830+
831+
// Ensure to await flush telemetry
832+
await Promise.all(appenders.map(a => a.flush()));
833+
834+
// Exit
835+
await this.destroyWindow(false, false);
836+
}
837+
778838
private async destroyWindow(reopen: boolean, skipRestoreEditors: boolean): Promise<void> {
779839
const workspace = this._config?.workspace;
780840

0 commit comments

Comments
 (0)