I have a use case where it would be useful to have a single exe that could decide on startup whether it's hosting only WPF application code or only WinForms code. Once the decision is made, the exe would simply load up one dll (for WinForms) or a different dll (for WPF).
I would like the exe to have as little code (and references) as possible and put most if not all of the application logic in a set of dlls. Here's what I'm thinking:
MyApp.exe <- The exe shim.
MyApp.Core.dll <- Things and Stuff.
MyApp.Windows.Forms.dll <- The WinForms dll.
MyApp.Windows.dll <- The WPF dll.
MyApp.exe would reference only the .NET framework assemblies that are common to both WinForms and WPF. (so, System, System.Core, System.Data, System.Xml, etc) Then it would just dynamically load a reference to either MyApp.Windows.dll or MyApp.Windows.dll which would do the rest of the work.
My questions are:
What can possibly go wrong?
I can't find any examples out there. Can you?
Is it worth the trouble just to avoid having 2 separate exes?
(Basically, a single exe would be really sexy and simple for end-users (who are developers), but it's not completely necessary. So if this idea is way, way off the beaten path and could potentially cause unusual problems I wouldn't want to do it.)
Thank You.
On you decision assembly just call Process.Start() and run the proper App. Don't mix the things on development.
Related
I have a WPF application whose output is a.exe. This application is dependent on an external b.dll (whose source code I have access to).
Requirements:
The output should only be a.exe which should contain the dll. I don't want to provide my users with a separate dll (if it can be avoided)
I should be able to obfuscate the code. (I don't want anyone to be able to modify it).
Approaches tried:
I embedded b.dll inside a.exe, it worked. But I was not able to obfuscate the exe as it gave an error that it was unable to find b.dll.
I obfuscated a.exe and b.dll but it did not work. It was unable to find b.dll.
Alternate approach :
Is there any way that I can perhaps add the spruce code of b.dll to my project and have the dll be compiled to the exe itself rather than a separate dll.
Is it possible to make this alternate approach work or are there any other ways ?
If nothing works, I know that I can compile a and b separately, obfuscate a and provide b as a separate file (what I'm trying to avoid).
Apologies for the formatting issues, if any, I'm using the android app. Let me know if you need any details.
I have had great success with Eazfuscator.Net in the past.
http://www.gapotchenko.com/eazfuscator.net
To run it from the command line enter the following command:
Eazfuscator.Net.exe -n a.exe b.dll
It will combine the two files into a single exe. The main program will be able to access the dll.
You can even set up Visual Studio so that the command line above runs as a post compile event.
Assembly embedding may seem quite confusing, so here is how it's usually done:
The dependencies are obfuscated if needed.
The target assembly is obfuscated. At this point, the obfuscator is also instructed to embed certain dependencies as a part of obfuscation process.
As a result, the embedded assemblies are stored as a resource of the target assembly.
In order to load dependencies at runtime, obfuscators usually install a handler for AppDomain.AssemblyResolve event that is raised by CLR when it fails to resolve an assembly automatically.
The handler extracts and loads an embedded assembly from the resource.
That's it. A good obfuscation tool allows achieving that quite easily. I don't see why it wouldn't work in the case with WPF application. If there are problems, I would recommend contacting product support.
Another option is assembly merging. Unlike embedded, the merged assemblies become an inseparable part of the target assembly code. For this reason, the assembly merging often helps to achieve a better obfuscation coverage and application startup time comparing to embedding. Although it may look a better option, merging may sometimes break the application functionality.
I'm working with Visual Studio 2010 and WinForms, .Net 4.0 (C#). I'm building an application with a lot of DLL (150). When I provide the application to my client, it's :
The Executable (.exe)
Dll files (.dll)
Each Dll is related to a module of the application, for example :
Ado.dll (provide access to database)
AccesManagement.dll (this module allows to manage users in the application)
Import.dll (this module allows the user to import data to the application)
etc.
When my client find a bug in the application, I correct it and I provide him impacted DLLs (in order to avoid him to test all the application). It can be for example the Import Dll.
The thing is, after some deliveries, we can have compatibility problems between Dll (a method that doesn't exist anymore in a new DLL for example). To avoid this problem, I would like to find a tool capable of checking compatibility between differents DLL.
I would like something like :
I specify the directory of the program to analyse (executable + Dll)
I launch the analyse
The program tells me for example : Error between Import.dll and Ado.dll, there is a class xxx in Import.dll expecting a method named xxx in the class xxx of Ado.dll
I've found some tools able to compare two versions of a Dll and provide added and removed members (Libcheck, ApiChange), but it's too complicated for me to do that because there are to many changes.
I think you may have a configuration management problem here -- at least as much as you've got a "compatibility" problem.
I'd recommend you find a way to track what versions of which assemblies each of your customers is using so that (1) you know what they're using when you decide what to ship, and (2) when they report bugs, you can replicate their setup (and thus, replicate their bug). If that sounds like a lot of work, it is. This is why a lot of software development shops take steps to ensure that there's a limit to the variation in setups among customers. It's nearly certain that you'll end up with some variation from customer-to-customer, but anything you can do to manage that problem will be beneficial.
Beyond the process implications, if you really need to create a "pluggable" environment, you probably need to create some interfaces for your objects to control the points where they connect, and you should probably look at Microsoft's Managed Extensibility Framework (MEF). MEF can help you manage the way objects "demand" behaviors from other objects.
I finally found a solution to my problem.
Since I'm :
Using SourceSafe and adding labels with the version of the application I'm building
Tagging each of my DLL with the version of the application
I built a program which is capable of :
Opening each Dll of a folder to read the version of the application in it
Getting from SourceSafe each project for the version specified in the DLL (With the functionnality "Get Label")
Then I just have to build the projet. If there is any compilation error, there is a compatibility problem.
This solution can avoid big compatibility problems, but you can still have compatibility problems which can't be seen with a compilation...
There are 5 console apps working off each other's outputs and are separately installed on my computer (C# 4.0, I am the author) . Management would like to distribute this suite of apps to other users, but aren't thrilled about asking non-tech users to install/configure 5 separate applications. Is there any way I can compile each program down into a .dll and reference them through a single master application?
Q. The main issue seems to be that you don't want 5 separate installation steps?
A. Make an installer for the suite :) Use any MSI builder (WiX, Visual Studio setup projects, InstallShield, and many others; Heck, you could even do an XCOPY deployment in most cases)
Q. How do I directly invoke these programs from within a single process?
A. Options:
Load the assemblies in your AppDomain.
Use a separate AppDomain in case of name(space) conflicts or version conflicts
Q. How do I optionally 'hide' the presence of the external console apps from view
A. Look at ilmerge to possibly combine the 'external' assemblies so they aren't visible anymore. If you can't use ilmerge (conflicts, or e.g. WPF apps) you might embed them as resources and load them on demand as per 1. and 2. above
Update: https://libz.codeplex.com/ is a nice looking project that makes this easy (haven't tried it myself)
Just because each of them is a separate .exe file doesn't mean you can't treat them as one application. And they don't have to be installed or configured separately either.
But a much better solution would be to rewrite each of the applications, so that they expose classes or interfaces that can be used without actually running the application. This way, communication between the parts is going to be much easier.
In .Net, the only difference between .exe and .dll is that you can run .exe directly. But you can treat both as libraries, so you can use functionality from one .exe in another .exe. Another step might be separating the core of each application into a .dll and make the .exes just deal with input and output. With this, the combined application wouldn't have all the code that it doesn't need from the other ones.
Its possible if every assembly is using different class names. Just include the whole source code when you compile the final version in one project.
Go to Project's properties, Application and change OutputType from Console to Class Library.
EDIT
Would like to express my doubts on architectual desicion like this, correct me if I'm wrong in my thinking:
Having different EXE applications standalone, I presume, you have different Applications that works standalone.
What advantage you gain by converting them in DLL's and puting them together in one master app ? Why do not just use this EXEs with one master app and launch them ?
In this way you leave as is it already working + you add a layer (master app) so for final user all this seems like one single app.
That is possible - several options:
you put the functionality of each console app into a separate class within the same project and have one "master console app" provide their functionalities
you put the functionality of each console app into a separate class each in different project with DLL as target, then you reference those DLLs as needed from your "master console app"
Note: IF you go the DLL route you could embed the DLLs into the console EXE using the technique from http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx
With both option (all in one EXE or EXE + embedded DLLs) you can just make an XCOPY deployment if there are no other dependencies...
I wrote a quick console application that uses SharePoint dll files. If I attempt to run it on a machine that doesn't have said dll files, the application immediately crashes upon opening.
I'm definitely a newbie, but I would prefer if there was a way the application could tell the user they are using it on a wrong machine, before it hard crashed. Is there a way of doing this other than writing a second application to scan for dependencies, to be run prior to the application in question? If I put the code that needs dependencies in a separate class, that isn't instantiated until the application has checked it is on the correct computer, will the application still fail immediately on opening? Surely someone has figured out a workaround for this sort of situation.
Unfortunately you will have to write a launcher application - if you think about it, the required DLLs need to be there for the main application to even start. If you embed the scan in your main application, it will not start due to the missing DLLs.
You may be able to use a plugin architecture that scans for required DLLs and loads them dynamically (MEF comes to mind).
How about wrapping the load of that dll into:
try {
Assembly.Load(..);
}
catch(TypeLoadException ex) {
//Let the user know which type from what dll was not loaded.
}
You will have to load that dll at runtime to actually do that though.
It might be possible to copy the assemblies to the output directory for sharepoint. So references are made locally.
if your application references directly the SharePoint dlls or assemblies there is no way to notify the user because the .NET CLR will not execute your code if any of the statically linked needed assemblies is not available.
you can either use some kind of dynamic loading of the SharePoint assembly and types so at the startup time the application does not need that assembly to execute, or you create a launcher for your application which does the check and if all is ok starts your application otherwise notifies the user.
There are a lot of posts on here about this, I'm using this code from another SO post and placing a delegate assignation in my Main() method. None of the other posts have directly answered my question.
I've got my third party assembly embedded as a resource but when I fire up the app:
I'm getting a TypeInitializationException with an inner of FileNotFoundException. It's trying to find the assembly on the file system and failing.
it's never getting to the Main method, where the event handler for AssemblyResolve is assigned
I have two assembly refs that are embedded in my Resources.resx, one is a third party tool (command line parser) and the other is a Library file where the meat of the application resides.
Maybe this isn't possible with a console app? Seems unlikely but I don't see a way around it.
Re: ILMerge etc: I'd like to get this done entirely in code without involving any tools. Reason: I don't want to have source code in the repository that requires other team members to install a tool that they probably don't have already. If that's not possible then ILMerge looks like the next best option.
Consider using ILMerge to merge the assemlies into one rather than embedding as a resource. This is download site for ILMerge.
You would merge your third party assemblies into your console app.
You could also look at application virtualization tools like XenoCode. They can package multiple assemblies (including the .net framework itself) into a stand alone executable.
If it is mixed mode assembly, it has to reside on the disk. Some limitation or something.