My C# WinForms application is designed to be simple to deploy and I don't like the fact that the log4net.dll becomes an additional file to deploy. Is there a way I can embed it into my application so all the user gets to see if the main .exe file and the backend SQL CE database?
Yes. You can do that using ILMerge.
ILMerge is a utility that can be used to merge multiple .NET assemblies into a single assembly. ILMerge takes a set of input assemblies and merges them into one target assembly. The first assembly in the list of input assemblies is the primary assembly. When the primary assembly is an executable, then the target assembly is created as an executable with the same entry point as the primary assembly.
Here's a GUI for ILMerge to make things easier for you
Well, as a side approach (other than ILMerge),
You can log everything in your server where you have deployed your application using log4net. When you want to retrieve your log, use Webrequest to get the data from the server.
Provided everything will need internet connection to log.
Related
I might be a bit stupid, but I want to create a tool in Visual Studio in C# and want to call third party tools via their API-DLLs. The only topics I found here are dealing with one of the two methods that I already know:
Compilation time: add a reference to "C:\FooTool\foo.dll" in my project + "using fooToolNamespace.fooToolClass" in my code (compilation time) --> I can "naturally" use the classes of the DLL and will even get full IntelliSense support if a suiting XML-file is available with the DLL. Also compilation time checks will be done for my usage of the dll.
Dynamic (run time): calling e.g. Assembly.LoadFile(#"C:\FooTool\foo.dll") and then using reflection on it to find functions, fields and so on --> no IntelliSense, no compilation time checks
So I actually have the DLL at hand and thus option 1) would be nice during development. But if my tool is used on a different PC, the third-party DLL might be in a different path there, e.g. "C:\foo\foo.dll" and "C:\bar\foo.dll".
In my understanding using a copy of "foo.dll" will not work, because "foo.dll" might have dependencies, e.g. requiring other files of the FooTool-directory. Thus in my understanding I have to call the DLL which is "installed" to the target PC and not a local copy of it.
So can I somehow change the path where my tool accesses the "foo.dll" at runtime and still use method 1) during development?
Or is there another way of doing things?
Or am I just dumb and there is a simple solution for all this?
Thanks a lot for the help and have a great day
Janis
To be able to use option 1 (a referenced DLL), you need to put the DLL somewhere "where your EXE (or, more precisely, the Assembly Resolver) can find it" on the customer's PC.
So where does the assembly resolver look for your DLL?
In the directory where the EXE resides (for desktop/console applications) or the bin subdirectory (for web applications). Since you mention that your DLL requires other dependencies as well, you'd need to copy them to that location as well.
The Global Assembly Cache (GAC). If your dependency supports this, installing it to the GAC ensures that it can be found by your application.
These two are the "supported" scenarios. There is also the possibility to tweak the assembly resolver to look into other directories as well, but that should be reserved for special cases where the other two options failed. (We had such a case and solved it with a custom AssemblyResolve handler on the application domain.)
I have a DLL I generate from a C# project. I then register it via regasm so that the library can be used inside several legacy VB scripts.
Recently I created a new project (C# console app) that will reuse certain modular aspects of the original library, and per good programming practice it made sense to add the library to the GAC for reuse by this and any future projects.
I've found that it plays nice at first, but after the server is rebooted, the VB scripts crash and burn, claiming they are unable to create an object of one of the types defined in the library.
The fix involves removing the library from the GAC and re-registering the library via regasm.
The libraries in the registry and GAC come from the same physical DLL file - same directory and everything.
I've confirmed the existence of registry entries for the library every step of the way, which says regasm did its job.
GAC entries only exist when the library is installed, and properly disappear when it is uninstalled. They only ever appear under GAC_MSIL, where, to my knowledge, they should be.
Any ideas why this is happening?
EDIT: I did not read the fine print, haha. On the regasm documentation I just saw this: "Creates a Codebase entry in the registry. The Codebase entry specifies the file path for an assembly that's not installed in the global assembly cache. Don't specify this option if you will subsequently install the assembly that you're registering into the global assembly cache. It is strongly recommended the assemblyFile argument that you specify with the /codebase option be a strong-named assembly." I was using that switch, so I will dig deeper. In the meantime any additional insights are greatly appreciated.
I would guess you didn't renew the GUIDs and/or distinguish the fully qualified type names of the new library and when you installed it with regasm, the old entries in the registry got overwritten. Registering the old library again has overwritten the new library's registry, but as you don't use it through COM that didn't affect it and now the scripts work again.
The VS solutions I often work with consist of a single executable project (console app, web app) and many class library projects that are all referenced by the executable.
When working with NuGet and installing packages, there's often an app.config file created for each project, usually containing nothing else than a list of binding redirects that consolidate versions of referenced assemblies. Sometimes there's some third-party library-specific content (like Entity Framework config section), but let's leave that aside for now.
When I build the solution and use the binaries of the main executable project, I see all the class library project assemblies in the build output together with the corresponding *.config files (the app.config file gets renamed to AssemblyName.config when built).
When launching the main executable, do the config files of the class library assemblies take any effect? Or is it just the app.config file of the executable that has an effect in this case? What if there are some binding redirects set up on some of the class library projects, and some different binding redirects set up on the main executable project — How are these combined, which take priority?
I've tried to research this online and from what I've read, it looks to me like the app.config files for non-executable assemblies are useless (with regards to binding redirects). Can someone confirm this or elaborate a bit more on the topic?
If it is that way, is it actually undesirable to have these app.config files created by NuGet in class libraries if they contain just the binding redirects? It feels to me that NuGet shouldn't create those binding redirects for class library projects, as it will only increase the confusion about what settings are actually applied.
I found these existing Stack Overflow questions on the topic, but their accepted answers are actually contradictory even when they're marked as duplicates of each other.
Why NuGet adds app.config with assemblyBinding to LIBRARY projects during a NuGet package update?
Is the bindingRedirect .config file needed or all assemblies in an application?
The accepted answer to the first question mentions that app.config files are actually used during compile-time, which means they could have effect. Sources like MSDN and MSBuild source code are cited there as a proof it's used during compile-time. Unfortunately, I'm not proficient enough in MSBuild to understand how it's being used, and if it's really a valid argument.
Can anybody describe an example scenario to prove that an app.config with binding redirects for a class library can do anything?
I have multiple applications with similar setup - Web application referencing multiple library projects each having their own nuget packages etc., Based on my personal experience the assembly bindings in the library projects are not considered during run time.
The bindings specified web or app config in the root application (web/console) is that only matters. All my library projects are setup with "Copy to Output Directory" setting as "Do not copy" for the app.config file - that way my output folder is not cluttered with dll and their config files.
Here is the link which says how the assembly is loaded and where is it being searched and the sequence of it. No where in the article they talk about individual project config files.
Hope that helps.
According to this old msdn article:
An application configuration file is an XML file used to control assembly binding. It can redirect an application from using one version of a side-by-side assembly to another version of the same assembly. This is called per-application configuration. An application configuration file applies only to a specific application manifest and dependent assemblies. Isolated components compiled with an embedded [ISOLATIONAWARE_MANIFEST_RESOURCE_ID] manifest require a separate application configuration file. Manifests managed with CreateActCtx require a separate application configuration file.
So only dll's with the ISOLATIONAWARE_MANIFEST_RESOURCE_ID set actually use an independent application config, otherwise it's deferred to the main process config file.
For more info on what ISOLATIONAWARE is you can read this other MSDN article that goes more in depth.
ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used primarily for DLLs. It
should be used if the dll wants private dependencies other than the
process default. For example, if an dll depends on comctl32.dll
version 6.0.0.0. It should have a resource of type RT_MANIFEST, ID
ISOLATIONAWARE_MANIFEST_RESOURCE_ID to depend on comctl32.dll version
6.0.0.0, so that even if the process executable wants comctl32.dll version 5.1, the dll itself will still use the right version of
comctl32.dll.
The answer is maybe. Depending on the type of project the library file is. Some library projects run in contexts where the library's config file is respected (e.g. Azure Web Roles), but that is not the norm.
See my answer here for more details.
Generally there is only one configuration file and thats the configuration file of the executeable (.exe.config, web.config).
Any assembly redirects have to be placed in the configuration file of the executable.
Configuration files of dlls need to be loaded manually using the ConfigurationManager class. See also this question Equivalent to 'app.config' for a library (DLL)
No, only the app.config of the executable will have effect. For example, if you have a console app hosting a WCF service, and in your WCF service you make use of, for example, ConfigurationManager.AppSettings, the AppSettings will come from the console host app.config file. If you spin up another console application (ConsoleClient) to try connecting to the ConsoleHost, then in the parts where the ConsoleClient can be said to be "executing" (for example in its main method), it will use ConsoleClient's app.config, but as soon as it begins using the WCF service, the WCF service will delegate to use ConsoleHost's app.config. (Note that this last point is more relevant to the details behind WCF though.)
Surprisingly, msdn provided this great source:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?referrer=http://social.msdn.microsoft.com/Forums/vstudio/en-US/e13194df-6308-4cbe-973c-f6a462f43eae/how-can-wcf-library-dll-access-application-settings?forum=wcf
Here I have 'ConsoleApplication01", "ConsoleApplkication02" and I am using COM reference of "Test.dll" in both Applications.
Now I am keeping both Exe's in same location to use functionally. So will it affect its operation due to this.
if the dll is the same it will not effect functionality .
we are using User.dll Kernel.dll almost in all applications .
leave this to OS
Generally, two applications can run together using the same assembly, keep in mind that it also depends on your referenced assembly functionality, for example, if the referenced assembly creates a file with a constant name in working directory and writes to it, the operation will fail if you will try to use this functionality from two applications in the same time.
How can I use different dll's (other Version) with the same name in one directory?
For Example, LibA (ExternalLib.dll) has Version 1 and LibB (ExternalLib.dll) has Version 2.
I'm deploying all my programs to the same directory (this is our companys standard and I can't change this fact). The problem is if ProgramB which is using the LibB is deployed in the directory where ProgramA is using the LibA then ProgrammA would not longer work.
For my own Libs I use a Major-Version-Number (.01, .02) if there are big changes. But the Lib I'm using is an external Lib and each version of it requires different licensing-keys (which are handled by the programs itself).
I tried to rename the external libs from "ExternalLib.dll" to "ExternalLib.v1.dll" and "ExternalLib.v2.dll", but when I run my fresh compiled programm it throws an exception that says "ExternalLib.dll could not be found". The reference in my project is set to "ExternalLib.v1.dll" and compilation works fine.
Any ideas / suggestions to handle different assembly versions in the same directory?
Unfortunately, the filename of the DLL file has very little do do with how .Net is loading these types. The actual name is written into the meta data of the assembly as part of the compilation process. So at runtime, it will be probing for ExternalLib.dll regardless of what you renamed the file to. The usual way to fix this is to install to the GAC and use Strong Naming to reference the specific version.
Given you may not be able to do this, there are 4 things you could try:
Ask the vendor to produce version specific DLL's for you. They could compile such that the version name is part of the filename and included in the assembly manifest. This would be the simplest solution for you.
Handle the AssemblyResolve event and manually try and use Assembly.Load to point at the file you want such that you can specify specifically which dll to use. See http://support.microsoft.com/kb/837908 for more information, but effectively you'll be using Assembly.LoadFrom(specific_path) to choose the file where the code will load from.
If possible, you might also be able to use ildasm.exe to decompile the dll's to Intermediate Language (IL), then use ilasm.exe to recompile it to a new dll name. You would then reference this new DLL name in your project.
If the assembly is not signed, then you may be able to edit the manifest yourself; you can either use a compatible binary editor or possibly MT.exe.