zoukankan      html  css  js  c++  java
  • vscode源码分析【七】主进程启动消息通信服务

    第一篇: vscode源码分析【一】从源码运行vscode
    第二篇:vscode源码分析【二】程序的启动逻辑,第一个窗口是如何创建的
    第三篇:vscode源码分析【三】程序的启动逻辑,性能问题的追踪
    第四篇:vscode源码分析【四】程序启动的逻辑,最初创建的服务
    第五篇:vscode源码分析【五】事件分发机制
    第六篇:vscode源码分析【六】服务实例化和单例的实现
    在mian.ts中的doStartup方法里,创建了一个命名管道服务
    (srcvscodeelectron-mainmain.ts)

    server = await serve(environmentService.mainIPCHandle);
    once(lifecycleService.onWillShutdown)(() => server.dispose());

    传入的environmentService.mainIPCHandle是命名管道的识别路径,
    一个有规则的字符串,规则如下:

    function getWin32IPCHandle(userDataPath: string, type: string): string {
    	const scope = crypto.createHash('md5').update(userDataPath).digest('hex');
    	return `\\.\pipe\${scope}-${pkg.version}-${type}-sock`;
    }

    注意:每次启动程序,取这个字符串的时候,都会获得同样的值(而且这个值是会被缓存起来的);
    以后监听消息、发送消息,都根据这个字符串来;
    创建服务的代码(serve):

    export function serve(hook: any): Promise<Server> {
    	return new Promise<Server>((c, e) => {
    		const server = createServer();
    		server.on('error', e);
    		server.listen(hook, () => {
    			server.removeListener('error', e);
    			c(new Server(server));
    		});
    	});
    }

    这个方法返回了一个Promise的对象,
    c和e是Promise的参数,c代表成功时的回调,e代表失败时的回调(有点类似es6的Promise)
    匿名函数内createServer就是nodejs里的原生接口,
    Server类绑定了连接和断开的事件,暂时不细说;

    回头看看main.ts   startup方法里有这么一句:

    instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnvironment).startup();

    这句显然是创建了CodeApplication的实例,然后执行了实例的startup方法
    注意:创建这个实例的时候,把我们前面创建的mainIpcServer传递进去了;
    CodeApplication(srcvscodeelectron-mainapp.ts)的startup方法,还启动了Electron的IPCServer

    const electronIpcServer = new ElectronIPCServer();

    vscode把electron默认的通信机制也接入到了自己的事件体系内,有消息过来,会触发事件;
    具体先不细说,后面再讲.
    接着就跳转到同类型里的openFirstWindow方法(是不是很熟悉,我们在第一篇文章中讲到过这里)
    在这里,给这两个服务(mainIpcServer和electronIpcServer ),创建了一堆信道:

    const launchService = accessor.get(ILaunchService);
    		const launchChannel = new LaunchChannel(launchService);
    		this.mainIpcServer.registerChannel('launch', launchChannel);
    
    		const updateService = accessor.get(IUpdateService);
    		const updateChannel = new UpdateChannel(updateService);
    		electronIpcServer.registerChannel('update', updateChannel);
    
    		const issueService = accessor.get(IIssueService);
    		const issueChannel = new IssueChannel(issueService);
    		electronIpcServer.registerChannel('issue', issueChannel);
    
    		const workspacesService = accessor.get(IWorkspacesMainService);
    		const workspacesChannel = new WorkspacesChannel(workspacesService);
    		electronIpcServer.registerChannel('workspaces', workspacesChannel);
    
    		const windowsService = accessor.get(IWindowsService);
    		const windowsChannel = new WindowsChannel(windowsService);
    		electronIpcServer.registerChannel('windows', windowsChannel);
    		sharedProcessClient.then(client => client.registerChannel('windows', windowsChannel));
    
    		const menubarService = accessor.get(IMenubarService);
    		const menubarChannel = new MenubarChannel(menubarService);
    		electronIpcServer.registerChannel('menubar', menubarChannel);
    
    		const urlService = accessor.get(IURLService);
    		const urlChannel = new URLServiceChannel(urlService);
    		electronIpcServer.registerChannel('url', urlChannel);
    
    		const storageMainService = accessor.get(IStorageMainService);
    		const storageChannel = this._register(new GlobalStorageDatabaseChannel(this.logService, storageMainService as StorageMainService));
    		electronIpcServer.registerChannel('storage', storageChannel);
    
    
    		const logLevelChannel = new LogLevelSetterChannel(accessor.get(ILogService));
    		electronIpcServer.registerChannel('loglevel', logLevelChannel);

    有存储、日志、菜单栏、工作台、升级.....等等
    主要的通信还是用electronIpcServer 来干的,mainIpcServer只有一个launch信道;
    下面我们看看消息是怎么传递的
    我们随便打开一个信道的类型(srcvsplatformwindows odewindowsIpc.ts)
    它有两个主要的函数,listen和call,

    	listen(_: unknown, event: string): Event<any> {
    		switch (event) {
    			case 'onWindowOpen': return this.onWindowOpen;
    			case 'onWindowFocus': return this.onWindowFocus;
    			case 'onWindowBlur': return this.onWindowBlur;
    			case 'onWindowMaximize': return this.onWindowMaximize;
    			case 'onWindowUnmaximize': return this.onWindowUnmaximize;
    			case 'onRecentlyOpenedChange': return this.onRecentlyOpenedChange;
    		}
    		throw new Error(`Event not found: ${event}`);
    	}
    	call(_: unknown, command: string, arg?: any): Promise<any> {
    		switch (command) {
    			case 'pickFileFolderAndOpen': return this.service.pickFileFolderAndOpen(arg);
    			case 'pickFileAndOpen': return this.service.pickFileAndOpen(arg);
    			case 'pickFolderAndOpen': return this.service.pickFolderAndOpen(arg);
    			case 'pickWorkspaceAndOpen': return this.service.pickWorkspaceAndOpen(arg);
    			case 'showMessageBox': return this.service.showMessageBox(arg[0], arg[1]);
    			case 'showSaveDialog': return this.service.showSaveDialog(arg[0], arg[1]);
    			case 'showOpenDialog': return this.service.showOpenDialog(arg[0], arg[1]);
    //......

    消息来了,进入listen函数,发送消息,进入call函数;
    注意,消息来了,触发的也不是他自己的方法,我们看看它的构造函数:

    	constructor(private service: IWindowsService) {
    		this.onWindowOpen = Event.buffer(service.onWindowOpen, true);
    		this.onWindowFocus = Event.buffer(service.onWindowFocus, true);
    		this.onWindowBlur = Event.buffer(service.onWindowBlur, true);
    		this.onWindowMaximize = Event.buffer(service.onWindowMaximize, true);
    		this.onWindowUnmaximize = Event.buffer(service.onWindowUnmaximize, true);
    		this.onRecentlyOpenedChange = Event.buffer(service.onRecentlyOpenedChange, true);
    	}

    看到没,触发的其实是一个事件,事件是关联到service实例的;
    这个实例是这样创建的:

    const windowsService = accessor.get(IWindowsService);

    具体的代码在:srcvsplatformwindowselectron-browserwindowsService.ts


     

  • 相关阅读:
    makefile中宏定义
    make的静态模式
    makefile中两重if判断
    定义命令包
    嵌套执行make
    AcWing 1014. 登山
    AcWing 482. 合唱队形
    AcWing 1027. 方格取数
    AcWing 1016. 最大上升子序列和
    AcWing 187. 导弹防御系统
  • 原文地址:https://www.cnblogs.com/liulun/p/11050725.html
Copyright © 2011-2022 走看看