Resolve `dotnet` executable path programmatically
Trying to get NuGet packages loading correctly under a hosted env. -- so I need to grab the NuGet package dir. But doing so programmatically itself seems to require a NuGet package so I'm trying to just grab the output from
dotnet nuget locals global-packages --list
instead.
However I want to try and support a situation where the executing dotnet
may not be the one on the PATH
, or no dotnet
is present on the PATH
at all -- so I'd like to grab the dotnet
executable which is running the current program. I couldn't find a reliable way to do this without some janky solution like getting the process argv
with native APIs so I thought I'd ask here.
Thanks in advance!57 Replies
I cant use the NuGet package for NuGet in my process for loading NuGet packages ;p
unless I embedded that package in my hosting lib which seems suboptimal
no it's
a native program loading and running .NET
so I've got a
ResolveAssembly
function which I'm adding to the ALC Resolving
within which I need to handle loading user DLLs, and therefore also their dependencies
yeah there's no dotnet
running the program
but there is an associated runtime somewhere on the system
I could get the hostfxr library path and work backwards or smth but that would also
be a bit jank
on Linux we defer to ld.so
's mechanisms for loading the hostfxr library since
the user could be doing something wacky
then have a few default paths as fallback
From what I can tell MS just recommends something like this for Windows:
which also doesn't allow for multi-installs or getting an alternate path but
at that point you'd just be asking the user for a path
from what I can tell on non-Windows systems the vendor is allowed tell dotnet
to go in a load of different prefixes
it's certainly not the end of the world to just say "please use a sane environment with a standard install" but as a hosting library that isn't neccesarily a reasonable request
before leaving Mono for .NET Core we had a mini Mono root being shipped in an engine f.e.
all good -- thanks for pitching in anyway!Isn't this what nethost is for, or?
wdym?
The nethost library. It's job is to locate hostfxr.
Unless I'm mistaken, the idea is you use either include the nethost bin, or statically compile it, and that is responsible for locating hostfxr.
haven't looked into it but that infra was written before I inherited the lib -- I'll take a gander but irrespective that doesn't really help me with the NuGet paths unless I'm misunderstanding you
Well the NuGet libraries are .NET assemblies.....
I think you're going to need to describe the entire problem a lot clearer.
okay gimme a sec and I'll reword it
I'm working in a .NET hosting env, I'm trying to get loading assemblies which use NuGet packages to work
so I need to get the NuGet package path of the relevant SDK that I'm using
but that SDK may not necessarily be in a standard location
and obviously I can't use the normal programmatic ways to get the paths because they are themselves NuGet packages
Why would there be an SDK at all?
so I need to grab the relevant
dotnet
executable, to get the NuGet package cache
well SDK/runtime they run out of the same relative root no?The part that doesn't make sense to me is that at runtime, an SDK isnt even required to be installed.
The .NET runtime itself doesn't make use of Nuget at all.
So these nuget packages you're trying to locate, I guess I don't understand why?
like if I just
dotnet build
a .NET project which happens to use NuGet packages -- those packages don't live alongside the project's built artefactsRight. That's what dotnet publish is for.
sure -- but packaging is the responsibility of the application which is using this hosting lib since
It builds a publishable (redistributable) set. Which includes any relevant dependencies.
it could have a whole plethora of other run req.s
and also to my understanding you don't want to be publishing for every single build?
So, let me try to see if I understand. YOu are getting DLLs from some unknown source, and need to 'include their dependencies'. And want to use NuGet at runtime to do that?
at least that's what MSDN made me believe
You don't need to publish if you are just running it out of your dev environment.
well yeah but that doesn't currently work
not neccesarily use NuGet at runtime -- but if the normal resolution fails
What normal resolution?
then try and resolve out of the NuGet runtime paths
The only 'normal resolution' is that specified by deps.json or the ALC by hand.
like -- the default relative-to-module DLL loading infra
Yeah. That's why .deps.json exists.
yeah, it just doesn't automatically resolve dev packages under the hosting env. for whatever reason
So, okay. This is the issue. You should not be even trying to load individual assemblies form third party sources like that. They need to come with their deps.
Barring that, you'd have to reconstruct all that: and you don't and cannot have enough information to truly do that.
wdym "come with their deps"?
like from running
publish
?Say I build a plugin for an app. When distributing the plugin, I would include a .deps.json, and all of the required assemblies.
Yup.
yeah there is a deps.json
which references the relevant package
deps.json doesn't reference packages, actually.
That's sort of a holdover from .NET Core 1, when packages.json was a thing.
?
Yeah but those need not be actual package IDs. ProjectReferences appear there as a key as well.
yeah there's this and a project ref
but it fails to automatically resolve the package
Yup Because nuget is out of hte picture at this point.
hence why I'm trying to "work backwards" as it were
The .deps.json describes the relative file path to use.
but then how can
dotnet
resolve from the NuGet package with assumedly the same amount of info when running in a dev env?
or does it source that from the slnIt doesn't.
Again, the dotnet runtime does not use nuget at all.
The BUILD does.
I think I'm misunderstanding you here -- running a build doesn't appear to copy any dependencies into the bindir
For an EXE it does.
ah well
uh
And there's a property to turn that on for assemblies.
ah I see -- which property would that be?
One sec. Checking.
CopyLocalLockFileAssemblies
MSBuild properties for Microsoft.NET.Sdk - .NET
Reference for the MSBuild properties and items that are understood by the .NET SDK.
So the general assumption is that you aren't going to be directly 'running' a DLL output type project. So it speeds up the build by not doing this work (though it is done during publish anyways).
(publish on a DLL output type is still how you should do it, imo)
In fact it says all that on that page.
I mean if
publish
on every build doesn't have detrimental effects then I can tell users to do that it's just
it seemed like that was discouragedOn every release, not on every build.
Distinction.
but during development you still need the dependency
If you're going to be distributing the DLL outside of the build diretory, etc.
like even if you never make a release you still need the dependencies to
run the DLL
Well, you don't run DLLs, so you're talking about some separate app doing the running, right?
Even at dev time.
yeah -- the hosting lib is "running" the DLLs
or IG "using" would be more accurate
Yeah. So. You can either turn on copylocklocal, and point the hosting DLL at the bin dir, or add custom MSBuild targets to do the publish. Or come up with some other dev loops.
think like a Unity project f.e. -- it builds to DLL then that gets "run" by the Unity runtime
ah darn
premake doesn't support that property by the looks of things -- time to bother dragonslayer 😅
anyway thank you very much for explaining!
No problem.
I went looking btw, and I'm a little doubtful whether any of this can be considered GPLv3 safe the way you want it to be. Hehe.
the primary audience for Coral seems to be game engine devs anyway so I think I can live with that ;p
Hazel itself already has some wonky licencing we'd need to iron out for a proper release :odileDespair: