I have a winforms application which is built dynamically by another application, now the code in the winforms application needs to reference an assembly which I have in a dll. I'd like to embed this in the winforms application somehow so that it doesn't need to be sent with the application to the client.
I've tried the compilerParams.ReferencedAssemblies.Add method but this does seem to let me run the application without still having the assembly in the directory with the application.
I've also tried putting the assembly in the resources of the winforms application and then pulling this back out in the runtime of the winforms application using Assembly.Load, the only problem here is that any references to the assembly don't seem to work so by the look of it I'd have to use reflection to identify the methods in the Assembly dynamically which isn't ideal.
Essentially my question is what's the best way to do this!
Have a look at the ILMerge tool.
Related
I have a winform c# app.
I can use a [web method] to check for a version of a DLL that my client winform should use. I can also download it. But, if I copy over the old DLL I will get an error stating that the file is in use. I had expected this.
Is there a way to unload this DLL from my running winform app, copy over the DLL and reload it?
I do not want to use a boot-strapper for my updater and it may come to having to stop and restart my application.
All this will be obsolete if I can just unload my DLL.
I have looked for a long time and cannot find anything. Before I retire on this I thought I would post the question here.
Thanks
PS
I could post the code that shows how to load an DLL in code and the error generated from it but it is open knowledge and does not add to this question.
Is there a way to unload this DLL from my running winform app, copy over the DLL and reload it?
Not in most cases. The only way to unload a DLL in a managed application is to unload the entire AppDomain. This typically means you need to be very careful about how you use the assembly (you can't just directly reference and use it as normal).
I do not want to use a boot-strapper for my updater and it may come to having to stop and restart my application.
This is the most common approach. Making this work inside the application is essentially building the bootstrapper into the application itself (in its own AppDomain), and unloading/restarting the AppDomain using the assembly. This is typically more work and just as disrupting as a separate bootstrapper application.
you are probably looking for something like MEF?
http://mef.codeplex.com/
http://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx
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.
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.
I am developing a windows 7 gadget.I am creating an activex object and loading the assembly.I am following the methodlogy mentioned here at codeproject (GadgetInterop). One of the tasks of the gadget is to interface with Facebook.
This is how I am referencing:
Javascript creates a GadgetBuilder object.
From here I load the my library. say "MyLibrary.dll".
When I call method say MyLibrary.GetCount(), (just return some integer) it works.
But when I call some facebook function inside the method say MyLibrary.GetFaceBookFeeds() it throws an error.I reference "facebook.dll" from CodePlex
If I test my code from a ASP.NET form it works perfectly. However, When I run it from my html page by trying to load it using javascript, I get the following error:
Could not load file or assembly 'facebook, Version=2.1.3654.38113, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
I verified that the dll's are in the same folder as "MyLibrary.dll".
Why is this error coming?
How do I go about achieving my task? (I need to use calling a dll from javascript as we are doing a lot of other things in the dll).
You're not forced to use a reflection-based assembly loader for .net code in desktop gadgets, you can write the assembly to be com visible, using class ids, etc. This article provides an example of using .net to achieve what you're trying to do without the "adapter".
That being said, there are various problems with activex based desktop gadgets that you should be aware of:
When an ActiveX instance is created in the gadget, the assembly dll will be "locked open" by sidebar.exe and the file cannot be deleted, even after the gadget has been closed. Unfortunately the gadget uninstallation process doesn't account for this and an uninstallation of the gadget will result in sidebar.exe copping out of the file deletion when it fails to delete the assembly, leaving the assembly and any other remaining files that hadn't been deleted up to that point. There's also no error message displayed. The same is true of overwriting a gadget (with a new version, for instance) - sidebar.exe attempts to delete the folder completely before installing the new gadget package, resulting in a failed installation in most cases.
The registration of such an activex control can be very tricky. The registry script given in the CodeProject article you provided does not work on my Windows 7 x64, for instance. The only way to work around this is to use WMI to write to the registry.
In a similar fashion, unregistration of the ActiveX control is also an issue. When the user uninstalls the gadget, the registry entries are left behind. Not a problem for a lot of people I suppose, but imagine a gadget enthusiast who tries every gadget he finds suddenly discovering the many unused registry entries. You can get around this by removing the registry entries directly after instantiating the object (since it's cached by the sidebar process anyway) and re-registering it again next startup.
So really although you can do it without reflection, using reflection can be a better option because you can copy the adapter assembly to an alternative folder, use it to load the current assembly and then unload it when the gadget is closed or finished using it. This eliminates the first issue of not being able to uninstall the gadget because the hosting assembly is located in a different folder and the reflected assembly is unloaded when the gadget is closed anyway.
The reason facebook.dll isn't loading is because the loader you're using doesn't correctly resolve dependencies (it can't find the file because it doesn't know where to look). You're welcome to try our reflection-based assembly loader called PluginLoader and see if that works. We haven't had an official release for it yet but we were intending to make it widely available and recommended for use by all developers to try and eliminate the problems with ActiveX and Windows Desktop Gadgets. Because we haven't officially released it you'll have to install our gadget, Auction Sidebar Tool which will install the plugin loader ready for use with the following code:
var plLoader = new ActiveXObject("Sidebar.PluginLoader");
var myLibrary = plLoader.LoadAssembly(classToLoad,
System.Gadget.path+"\\path\\to\\MyLibrary.dll");
myLibrary.GetFaceBookFeeds();
Where class to load is the class you need to load in the format Namespace.Class (ie MyLibrary.MyClass). We specifically coded it to correctly resolve any dependencies so it should work for you just fine. If it does work for you, you're welcome to include it with your gadget. All you need is the PluginLoader.js and PluginLoader.dll files from the AuctionSidebarTool folder, but you'll need to edit the PluginLoader.js file to remove the parts that reference our assembly (line 110 onwards). If you include this in your project, it will check for an existing PluginLoader.dll and if it fails, it will copy it to the Windows Sidebar folder in local AppData, register it and provide the AddInLoader object with the methods LoadAssembly and UnloadAssembly. If you need any extra help just let me know in the comments.
Hope that helps. That's probably the longest answer I've written so far on SO :)