Scoop icon indicating copy to clipboard operation
Scoop copied to clipboard

Support shims to both console and GUI apps

Open prasannavl opened this issue 7 years ago • 68 comments

When using any tools, like sysinternals for example, an empty command window (the shim) is open, and has to be manually closed.

The ideal way would be that the shim itself be a "win32" app. Currently all shims are console programs. i.e, not linked as "win32" apps for gui mode.

EDIT: Suggestion, allow for properties in the manifest to configure which binaries are gui shims, and which should be commandline shims, and use shims accordingly.

prasannavl avatar Jul 18 '17 09:07 prasannavl

would it be possible to add a flag in the json (then in the .shim) indicating that shim.exe should not wait indefinitely? Something like

bool fork = bool.Parse(Get("fork", config) ?? "false");
if(fork) {
    return 0;
}
else {
    WaitForSingleObject(pi.hProcess, INFINITE);

    uint exit_code = 0;
    GetExitCodeProcess(pi.hProcess, out exit_code);

    // Close process and thread handles.
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return (int)exit_code;
}

I'm not sure how one might specify this in the app.json, and currently it looks like function shim within core.ps1 would need to accept another argument. It might make sense (for future concerns) to allow $arg to be a dict of key/vals that can be dumped to the .shim file for loading. Not to get ahead of this current problem.

SimplyKnownAsG avatar Mar 01 '18 18:03 SimplyKnownAsG

@r15ch13 is there a way you think this should be accomplished? i'd be happy to close #2006 if there were another way around it. I suppose we could also change GUIs to just add the path rather than creating a shim. is there a preference of adding to path vs creating a shim?

SimplyKnownAsG avatar Mar 13 '18 23:03 SimplyKnownAsG

A symbolic link would suffice. BTW, why do we need a shim.exe?

Congee avatar May 25 '18 15:05 Congee

A symbolic link doesn't work, as the exe that is the symlink's target cannot find its related .dlls, as the "exe's directory" is the directory the symlink is in, not where the target lives.

rasa avatar May 25 '18 16:05 rasa

Windows isn't very friendly about symbolic links, but hard links are more accessible for those who do not have admin rights. However, I think that @rasa is correct about .dlls.

@Congee, I'm not sure I understand the question:

why do we need a shim.exe?

I think the intent of scoop/shims/*.exe is used to help prevent pollution of the PATH. shim.exe is a fancy/funky symlink

SimplyKnownAsG avatar May 25 '18 17:05 SimplyKnownAsG

why do we need a shim.exe?

I think the intent of scoop/shims/*.exe is used to help prevent pollution of the PATH. shim.exe is a fancy/funky symlink

Additionally, if you create file assocations or any other reference for an application that is installed via scoop, they would not work anymore if the application gets updated (since the folder name would change within apps/).

Btw. it appears that icons from the "shim"ed (?) executable also do not work: https://stackoverflow.com/questions/53430845/scoop-installed-git-bash-open-git-bash-here-context-menu

fritzmg avatar Nov 22 '18 16:11 fritzmg

@fritzmg the actual shim.exe doesn't have an icon, so it can't be displayed. In this case, it's recommended to use the current version path. (e.g. ~\scoop\apps\git\current\git-bash.exe)

r15ch13 avatar Nov 22 '18 18:11 r15ch13

Ah yes, thank you, just noticed your answer on stackoverflow too :)

fritzmg avatar Nov 23 '18 08:11 fritzmg

would it be possible to add a flag in the json (then in the .shim) indicating that shim.exe should not wait indefinitely? Something like

bool fork = bool.Parse(Get("fork", config) ?? "false");
if(fork) {
    return 0;
}
else {
    WaitForSingleObject(pi.hProcess, INFINITE);

    uint exit_code = 0;
    GetExitCodeProcess(pi.hProcess, out exit_code);

    // Close process and thread handles.
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return (int)exit_code;
}

I'm not sure how one might specify this in the app.json, and currently it looks like function shim within core.ps1 would need to accept another argument. It might make sense (for future concerns) to allow $arg to be a dict of key/vals that can be dumped to the .shim file for loading. Not to get ahead of this current problem.

Totally agree. Even more, it is easy to check if the application is console or not even without a flag.

excitoon avatar Dec 20 '18 12:12 excitoon

@excitoon how would this console/GUI check look like? Is that possible?

r15ch13 avatar Dec 20 '18 17:12 r15ch13

@r15ch13 I just made a PR for that.

excitoon avatar Dec 20 '18 20:12 excitoon

As for second part, icon for shim, there are two ways doing it:

  1. make shell handler which would set proper icon for a file (quite system-intrusive);
  2. simply copy icon from executable into shim (PE format is well described and static).

excitoon avatar Dec 24 '18 09:12 excitoon

Can it add a parameter? ex scoop install aaa --gui, then it create shims as a gui app.

fcying avatar Feb 04 '19 05:02 fcying

Hi Chocolatey is also using the same shim technique to (I believe) avoid polluting the path and it doesn't have this issue. Here is their github repo: https://github.com/chocolatey/shimgen

yelkarama avatar Apr 06 '19 19:04 yelkarama

@yelkarama shimgen of chocolatey is a closed source proprietary software, though they say it's an open source feature in their docs title, kinda funny.

https://github.com/chocolatey/choco/blob/master/src/chocolatey.resources/tools/shimgen.license.txt

You know that Scoop is a personal project of luke, while Chocolatey is a commercial software, though it has community version. The distribution or use of shimgen outside of Chocolatey without permission is prohibited. The shimming system is a critical piece of Scoop/Chocolatey, obviously. Scoop community developers will always be interested in improve the project, but as you know it's still a community maintained project, thus it can take more time. :)

chawyehsu avatar Apr 26 '19 10:04 chawyehsu

@yelkarama Link you posted is only a readme and issue list.

excitoon avatar Apr 26 '19 10:04 excitoon

I want to use shimgen outside of Chocolatey.

If your project is FOSS, please contact us for a grant of a free license to do so. > If your project is commercial, please contact Chocolatey Software for a quote.

shimgen is closed source proprietary software, while generated shim is under MS-RSL...

niheaven avatar Apr 26 '19 13:04 niheaven

This issue should be fixed in #3998, which was merged into master. To use, type:

scoop config shim kiennq
scoop reset *

or

scoop config shim 71
scoop reset *

Eventually, one of those shims (probably kiennq) will be made the default.

If this issue is still a problem after trying both solutions above, please reopen this issue. Thanks!

rasa avatar Dec 23 '20 15:12 rasa

I guess this still is an issue for example if you install and run https://wezfurlong.org/wezterm/install/windows.html

hinogi avatar Apr 02 '21 18:04 hinogi

seems to be still an 'issue' as of July, e.g., with notepad++ when using win+r ('run')

I guess this still is an issue for example if you install and run https://wezfurlong.org/wezterm/install/windows.html

street-grease-coder avatar Jul 14 '21 12:07 street-grease-coder

Why do I get this error when running both of these commands?

scoop config shim kiennq
scoop reset *
scoop config shim 71
scoop reset *

image

syncrodazt avatar Aug 04 '21 00:08 syncrodazt

@syncrodazt try doing scoop update -f 7zip

And speaking of the feature itself. I very much like it. I am a new scoop user and it bothered me when i went windows key -> type 'git bash' -> have cmd and git bash open up.

It's been like this with most apps ran through windows quick access. With the shim config it's solid now.

Yazir avatar Aug 04 '21 21:08 Yazir

I'm seeing this issue again since a recent update on sumatrapdf

FelixZhang avatar Jun 20 '22 03:06 FelixZhang

Multiple of the apps I have installed still show the blank cmd windows when I run the shim executables. Ones that are console anyway will use that console window, but ones that are GUI, this console window does nothing, and closing it closes the app.

Notably, git-gui and Blender (I think Blender runs DeallocConsole though to get rid of it, because opening a console first is Blender's default behaviour) work fine, while some examples like notepad2 do not. Also, the ones that create entries in the start menu through the "scoop apps" folder are also fine, but those don't use the shim exeuctable anyway. Those GUI apps that don't make such an entry, those will be the ones directly found by the executable in start menu search and those still suffer for me.

sinni800 avatar Jun 20 '22 04:06 sinni800

Which shim executable are you using? Can you run this and try again?

scoop config shim kiennq 
scoop update
scoop reset *

rashil2000 avatar Jun 20 '22 08:06 rashil2000

It seems I forgot to write after all that I did try both kiennq and 71. I even deleted the entire shim folder and let the reset reinitialize it (leaving the shim for scoop itself intact). I also verified that with those shims, there wasn't a cmd and ps1 for every executable anymore, it was all exe and ".shim" files that contain the path to the executable in the case of kiennq.

So i think I did my due diligence, did I miss anything?

sinni800 avatar Jun 20 '22 11:06 sinni800

Ah okay I think I understand the issue now. The shim executable is a console program, so it will always open a console regardless of whether the target executable is a console program or a GUI program. Note that this is a peculiarity of Windows itself, all programs need to declare what subsystem they belong to (either CONSOLE or WINDOWS) before compilation and there's no way to work around this.

Programs which have a GUI should create shortcuts for themselves in the manifest. Using the shim for them is not recommended, the shim is only supposed to be used from the shell/terminal.

rashil2000 avatar Jun 20 '22 13:06 rashil2000

Well, there are solutions I can personally think of.

I know for console apps you can't just not wait for execution to end (or else the console will dealloc), and for it to stay in the same console session, you have to execute the app in your own console session... I get that this is why scoop does it this way.

I can see a few solutions to this.

First, actually read the PE info of the executable and ShellExecuteEx it if it's a gui app (then don't wait and the shim will pop up a console but at least disappear).

Other solutions I havd would need the manifest to include information about the nature of the app though...

Here, I can see generating different shims whether or not the app is a gui app - something like Blender would say it's a console app (because it does always start up with a console first), for example. A gui shim is a gui executable, while a console shim is as now. Make the default console and you only have to update the gui apps (least destructive way).

Second, use the ".shim" file to determine this state, then the shim, when reading that, decides to DeallocConsole at runtime or, here, again, ShellExecuteEx the executable instead.

Since we're on Windows, unlike on Linux, the parent process can die without taking its children with it.

sinni800 avatar Jun 20 '22 14:06 sinni800

I mean I understand there are workarounds for it (which will require a lot of hard work and special casing, for e.g. not all target executables are .exe files etc.), but I still don't understand the point of this effort. GUI apps have shortcuts already (which directly target the app executable), why would you want to launch them using a shim, and that too directly from Start Menu (where the said shortcuts exist)? Shims are a CLI tool by definition: they should be used only from the CLI.

rashil2000 avatar Jun 20 '22 19:06 rashil2000

Well, the use case is that some (gui) applications are very good to run from a console or the "RUN" field, like notepad++ or notepad2. The console blocking on that is actually kind of annoying here.

Of course, assigning the filetype to that app also works, but you can only have one app assigned to a file type.

I get some apps actually use bat/cmd and not exe. In that case, the special case is just this: If exe, do PE introspection, if not, do nothing at all and behave like before.

As for the analysis though, I have done some Google-Fu, and there is a class for PE Headers in... dotnet v6. Since scoop needs to run on the basic windows included Powershell, that's out. There is a c# library that should fit in the requires versions, but yeah, it's a lot more work than I thought to do the analysis here. https://github.com/secana/PeNet

With the dotnet v6 class it would be a handful of lines to find the subsystem type in the PE header.

sinni800 avatar Jun 20 '22 20:06 sinni800