@@ -30,7 +30,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
30
30
import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol' ;
31
31
import { resolveMarketplaceHeaders } from 'vs/platform/externalServices/common/marketplace' ;
32
32
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' ;
34
34
import { ThemeIcon } from 'vs/platform/theme/common/themeService' ;
35
35
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService' ;
36
36
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
44
44
import { IStateMainService } from 'vs/platform/state/electron-main/state' ;
45
45
import { IUserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile' ;
46
46
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' ;
47
53
48
54
export interface IWindowCreationOptions {
49
55
state : IWindowState ;
@@ -727,19 +733,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
727
733
// we cannot detect AppLocker use currently, but make a
728
734
// guess based on the reason and exit code.
729
735
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 ) ;
743
737
}
744
738
745
739
// Any other crash: offer to restart
@@ -775,6 +769,72 @@ export class CodeWindow extends Disposable implements ICodeWindow {
775
769
}
776
770
}
777
771
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
+
778
838
private async destroyWindow ( reopen : boolean , skipRestoreEditors : boolean ) : Promise < void > {
779
839
const workspace = this . _config ?. workspace ;
780
840
0 commit comments