I am setting up an installer project for a C# solution and I encounter a dependency problem:
In my solution, I have 4 independent project outputs – one windows service and three executables, who all share between them some references.
I need the installer to install all four of them in order for the solution to work.
I've set up an installation folder for each project output under "Application folder" in the "File system on target machine" dialog, added the project output of the windows service successfully in its folder. But when I continue to try and add the executables' project outputs in their folders the assemblies already carried into the windows service folder are not carried into the executable folder, and following the installation the executables won't run as they are missing dependencies.
I can manually add the missing assemblies to the executables' folders, but it seems that this is not how it should be done and there's something I'm missing.
Any ideas?
Well you should create a new project in the solution, and set the "installer" to be the output of your main application (or main applications) it should solve the dependencies itself.
I was having what I think is the problem that was originally described. I have a Winform app and a console application as two separate projects, but a single setup project handles both.
Both the Winform app and the console app use the same two external assemblies: one not part of the solution (reference to a file in a folder), and the other from a C# class project (reference to the project).
What I have found is that the installer assumes that the project output is all combined into a single folder on the installation machine. Therefore, all of the common assemblies will also co-reside with the executables that need them. So if you add the project output from the first executable into the folder, that is why you see all its dependencies appear, and then when the second project output is added, only the assemblies not already added will appear.
It doesn't matter if you create subfolders under the Application folder, Visual Studio appears to treat the Application Folder as a whole unit... as far as Project Output (exe, dll and res) are concerned.
There are two ways to solve this. The first is to create a separate installation project for each executable. In a large project, this could be a lot of setup projects.
If you want to keep everything in a single installation, a better option is to use the GAC for the shared assemblies, which is described in another Stack Overflow article here: Use Visual Studio Setup Project to automatically register and GAC a COM Interop DLL
MSI can get the job done. Right-click "File System on Target Machine",
Add, GAC. Right-click that added folder, Add, Project Output. That
ensures the assembly is gac-ed.
The GAC is the better solution in my mind, because your assemblies are managed by the .NET layer if you later make changes and enhancements to them. One of the benefits of .NET is to eliminate the old "DLL hell" issues that were in Win 98 and previous versions of Windows. I highly recommend using it for your common code.
Related
I have a WPF app that works with local SQLite and Entity Framework Core. I want to distribute my app using ClickOnce.
Everything works fine when I run it using Visual Studio 2017. But app had a crash on a start when I used ClickOnce. The crash was so early so I couldn't even log the exception. After some time I found that in publish folder some dlls were missed. For example System.Runtime. All references are NuGet packages. Then I found that despite of I have a reference to the dlls in my project ClickOnce application files list doesn't contains it.
The only solution I have found for now is to add missed dlls as files in root of my project and set build action to Content. In ClickOnce application file dialog I set publish status to Include.
It works now but it looks like not the best way to do it. The question is why they are missed in the first place. More likely I missed something or I am not understand the root of the problem.
UPD:
You can find an example code here.
It works from Visual Studio but crashes on a start when you try to install it as ClickOnce application.
UPD: The problem was fixed in Visual Studio Professional version 15.6.1
There are two ways solving solve this.
At first, you have to go Properties → Publish → Application Files, and at this place, make your DLL files include in your project
But if it does not work, go to References and make the DLL file CopyLocal = False. You add a DLL file like Existing Item in your project and make them Copy Always.
It will work correctly.
But for your sample I watch this and I solved it. Look at this image:
You have four DLL files. You need do this for them:
System.Diagnostics.Tracing.dll
System.Reflection.dll
System.Runtime.dll
System.Runtime.Extensions.dll
At first go to your reference and make them Copy Local False:
Then go to the path of each DLL file and add them like Existing Item, and then make all of them Copy To Output Directory CopyAlways
Then Publish it and run it like in this picture. I run it from publish file and it works.
Even if you set the dll to copy local, the dll will not get copied over unless you actually use the dll in your code. You might try adding System.Runtime in your code somewhere like this maybe?
var dummytest = System.Runtime.GCSettings.IsServerGC;
Based on Issue 9 on https://blogs.msdn.microsoft.com/bclteam/p/asynctargetingpackkb/ I was able to do the following:
Symptom
ClickOnce applications targeting .NET Framework 4.0 that reference the Microsoft.Bcl or Microsoft.Bcl.Async packages may experience a TypeLoadException or other errors after being installed.
Resolution
This occurs because ClickOnce fails to deploy certain required assemblies. As a workaround, do the following:
Right-click on the project and choose Add Existing Item
Browse to the folder where the System.Runtime.dll lives
In the File name text box paste in the path of the file
Click the down-arrow next to the Add button and choose Add as Link
In Solution Explorer, holding CTRL select System.Runtime.dll
Right-click the selection, choose Properties and change Copy to Output Directory to Copy always
Republish
I have a large solution currently under VS2010, with lots of projects and dependencies. Some of them are installed to the GAC, some of them are just included from a "lib" folder. I need to build one of my projects (specifically a WinForms app) to able to run on any, non-development computers without any installation process (except for the .NET runtime of course), just as portable apps do.
For this to work, I need to have all of the referenced DLLs and their whole dependency tree in the output folder of my EXE. I can do it for exemple by marking the dependencies to "Copy local" in the properties window, but that works only for the direct references of the EXE project, so it's far not enough. Another way is to make a setup project, but my client and also I want to avoid that (in the final version I'm gonna use ClickOnce). Of course I can always do it purely by hand, gathering all the DLLs manually, but that's quite a nightmare.
Is there some tool, msbuild trick, command-line option, whatever hack to force Visual Studio to gather the whole dependency tree of my EXE during build, and copy them to the output folder? So that I could just ZIP everything together and send to my client.
I actually chose a somewhat "middle" solution, the following way.
I created a "dummy" setup project, not caring about setting anything but adding the project outputs (primary output, localized resources, contents, etc.). It was a 2 minute task this way.
I built the setup project, and got the MSI file as the output.
I've extracted the contents of the MSI file to a specific folder, called "MyAppPortable" for example. I found the solution here. The command-line command is
msiexec /a "absolute_path_to_my_MSI_output" /qb TARGETDIR="absolute_path_to_my_desired_output_folder"
I got the full application with all of its resolved dependencies (except for late-binding dependencies, but I took care of them manually, by adding them as references to my projects). I could ZIP the whole folder, put it on another computer, and voila, everything worked fine.
Basically, using Visual Studio, you can set all of your Solution's Projects to build into the same Output folder and use this folder as your Windows Form application folder (where the application EXE will reside).
By doing this, you will coordinate all of the possible assemblies references that your app is depend on.
In VS 2012, right-click on a Project => Properties => Select Build (left pane) => Set your Output path:
I would select a a solution-level folder as the Output path.
And if it's prohibited to perform such a modification at your workplace so I would suggest you to use dependency analysis tools like the following in order to interrogate and gather the appropriate assemblies that your app is depend on and will require at run-time:
Dependency Walker
NDepend
Red-Gate Reflector
Update:
Using the above mentioned tools will not yields assemblies references which are late-bounded (at run-time), for this case you may use: Fusion (the Assembly Binding Log Viewer)
Check out the Fody/Costura recommendation from this question:
Embedding DLLs in a compiled executable
It's great! I just tried it out for a similar need and in less then a few minutes I had a completely portable (except the .Net framework) exe that I could easily give to co-workers.
So I made a C# project in visual studio with 3 class library projects. Everything works fine when debugging but When I try to deploy. Database and Program installs just fine but when I try to open the Application, I get an Assembly or File not Found Exception. The DLL he can't find is a class library in my project.
On the File System Editor, VS automatically detected the dependencies and included the 3 dll files in to application directory. I tried excluding these dll's and just adding the class library projects's primary output's (Same dll) but still the same error.
I used a Custom Installer class for creating my database on installation. But I don't think that is relevant.
If you have verified that your 3 assemblies are indeed deployed to your destination folder,
it could very well be an another dependency that you have not included in your setup project.
Please double check that you indeed have the right number of assemblies included.
You can also right click the setup project and refresh dependencies.
Have you checked that dependencies in the setup project aren't excluded (by mistake)?
Furthermore, it may also be a .NET profile issue. Do you depend on assemblies that are only available in the full .NET profile, and your destination only has the client profile installed?
In worst case, run the SysInternals process monitor and that way figure out which assembly is missing.
you need to include all dll's that are not part of the .net framework with your deployable. Your custom installer will copy these files to the location of the executable on install.
i usually create a folder called /deploy and copy all my needed dlls in there. I also change my projects settings to output to the /deploy-directory (instead of bin/). after you build, this directory will contain all dll's and other resources needed to run the application.
I finished a project.I am trying create a setup .
My Problem is that :after I create setup project dll files that I used in project added to same folder with my .exe file like
ApplicationFolder(Folder)
Devexpress.Data.dll
Devexpress.Util..dll
.
.
project.exe
but I want to get it different folder.
like
ApplicationFolder(Folder)
MYDLLFILES(Folder)
project.exe(exe file)
how can I make this? Thanks a lot
This is not only a problem of setup. unless you are already handling this in the app.config and/or with appdomain.assemblyresolve event your application will not work at all on the user's machines once those required references will not be available in the same folder if the .exe file.
Surely you could isolate every single file and tell the setup project where to put it but your program has to be modifief to then look for those files in those other locations.
I accidentally faced this problem today, I want to add some separate dll files into the setup package (I have to do this because I can't add reference of these dll files into my C# program , these dll files are of 3rd-party software).
I did as following:
Right click on Setup Project > Add > Assembly and then browse to dll which I need, then press OK button.
These dll files will be included into Setup project, and will be packaged into setup file also.
Hth.
The problem is that Visual Studio setup projects will automatically include referenced DLLs for you so you won't be able to customize their location with these setup projects.
See also the following articles by DevExpress:
How to deploy WinForms applications on client machines
How to distribute applications which use Developer Express .NET Windows Forms controls
The second article explains how to register DLLs copied to a different location.
By the way we're also also deploying a big app using these VS setup projects and our base installation folder is full of DevExpress and other DLLs. I agree that it looks totally ugly and I'd also prefer a clean structure with a lib subfolder, but nobody cares about that. Customers don't start our application from the installation folder, they use the shortcuts.
I've created a basic console app in Visual Studio 2008, which references an external assembly.
When I publish and install the project, both the executable and the external assembly are installed in the target folder.
Is it possible to compile the project, and have all referenced assemblies included in the main executable - so there is only one file to distribute?
Thanks for any help,
Franko
You can use ILMerge to merge the assemblies for deployment. This lets you keep them separate during development, but put them all into one .exe file when you ship.
You can use ILMerge from Microsoft for this, or the Cecil tool from the Mono project.
You can create a setup file. so you can redistribute only one file.
But it still going to be installed into a folder with each assembly separated.
You can also consider placing your assemblies into the GAC.
If you find ILMerge is not enough because your app needs files other than .net assemblies, I have found that packaging it as self extracting exe using MakeSFX works nicely. It sounds unlikely but with correct command line flags the self extracting bit is completely transparent and it runs just like any other application.