Skip to content
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

Calling .NET Core-compiled custom executables via symlinks on Windows should be supported #2923

Closed
livarcocc opened this issue Oct 2, 2017 · 11 comments
Labels
area-Host enhancement Product code improvement that does NOT require public API changes/additions
Milestone

Comments

@livarcocc
Copy link
Contributor

From @mklement0 on September 30, 2017 21:27

Trying to call a .NET Core 2.0 *.exe file via a symbolic link doesn't work as-is, resulting in the following error message:

The managed DLL bound to this executable: '<original-name>.dll', did not match own 
name '<symlink-name>.dll'.
A fatal error was encountered. This executable was not bound to load a managed DLL.

The idea is to use a symlink to provide an efficient, shell-agnostic way to invoke an executable by a shorter name (without having to resort to shell-specific aliases or cumbersome wrapper batch files) - just like on Unix platforms, where this scenario is already supported.

This came up while discussing a shell-agnostic way to invoke PowerShell Core with a shorter name.


Steps to reproduce

Run the following from an elevated PowerShell prompt on (64-bit) Windows:

Create a hello-world project with executable foo.exe in %TEMP%\foo:

PS> Set-Location (mkdir $env:Temp/foo)
PS> dotnet new console
PS> dotnet publish -c Release -r win-x64

Invoke the resulting executable, which works fine:

PS> .\bin\Release\netcoreapp2.0\win-x64\foo.exe
Hello World!

Now create a symlink named fooL.exe that points to the executable and try to invoke it:

PS> cmd /c mklink fooL.exe .\bin\Release\netcoreapp2.0\win-x64\foo.exe
PS> .\fooL.exe  # !! Fails as of .NET Core 2.0

This results in the error message cited at the top.

Note that creating the symlink without extension (fooL instead of fooL.exe) half works:

  • From cmd.exe, you can't call this symlink as an executable at all.
  • PowerShell does allow invocation and even succeeds in calling the target executable with the arguments specified, but invariably runs it in a new console window.

Use Set-Location ~; Remove-Item -Recurse $env:TEMP/foo to remove the temp. directory afterwards.

Copied from original issue: dotnet/cli#7739

@mklement0
Copy link

@livarcocc Thanks for moving the issue, but it isn't really related to .NET Core's own installation / executables - it is about calling custom executables compiled with .NET Core via symlinks (I didn't do a a great job of making that clear).

@mklement0
Copy link

mklement0 commented Oct 8, 2017

@livarcocc:

Based on my later clarification, could you please either explain why this repo is, after all, the right place for this issue or move it back to the cli repo or whichever one is more appropriate?

I'd be happy to update the original post with my clarification, but since the post is now owned by you, I cannot do so.

A quick improvement would be to change the title to:

Calling .NET Core-compiled custom executables via symlinks on Windows should be supported

@Petermarcu Petermarcu changed the title Calling .NET Core executables via symlinks on Windows should be supported Calling .NET Core-compiled custom executables via symlinks on Windows should be supported Oct 9, 2017
@Petermarcu
Copy link
Member

Updated the title. This is probably the right place for the issue. This repo is where the "host" code lives which is what hosts the runtime and launches the application. The application exe is the host and so is dotnet.exe. Once the application is compiled, the CLI is out of the picture.

@mklement0
Copy link

Thank you for updating the title and clarifying, @Petermarcu, I appreciate it.

@steveharter
Copy link
Member

We need to document and discuss the original reason(s) for not allowing the exe to be renamed.

@steveharter
Copy link
Member

The corresponding .dll name is embedded into the exe which currently must match the .exe name

If we remove that check, the code would probably work. I believe it is just a sanity check to make sure the tooling did the right thing. I don't think there is a security or TwC hijacking-type issue either as anyone can rename a given .exe.

However, is making the change worth the cost and potential risk if the main goal of this is to support easier tooling infrastructure which can be worked around?

@mklement0
Copy link

mklement0 commented Jan 13, 2018

if the main goal of this is to support easier tooling infrastructure

I don't see this limited to tooling; to reiterate what I said in the original post:

It should be possible use a symlink as an efficient, shell-agnostic way to invoke an executable by a shorter - or different - name.

On Unix platforms, this is already common practice and some utilities even use the specific name of the symlink / executable they were invoked with to adjust their behavior.

Even in the Windows world this would be handy, now that symlinks are becoming more prevalent there.

@steveharter
Copy link
Member

I believe this will be addressed with https://github.com/dotnet/core-setup/issues/3720 because there is an implementation detail that removes the exe:dll name check

@steveharter
Copy link
Member

This is not going to be addressed by dotnet/core-setup#3720 because although the exe:dll name check is removed, there are other conventions including that a self-contained app have all files next to it, contain a runtimeconfig.json, etc.

When using a soft or hard link, it appears Windows treats the link as the actual executable, so when we ask for the currently running executable, Windows returns the symbolic link file, not the target file. Thus the conventions (must have files next to it, etc) fail.

@steveharter
Copy link
Member

I'm going to close this since I don't see how a symbolic link would ever work, unless there is a way for a symbol link to truly behave like the destination executable. Please re-open if necessary.

dotnet/core-setup#3720 will provide a way to have a renamed exe (apphost) plus point to another location that contains the application files. However it does require a local startupconfig.json file to tell it where the app files are located. So the exe and a simple json file are similar in functionality to the symbolic link original requirements and this new functionality will be leveraged by global tools.

@mklement0
Copy link

Thanks for the heads-up, @steveharter.

If I understand you correctly, you're saying that argv[0] reports the symlink's path.

If so, wouldn't a call to GetFinalPathNameByHandle resolve this issue?

Perhaps as a fallback mechanism so that the cost doesn't have to be incurred every time?

@msftgits msftgits transferred this issue from dotnet/core-setup Jan 30, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 30, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Host enhancement Product code improvement that does NOT require public API changes/additions
Projects
None yet
Development

No branches or pull requests

5 participants