Question How to generate a self-contained .exe that can be run from other PCs

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Dear C# Experts,
First off, please forgive me to ask basic, maybe silly questions. I am a C# beginner.

I developed a C# script (attached) that gets access to a Postgres database, the Velocity database, ConsoleX (available from GitHub), and some fuzzy string search algorithms.
Therefore my code makes references to Npgsqp, Velocity API, ConsoleXUI, and DuoVia.FuzzyStrings.
Please, be aware I cannot attach the whole "solution" folder as it is too big for the server to accept it even if compressed. I have attached all the .cs files of this project.

Visual Studio 2022 allows me to insert all the references I need. In fact, my code works locally (on the PC where I developed it) with and without the debugger (attached is a picture of the References).

My goal is to deploy an executable stored on a shared drive from which my colleagues can download it and run it.

I published my code using Visual Studio. I managed to avoid signing the application and generating a certificate or a manifest.
I just wanted to make things easy for me and my colleagues who are eager to use it.
From Visual Studio top menu bar I selected:
Project --> Test1 Properties -> Publish -> Publish Now.
The publication process was successful. The .exe file was placed on a shared drive.
When I run the executable from the shared drive the program dies on a system call:
"Path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;"
Such a call is supposed to inform the application about which configuration file to use to connect to the Postgres database.

I stuffed my code with printing statements to find out where it dies.
As an experiment, I eliminated the function that reads the configuration file and hardcoded the string to connect to Postgres.
It did not solve the problem. The executable dies upon attempting to access Postgres.

I called the department IT gentleman who has experience with code development. He singled out my problem.
He said I have to generate a self-contained executable. Basically, what MathLab calls a "Run-Time Environment". Something
like a "container" that contains the .exe file and also all its references.
I have no idea how to do that through Visual Studio. The IT gentleman has no idea either.
If I were working on a Linux or Unix platform I would edit the makefile. Unluckily, my knowledge of Windows at the system level is close to zero.

I would greatly appreciate some help to move on from this impasse.

Thank you in advance for your attention.
 

Attachments

  • References.PNG
    References.PNG
    40.8 KB · Views: 69
  • CSharp.zip
    9.6 KB · Views: 40
When I run the executable from the shared drive the program dies on a system call:
"Path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;"
Such a call is supposed to inform the application about which configuration file to use to connect to the Postgres database.
Three things about this:
  1. You say it dies. What exception or error is given when it dies?
  2. Why are you not using the app.config (if this is a .NET Framework app), or a appsettings.json (if this is a .NET Core app) to store this configuration information? .NET Framework and .NET Core know how to load their settings file without you needing to detect your deployment location.
 
Single file executables for .NET Core:

If you go with the self-contained route, this is worth reading since there is a high probability you want to enable trimming:
 
And if you are not using .NET Framework, most of the installer projects have options to create a single executable.
 
Three things about this:
  1. You say it dies. What exception or error is given when it dies?
  2. Why are you not using the app.config (if this is a .NET Framework app), or a appsettings.json (if this is a .NET Core app) to store this configuration information? .NET Framework and .NET Core know how to load their settings file without you needing to detect your deployment location.
Thank you.
My script uses .Net Framework 4.8
Platform: Windows 10 X64
I stuffed my code with Console.Write() and Console.ReadKey() statements to be able to follow what the executable does when run from the shared drive.
The program dies upon attempting to execute the following statement:
"Path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;"
I have attached the message from the thrown exception.

The executable was placed on the shared drive (U-drive) but surprisingly it is running on the C-drive that belongs to the PC where I developed it.
I understand that telling the system where to publish an executable does not tell the system where to run it.
However, in the publication electronic form (attached) I also indicated where to install the app but the indicated folder is empty.

I did not use the "app.config" file out of ignorance of its existence.
I have no idea where to find it.
Shall I create it or is it provided by Visual Studio?
I will have to google in the hope to find some tips.

I see that the remote folder, where the executable was generated, contains a directory called "Application Files" whose content is attached. Presumably, these are all the files the executable needs to run. If that's true then why it does not use them?

Many thanks
 

Attachments

  • Exeption-captured.PNG
    Exeption-captured.PNG
    72.2 KB · Views: 152
  • Publication-Form.PNG
    Publication-Form.PNG
    120.3 KB · Views: 154
  • Application-Files.PNG
    Application-Files.PNG
    105.7 KB · Views: 154
For .NET Framework, you need to read about ClickOnce and some of it's limitations (like running with lower rights when executed from a file share).

What is wrong with just doing an copy deployment from your Release build dir to the fileshare?
 
Three things about this:
  1. You say it dies. What exception or error is given when it dies?
  2. Why are you not using the app.config (if this is a .NET Framework app), or a appsettings.json (if this is a .NET Core app) to store this configuration information? .NET Framework and .NET Core know how to load their settings file without you needing to detect your deployment location.
I found a file called "app.Config in the same directory containing the project and the solution files. Its content is as follows:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>



I googled "app.config C# Visual Studio".
I found plenty of documentation. My understanding is that I have to create a Publish Profile to deploy a self-contained application. I am trying to follow the article on
Deploy .NET Core apps with Visual Studio - .NET
I think my case is explained in the section "Self-contained deployment with third-party dependencies'".
I do not know how to create a Publish Profile because the pictures shown do not match what I see with Visual Studio 2022.
I right-click on my project name in the Solution Explorer panel. Then I choose Publish And see the attached "Publish-page1". I click on NEXT and see "Public-page2". I click on NEXT and see "Publish-page3". I click on NEXT and see "Publish-page4". I click on FINISH so the publication process starts and completes successfully in under a minute. Such steps produce "Publish-result". When I click on the generated ConsoleApplication the program dies, as previously described.
I cannot find where and how to create a Publish Profile.
Shall I edit an XML file?
I am lost!

Can you please walk me through the generation / modification of the app.config so as to generate a self-contained application?

Thank you so much
 

Attachments

  • Publis-page1.PNG
    Publis-page1.PNG
    35.3 KB · Views: 93
  • Publis-page2.PNG
    Publis-page2.PNG
    36.9 KB · Views: 93
  • Publis-page3.PNG
    Publis-page3.PNG
    44.5 KB · Views: 80
  • Publis-page4.PNG
    Publis-page4.PNG
    28.9 KB · Views: 92
You have to choose whether you'll be targeting .NET Core or .NET Framework. Although they .NET Core is a descendant of .NET Framework, there are some major differences in the way that they work and how they are normally deployed. If you are a beginner and cross platform in not important, I would recommend sticking with .NET Framework because of the wealth of information available, as well as, less "gotcha's" and "surprises". If you're end goal is to eventually have the same code running on multiple OSes and you have a solid programming background, you may able to tolerate .NET Core, but I would suggest jumping straight to .NET Core 6.0 instead of fiddling around with the lower versions even if there is more literature available for the older versions.
 
Thank you for your help. Unluckily, I am not out of the woods yet.
I read the article "Single File Application".
There are snippets of XML language that, if inserted in the right place, should customize the polish process output (I think).
My question is: where to insert such snippets.
First of all I have to make sure I know the name of the project file.
My source code is "Test1.cs". Among the raft of files that Visual Studio creates there is. "Test1"
If I hover on it it appears that it is the C# project file.
I inserted <PublishSingleFile>true</PublishSingleFile> in the project file at the beginning then I tried to insert it at the end but still inside the project definition.
IN both cases Visual Studio printed out an error as that instruction could not be interpreted (attached screenshot). It did not load the solution file anymore.
When I right-click on the project name in the solution explore pane I see this window (attached screenshot). There is no Edit option as indicated in the article.

Then i tried to insert the longer snippet I tried to insert the longer snippet
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net5.0</TargetFramework> <PublishSingleFile>true</PublishSingleFile> <SelfContained>true</SelfContained> <RuntimeIdentifier>win-x64</RuntimeIdentifier> <PublishReadyToRun>true</PublishReadyToRun> </PropertyGroup>
in the project file. I observed that the publish section had changed and allowed me to select the option "selfcontained". Unluckily, despite the publication completed successfully, the destination folder for the executable was empty.
...... I am back to square number 1.
 

Attachments

  • Screenshot 2022-01-23 at 20.20.51.png
    Screenshot 2022-01-23 at 20.20.51.png
    288.4 KB · Views: 75
  • Screenshot 2022-01-23 at 19.56.33.png
    Screenshot 2022-01-23 at 19.56.33.png
    616.8 KB · Views: 77
This is only for .NET Core apps:
<PublishSingleFile>true</PublishSingleFile>. You said your app if .NET Framework.
 
True.
I have .NET Framework 4.8
So, how am I supposed to manipulate the project file, or any other file, to produce a self-contained Console application?
Thank you in advance. Regards
 
Why is it so important for it to be a single executable?

Since your users have to download from the file share and install the program, why can't your users just copy the entire file share directory unto their machine instead? You don't trust them to copy an entire directory, but you trust them to copy a single file?

If a single executable is a must, For .NET Framework, your best bet is to use InnoSetup (or most other decent Windows setup programs) to create a single executable which will install the app into your users machine. What makes this even better is that your users don't even have to download it to their machine. They can just run the generated setup executable right from the file share and your program will be installed into your users machines. InnoSetup also lets you setup icons on the desktop or start menu. And the best part is that you also have a clean uninstall because InnoSetup will also register the program into the machine so that Add/Remove Programs or the Win10 Apps settings can list your app for uninstall later.
 
Thank you.
My clients are actually my colleagues.
All use computers. However, they use Eclipse (treatment planning system) or Velocity (used for registering multi-modality biomedical images). I am afraid they will get confused and try to t=run the application clicking randomly on those files that Visual Studio dumps together with the executable.
I will check out the product you mentioned. I guess it is an installer, isn't it?
In the meanwhile, I will create a shortcut to the executable and distribute it.
It should not be a problem if more people run the application where it has been created rather than download a whole folder onto their respective PCs. In fact, through my code, they will access the Velocity database. However, Velocity allows only one user at a time to download and modify patient data.

Does the installer you advise require a license?
Thanks
 
Back
Top Bottom