New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

access electron API from vscode extension #3011

Closed
drywolf opened this Issue Feb 14, 2016 · 23 comments

Comments

Projects
None yet
8 participants
@drywolf
Copy link

drywolf commented Feb 14, 2016

Hi,

is there currently a way or is it planned for the future that we can access the electron shell API from VS-Code extensions ?

I would like to implement an extension using the BrowserWindow API of electron (more specifically the BrowserWindow.getAllWindows() API), but I can't find any way to get access to that from the scope of an extension.

Thanks

@alexandrudima

This comment has been minimized.

Copy link
Member

alexandrudima commented Feb 15, 2016

@drywolf The extension host is spawned as a regular node process (meaning only node API). It is very unlikely we will spawn it as an electron renderer (to give access to electron API). Perhaps we can enhance our own vscode API to accomodate your use case if you would explain what you want to do.

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Feb 15, 2016

Thanks for the reply.

I would like to integrate some minimal UI to see what are my currently open "projects" among all the VSCode windows. You could think of it as a very minimal and lightweight form of a solution explorer, but where each project in the solution explorer actually just refers to the related VSCode window.

My usecase that I want to address, is to be able to more comfortably keep track and switch between the 3-5+ vscode windows that I often have opened when working on a project that is composed of several modules (each is a separate VSCode project).

E.g. this would be five open VSCode projects in the windows taskbar that I have to navigate between...
image

To integrate such a feature with an extension, at least I would need to have access to...

  • a list of the currently opened VSCode windows in a VSCode instance/process
  • their active title / directory name
  • a way to switch the currently active window / setting the currently active window

For the implementation of my extension I can imagine three different UX solutions that I would like to try out and mix/match to see what works best:

  • add a minimal "solution explorer"-esque listview in the VSCode UI with the names of the currently opened windows, a double click would switch to the selected window (maybe also with the option to close such a window)
  • add a command that would show the list of names of the currently open windows in the quick info box at the top, then the user can select the one he wants to switch to
  • add task-items for the currently active windows to the windows taskbar context-menu popup on right-click, see this screenshots for example...

image

the currently opened windows could maybe be placed below the "New Window" task via the electron desktop integration API, and the user could have a very minimalistic overview over the currently open windows/projects and switch more easily between them.

Thanks

@egamma

This comment has been minimized.

Copy link
Member

egamma commented Feb 15, 2016

@drywolf You could spawn a new process from the extension that launches electron, shows the UI and returns the user selection on stdout that you read from your extensin.

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Feb 15, 2016

That's an interesting approach, thanks for the inspiration.
I will try it out. 😀

Edit: The only concern that I have is that electron will take "too long" to boot, maybe I'll have to keep it running in the tray to circumvent that. But I can figure that out.

Thanks again

@egamma

This comment has been minimized.

Copy link
Member

egamma commented Feb 15, 2016

@drywolf pls let us know how it goes. I would start with the simplest thing that could possibly work, electron tends to start quickly. What will be interesting to see whether the focus/activation behaviour is tolerable.

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Feb 16, 2016

A first POC is working out quite well, I can switch between vscode windows from my electron UI when I start it manually from the command line.

image

But when I try to run electron from within my vscode extension it does not find the electron module for some reason:

    var command = 'node_modules\\.bin\\electron.cmd';
    var cwd = 'C:\\Users\\JohnDoe\\Documents\\code\\code-solution\\electron-service';

    var child = exec(command, { cwd: cwd, });

    child.stdout.on('data', function(data) {
        console.log('stdout: ' + data);
    });
    child.stderr.on('data', function(data) {
        console.log('stderr: ' + data);
    });
    child.on('close', function(code) {
        console.log('closing code: ' + code);
    });

The error:

Error: Cannot find module 'electron'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:289:25)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at Object.<anonymous> (C:\Users\JohnDoe\Documents\code\code-solution\electron-service\main.js:3:18)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Function.Module.runMain (module.js:457:10)

I have not been able to fix it so far, so any help is much appreciated.

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Feb 16, 2016

Now I packaged the eletron app into an exe bundle and I try to run that instead. Now the app seems to be executing but it does have some problem to create the main window, I can't see it anywhere on the desktop.

image

Edit: this might be related to electron/electron#1613

@alexandrudima

This comment has been minimized.

Copy link
Member

alexandrudima commented Feb 16, 2016

@drywolf There is an environmental variable we set to get electron to run as a node process when we spawn it: ELECTRON_RUN_AS_NODE. It might be that when you spawn electron out of vscode, this environmental variable remains set, thus making the spawned electron run in node mode again. You can try to remove that variable from the env (passing in a env clone without it to spawn).

Hope it helps, I'm just guessing...

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Feb 16, 2016

@alexandrudima Thanks for the hint.
In the issue that I linked above this is also the suggested fix.
I tried it out with the proposed ATOM_SHELL_INTERNAL_RUN_AS_NODE=0 fix, which didn't seem to make a difference. I didn't pick up that this was the atom-specific version of the env-variable, so I will try it out with ELECTRON_RUN_AS_NODE=0 later today.

Thanks

@alexandrudima

This comment has been minimized.

Copy link
Member

alexandrudima commented Feb 16, 2016

Yeah, the env variable got renamed in Electron (which still supports the old one):

https://github.com/atom/electron/blob/b42695a0b5e6dec92fe86b8a7f40ec0d0b7c8db7/atom/app/atom_main.cc#L36

@alexandrudima

This comment has been minimized.

Copy link
Member

alexandrudima commented Feb 16, 2016

Sorry I got mixed up as well, looks like the best is to unset both -- not sure setting to 0 is a real unset.
cc @joaomoreno

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Feb 16, 2016

@alexandrudima
I had a look into it. In my env only the ATOM_SHELL_INTERNAL_RUN_AS_NODE was present, but you were right that setting it to '0' was not enough, I had to really unset it...

    // works
    delete sp_env.ATOM_SHELL_INTERNAL_RUN_AS_NODE;
    delete sp_env.ELECTRON_RUN_AS_NODE;

    // does not work
    // sp_env.ATOM_SHELL_INTERNAL_RUN_AS_NODE = "0";
    // sp_env.ELECTRON_RUN_AS_NODE = "0";

So the above code fixed the issue and the electron process spawns just fine now.

To correctly switch to the selected VSCode window and activate it, I used the 'ffi', 'ref' and 'ref-struct' modules to call the necessary WinAPI methods. So I am currently not using any inter-proccess communication (stdout) in my solution, but I just perform the switching to the selected window directly in the opened electron process.

const SW_SHOWMINIMIZED = 2;
const SW_SHOW = 5;
const SW_RESTORE = 9;

var wnd_plc_ptr = ref.alloc(WINDOWPLACEMENT);
user32.GetWindowPlacement(hwnd, wnd_plc_ptr);
var wnd_plc = wnd_plc_ptr.deref();

// when the window is minimized then SW_RESTORE
if (wnd_plc.showCmd == SW_SHOWMINIMIZED)
    user32.ShowWindow(hwnd, SW_RESTORE);
// otherwise SW_SHOW
else
    user32.ShowWindow(hwnd, SW_SHOW);

user32.BringWindowToTop(hwnd);
user32.SetForegroundWindow(hwnd);

@egamma
Right now, I have the first prototype version of the extension that I had in mind working just fine.
The boot time is about half a second, so it could be "okay" for most users I guess (optimizations could be done in the future though).

For the short time that I tested the window interactions, everything seems to be ok so far. Also the keyboard focus seems to be just fine while switching between the windows. Time will tell if there are any other mishaps that are not immediately obvious right now.

Once I have implemented a usable UI experience for the extension I will put it on github / publish it to the extension gallery.

Thanks again for the help & feedback 😀

@egamma egamma removed the needs more info label Feb 17, 2016

@egamma

This comment has been minimized.

Copy link
Member

egamma commented Feb 17, 2016

@drywolf thanks much for exploring this. The feedback sounds promising. I'd be very interested to use the extension once you are happy with it.

@egamma egamma self-assigned this Feb 17, 2016

@egamma

This comment has been minimized.

Copy link
Member

egamma commented Mar 7, 2016

@drywolf just curious - did you make progress on this?

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Mar 7, 2016

I had some busy weeks at work, so I didn't have much of a spirit to develop the prototype any further yet.
Maybe I'll find some hours this week to make a version that would be worth a release. I will let you know when I continue work on this.

@egamma

This comment has been minimized.

Copy link
Member

egamma commented Mar 8, 2016

@drywolf thanks for the update, please no stress, I was just curious.

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Mar 12, 2016

@egamma

I put some work into it and made a first experimental alpha release, which can be found on github...
https://github.com/drywolf/code-solution-manager/releases/tag/0.0.1

code-solution-manager

The interaction between the vscode's electron window and the extension's electron window works well.
I tried several methods of using the Win32 API (via ffi) to actually switch to the vscode window by the users' selection.
I ended up using kernel32.AttachThreadInput & user32.SetActiveWindow, which don't seem to work correctly when running the extension during debugging, but once the extension is installed natively in vscode everything works well. The window & keyboard focuses are working fine.

There are a few points though that are still making it rough to develop this further into a more meaningful, stable extension:

  • currently the extension has to heavily rely on the formatting of the vscode window title, since there is no way to get information about all opened windows in the vscode extension code (which led me to create this issue in the first place)
  • also I haven't tried if there would be a good way to share information back from the extension-ui electron process to the vscode extension process. Maybe some kind of ipc / http channel could work, but might also degrade the startup time of the UI further.
  • in the released version I made it so that the extension ui process will simply start and close each time that it needs to show the UI. I tried out some of electron's support for leaving the process running in the background and just showing/hiding the window. This improved the startup time of the UI a meaningful bit, but also introduced problems since the process could keep running also after vscode was already closed.
  • the current vsix package of the extension weighs in at around ~70+mb since it has to include the electron binaries for the UI parts (this also seems to hit some kind of limit for the Visual Studio Marketplace, since I got a 404 error when trying to publish it via vsce)
  • for the mentioned points that I used the Win32 API and had to bundle a prebuilt Win32 version of electron, the extension will only work on windows. To get it to work on OSX/Linux I would have to also implement two code paths for the window switching for those platforms and probably release platform dependent versions of the vsix packages for each platform that include the required electron binaries.
@egamma

This comment has been minimized.

Copy link
Member

egamma commented Mar 14, 2016

Thanks for the update, the animated GIF looks nice and the appearance looks snappy.

I haven't tried if there would be a good way to share information back from the extension-ui electron process to the vscode extension process. Maybe some kind of ipc / http channel could work, but might also degrade the startup time of the UI further.

You could use stdin/stdout and a JSON payload. This how the extension process takes to language server processes for typescript.

introduced problems since the process could keep running also after vscode was already closed.

When Code shuts down the the deactivate method of your extension is called and you should be able to clean up.

the current vsix package of the extension weighs in at around ~70+mb

This is a lot, I'm not aware of this limit. One option would be to fetch the code from nuget on first activate. However, this is getting complicated for your scenario so we should look into exposing BrowserWindow.getAllWindows() API.

An another challenge is how to align the themes between Code and your UI process.

@drywolf

This comment has been minimized.

Copy link
Author

drywolf commented Mar 14, 2016

When Code shuts down the the deactivate method of your extension is called and you should be able to clean up.

This is what I already tried, but the spawned electron process keeps running, even when vscode is already closed.
When I debug the extension in vscode, the deactivate() function is not called when the extension host is closed. I tried commenting out the code that spawn the process, and even then deactivate() is not being called most of the time.

I also tried adding a disposable object to context.subscriptions, but the dispose() function there is not called either. What could cause such a problem ? Am I debugging the extension in a wrong way ?

Might be related to #1298 ?

@mbana

This comment has been minimized.

Copy link

mbana commented Nov 16, 2016

@alexandrudima, hi,

let ws = new WebSocket(...);

Will fail with ReferenceError: WebSocket is not defined (because node doesn't support WebSocket, IRC, at the moment).

What's nice about allowing access to the Electron api, say, is being able to view the network traffic in the developer tools. The Node modules that provide WS support won't have special treatment so some extra work is required to debug these sorts of connections.

@ricky-hartmann-zocdoc

This comment has been minimized.

Copy link

ricky-hartmann-zocdoc commented Mar 21, 2017

Has this gone anywhere since? This would be an awesome feature to bring into VSCode

@bpasero bpasero added the api label Nov 17, 2017

@ayqy

This comment has been minimized.

Copy link

ayqy commented Feb 1, 2018

@drywolf @egamma Awesome work and idea, just like the magic portal in room escape.👍

spawn a new process from the extension that launches electron, shows the UI and returns the user selection on stdout that you read from your extensin.

Eventually, we escaped from ELECTRON_RUN_AS_NODEed extension host environment, and opened a new isolated window, then set up a communication channel to compose them. Seems not so bad...But, why not open a door to the world as you see ?

Is there any way to build a floating window, or something like sticky tool bar ?

@vscodebot

This comment has been minimized.

Copy link

vscodebot bot commented Sep 20, 2018

This iteration we focus on issue grooming. This issue is being closed to keep the number of issues in our inbox on a manageable level, we are closing issues that are not going to be addressed in the foreseeable future: We look at the number of votes the issue has received and the number of duplicate issues filed. More details here. If you disagree and feel that this issue is crucial: We are happy to listen and to reconsider.

If you wonder what we are up to, please see our roadmap and issue reporting guidelines.

Thanks for your understanding and happy coding!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment