博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vscode源码分析【七】主进程启动消息通信服务
阅读量:4942 次
发布时间:2019-06-11

本文共 5217 字,大约阅读时间需要 17 分钟。

第一篇: 

第二篇:
第三篇:
第四篇:
第五篇:
第六篇:
在mian.ts中的doStartup方法里,创建了一个命名管道服务
(src\vs\code\electron-main\main.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
{ return new Promise
((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(src\vs\code\electron-main\app.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信道;
下面我们看看消息是怎么传递的
我们随便打开一个信道的类型(src\vs\platform\windows\node\windowsIpc.ts)
它有两个主要的函数,listen和call,

listen(_: unknown, event: string): Event
{ 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
{ 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);

具体的代码在:src\vs\platform\windows\electron-browser\windowsService.ts

 

转载于:https://www.cnblogs.com/liulun/p/11050725.html

你可能感兴趣的文章
Java获取新浪微博cookies
查看>>
面试题总结
查看>>
【BZOJ1095】捉迷藏(动态点分治)
查看>>
Table Basics [转载]
查看>>
Logback 学习笔记
查看>>
并查集
查看>>
11、组件注册-使用FactoryBean注册组件
查看>>
nyoj_95_众数问题_map练习
查看>>
For循环
查看>>
020-安装centos6.5后的生命历程
查看>>
面试介绍项目经验(转)
查看>>
创建并设置ASP.NET的会话状态服务器(SQL State Server)
查看>>
<metro>Google的验证
查看>>
SQL中NUMERIC和DECIMAL的区别
查看>>
安卓课程设计:微课表
查看>>
Oracle 表的分组操作
查看>>
在OS X上的Intllij Idea中配置GlassFish
查看>>
用查表法快速转换yv12到RGB【转】
查看>>
使用公钥登录SSL
查看>>
hdu 1290_献给杭电五十周年校庆的礼物
查看>>