ILMerge: Combining assemblies in one exe, App.Config - c#

I am using ILMerge to combine .ddls in one executable, however when I run the Output.exe, it seems not to be finding the App.Config file. It is returning an error of: InvalidOperationException: No connection string name could be found in application config file.
I wonder whether ILMerge has included the App.Config file in the Output.exe at all.
How can I not include it and make sure that the Output.exe is referencing it?
I used the ILMerge GUI - this doesn't give me the option to include anything but the .dlls - which I select from the bin/Release folder where the ConsoleApplication compiles into.
Here is an image from the bin/Debug folder. ILMerge doesn't give me the option to include ConsoleLayer.vshost.exe.config - which includes the (basically) App.Config file. How can I make it include it so that the Output.exe knows the connection string details when it runs?
Thanks.

The default configuration file is app_name.exe.config. You need to take the config file you want and rename it to match the exe file.
In your case Output.exe.config.

This may be a bit late for this if you have found a solution, but any file with vshost in it's name is generally associated with debug mode in your application. It's you application running in debug mode. So when you are clicking on the application.exe to run you app, it does not look for any file with vshost in the file name. it looks for the application.exe.config instead. You can turn this off for debugging.
Unless you are planning on including your debug files in you merged exe, I see no need to include it. it's only useful in debugging.
Here are some links that may be helpful...
google search for disabling vshost
Stackoverflow question and answer...
what-is-the-purpose-of-vshost-exe-file answered by the famous Jon Skeet

Related

c# How do I correctly compile code for distribution?

I want to convert my program into something that I can give out and people can use (just to my friends and people I know) but I'm totally lost as of how to do it. I've tried doing lots of things from other forums but none seem to work or actually do what I'm looking for.
I tried using the publishing feature in the build tab but don't like that It makes It into a ClickOnce application as I'd much rather have it as an .exe.
From what I read there is already one of these in the bin\debug folder (I'd use the use the release bin\ folder when I am fully finished) but i don't know how much or what files actually need to be packaged together for it to work on another computer.
My main questions are:
Can I actually make a distributable a application using the bin\debug .exe with all the other files in it?
Do I also need to include the obj and properties folder? (I'm guessing not for the properties but the obj does look kind of important)
Because I've used NuGet packages and references do i have to to include the App.config and packages.config or is this just something that visual studio uses?
sorry if I've got anything wrong with what I've said, I'm way out of my comfort zone here.
For a console application, you should be able to zip up the contents of the bin/release directory and distribute it directly.
You can safely exclude .pdb files from your archive, though they can help you debug the program if your friends and cohorts encounter errors.

Creating a "portable" .exe (without installer)

I've recently coded a little program to determine numbers in a picture and it is reliant on two libraries I've used. (DLLs)
Since my target computer is not allowed to install programs due to security reasons, I need to create a portable .exe.
.NET is installed on the target computer but for some reason VS still does not include the libraries I've used in the exe but instead creates an application folder with a setup.exe, some .DEPLOY files and an application manifest.
I am new to VS and .NET in general so this question could be easy to answer, but I'm asking since I've found nothing useful on StackOverflow neither on google.
You can simply build the application and copy your bin/Debug folder along, but that would still mean you need multiple files.
In order to merge all references into the executable, use ILMerge. Here is some help calling ILMerge.
Basically, after building, you should do something like this:
ilmerge /target:winexe /out:SelfContainedProgram.exe
Program.exe ClassLibrary1.dll ClassLibrary2.dll
There is just one file you need to send along.
One way to do this is to build your application in Release mode (You can pick from Debug or Release in the drop-down). Then go to C:\Projects\[ProjectName]\[ProjectName]\bin\Release (The location of your project folder may vary). You'll see a bunch of files but all you really need are the DLLs, executable, and the config if you used one. You won't have to do any setup if you keep the necessary files in the application's folder, just copy them all to a folder on the target computer, create a shortcut if you want then you're good to go.
You can just copy all your assemblies into any folder you want. Simply chose "Build" from within Visual Studio and copy the files from bin/debug to your destination-folder.
However you have to ensure that all (relative) paths (if existing) still work as you cannot be sure where the user of your program copies the files to.
One simple way could be to use 7zip Packager, it doesn't need any installer. However, VisualStudio method might be more reliable.
I encountered the same issue recently. ILMerge suggestion above is no longer supported. I found Fody.Costura as a modern replacement.

Why do I sometimes have an app.config and other times a binaryname.dll.config file?

In .NET, after building a project, why do I sometimes have an app.config and other times a binaryname.dll.config file?
You see it as app.config file during development (in Visual Studio). When deployed (as well as in your bin directory), app.config becomes binaryname.dll/exe.config file (automatically renamed by Visual Studio).
As for the exact reason...there is a good reason not to have it as app.config...for example, if you deploy several applications in the same directory, you would be able to have only one app.config...so there is a good reason to name it binaryname.dll.config.
So the real question is: why is it named app.config and not binaryname.dll.config in the first place?
One of the reasons I can think of is that you can always change your binary output name in project options (so compiler generates .exe file with a name different than your project name), and config file will be copied to correspond to that binary output name. Having it named app.config in the solution is better because you always copy the same file name to some destination file name, without a need to rename that file in solution (which is good especially when that file is under source control). There might be some other reason as well.

Temporary debug releases and final application releases

I have a quick question regarding debug and release in VS 2008.
I have an app i've been working on - its not yet complete but the bulk of the functionality is there. So basically i'm trying to give a copy of it now to the person helping with documentation - just so they can have a play and get the feel for what i've made.
Now the question is how to provide it to them. I was told to just copy the .exe out of the debug/bin folder and put that onto USB. But when testing, if I run this .exe anywhere else (outside of this folder) it crashes. I've now worked out why this is:
var path = ConfigurationManager.AppSettings["PathToUse"];
var files = Directory.GetFiles(path);
throws a null reference, so that App.config file is not being used. If I copy that file in with the .exe it works again.
So actually my question is regarding the best way to manage this situation. What is the best way to provide a working copy to people, and, is there a reference on preparing apps for release - so everything is packaged together and installed in a clean structured folder heirarchy?
If you want to be safe grab everything in the debug/bin folder. If you use the drop down in VS to change to release and then compile the project, there will be fewer files in the release/bin folder because many debug related files are not included.
If there are third party DLLs you are referencing, like if you downloaded log4net or something like that, then you can simply put them in the same folder as the exe. This is called side-by-side deployment, and in my opinion is the simplest and easiest to test.
You can search for XCOPY deployment to learn more about what you are trying to do.
You can take another step of compressing the bin folder into an archive like a zip file to make it easy for the user to extract them, or you could use a tool like WIX or NSIS to create an installer to extract and copy the files.

Getting Content Files and Primary Output programmatically

For some reason, we have a script that creates batch files to XCOPY our compiled assemblies, config files, and various other files to a network share for our beta testers. We do have an installer, but some don't have the permissions required to run the installer, or they're running over Citrix.
If you vomited all over your desk at the mentions of XCOPY and Citrix, use it as an excuse to go home early. You're welcome.
The code currently has hundreds of lines like:
CreateScripts(basePath, "Client", outputDir, FileType.EXE | FileType.DLL | FileType.XML | FileType.CONFIG);
It used to be worse, with 20 int parameters (one per file type) representing whether or not to copy that file type to the output directory.
These hundreds of lines create upload/download batch files with thousands of XCOPY lines. In our setup projects, we can reference things like "Primary output from Client" and "Content Files from Client". I'd love to be able to do that programmatically from a non-setup project, but I'm at a loss.
Obviously MS does it, either using an API or by parsing the .csproj files. How would I go about doing this? I'm just looking for a way to get a list of files for any of the setup categories, i.e.:
Primary Output
Localized Resources
Content Files
Documentation Files
EDIT:
I have a setup project like Hath suggested, and it's halfway to what I'm looking for. The only problem keeping that from being a perfect solution is that multiple projects depend on the same assemblies being in their own folder, and the setup will only copy the file once.
Example:
Projects Admin, Client, and Server all rely on ExceptionHandler.dll, and Admin and Client both rely on Util.dll, while Server does not. This is what I'm looking for:
Admin
Admin.exe
Admin.exe.config
ExceptionHandler.dll
Util.dll
Client
Client.exe
Client.exe.config
ExceptionHandler.dll
Util.dll
Server
Server.exe
Server.exe.config
ExceptionHandler.dll
Since the referenced assemblies are all the same, what I get is this:
Admin
Admin.exe
Admin.exe.config
ExceptionHandler.dll
Util.dll
Client
Client.exe
Client.exe.config
Server
Server.exe
Server.exe.config
This causes a FileNotFoundException when either Client or Server can't find one of the two DLLs it's expecting.
Is there a setup property I'm missing to make it always copy the output, even if it's duplicated elsewhere in another project's output?
EDIT AGAIN: All referenced DLLs are set to "Copy Local", and always have been. I found a decent article on using NAnt and XSLT to grab the list of files, so that may be a possible solution as well, as neouser99 suggested.
ACCEPTED SOLUTION: I'm pretty much back where I started. All .exe and .dll outputs are put into a "bin" directory in the setup project, loosely packed. The other per-application folders contain shortcuts to the executable in that directory.
The difference now is, I'm going to add a custom action to the installer to use reflection, enumerate the dependencies for each executable output, and copy the .exe and .dll files to the separate directories. Bit of a pain, as I just assumed there was a way to programmatically detect what files would be included via some setup library.
why not use another setup project and just set the 'Package files' setting to As Loose uncompressed files (setup project->properties)? then share the folder.. or something.
edit:
I see, you have 3 folders for your outputs. but the setup project only detects the ExceptionHandler.dll and Util.dll once, so it will just pick the first folder and put it in there.
You could do a setup project for each project - bit annoying maybe..
You could manually add in the dll's to the projects that are missing the assembly's
either by adding in the File by 'add file' or 'add assembly' or 'add project output' if you have those projects in the same solution.. (I doubt that's the case though).
or just dump all of them into one output directory...
Although it's designed as a build tool, you might find NAnt to be extremely useful in what you are talking about. The tasks (build, copy, move, delete, etc.) that you can define allow for very fine-grained file lookups, up to general, full folders. If you also incorporate NAnt into your build process, I think you could find that it helps out in more ways then one.
Another approach that has worked for me in the past is to add the shared resource (Assembly, DLL or project) as a reference to each of the Admin, Server and Client projects. Then open the properties panel for the referenced item in each project and set "Copy Local" to true.
Now when you build the projects, each will have its own instance of the Assembly copied into its output folder.
This should also cause the shared components added in this manner to be replicated in each of the output folders in the setup package.
A completely different approach could be to set them up as symbolic links on the network share. A symbolic link is basically a short-cut where the file-system hides the fact that it is a short-cut, so all other applications actually believes that the file has been copied (http://en.wikipedia.org/wiki/NTFS_symbolic_link).
One advantage of this approach is that the file is updated immediately as the file changes and not only when you build your projects. So when you for instance save one of the config-files with a text-editor the update is applied immediately.
The following MSBuild script part can build your SLN file (you can replace it with .csproj) and will report a list of all projects that were build (Dlls, EXEs).
<MSBuild Projects="MySolution.sln" Targets="Clean; Rebuild" Properties="Configuration=$(BuildMode);">
<Output TaskParameter="TargetOutputs"
ItemName="AssembliesBuilt" />
</MSBuild>
Now, this doesn't really solve your problem, but it gets you a list of everything that was build. You also have copylocal, so you could probably just take AssembiesBuild and copy all DLL and .CONFIG files from there.
Example:
AssembliesBuild = c:\myproj\something1\build.dll
you'd go to c:\myproj\something1\ and simply search for all *.dll and *.config files and include them. You can do this pretty easily with MSBuild or powershell, if you have it installed. To output a XCOPY script from MSBuild, I think you'll need MSBuild contrib projct installed.

Categories