V.B.
V.B.

Reputation: 6382

Detect if running from published self-contained executable

Is there a simple way to detect if a .NET Core app is running from dotnet installed on the system or self-contained distribution?

I am working on a build automation script that requires some knowledge about relative paths and entry point for creating dependent processes with cli args.

I am Using .NET Core and publish self-contained app that creates myapp.exe. During design and debug time the program is run with dotnet command and I use the following to start another process with specific cli args:

var filename = typeof(Program).Assembly.Location; // .../myapp.dll
var argsString = string.Join(" ", args);
var startInfo = new ProcessStartInfo
            {
                Arguments = filename + " " + argsString, 
                UseShellExecute = false,
                RedirectStandardOutput = true,
                FileName = "dotnet",
                CreateNoWindow = false,
                WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
            };

But then in self-contained application the file name should be FileName = "myapp.exe" and Arguments = argsString. However, the property typeof(Program).Assembly.Location still returns myapp.dll, because myapp.exe is a wrapper over distributed copy of dotnet packed with the self-contained app and it calls the same myapp.dll.

Without knowing where I am running from I need to change the parameters every time I publish the app, which significantly slows down development and makes build automation much harder.

Is there a "normal" - i.e. supported by the framework with some property or methods - way to detect this, without checking if myapp.exe is present in the working directory or some other heuristic?

Upvotes: 6

Views: 1498

Answers (2)

David Browne - Microsoft
David Browne - Microsoft

Reputation: 89006

Looks like Assembly.GetEntryAssembly() is redirected to your .dll, but you should be able to see the real executable with Process. Eg

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

Which is more of an an OS-level API.

Upvotes: 3

V.B.
V.B.

Reputation: 6382

It was a wrong direction/approach.

To achieve what I wanted:

a. Build -> Configuration Manager... -> New Config

b. Name it e.g. Publish

c. Add the following to .csproj file:

<PropertyGroup Condition="'$(Configuration)'=='Publish'">
  <DefineConstants>$(DefineConstants);PUBLISHED</DefineConstants>
</PropertyGroup>

d. Use the newlly created Publish config in dotnet publish or from VS Publish... wizard.

e. Use from code:

#if PUBLISHED
            Console.WriteLine("+++++++++++ Running from published +++++++++++++");
#endif

Upvotes: 3

Related Questions