Why are referenced assemblies locked? - c#

I have 2 assemblies. Assembly2 is referenced by Assembly1.
Why is Assembly2 locked?
I thought the whole assembly is loaded into the RAM by the JIT-Compiler, isn't it?
How does the machinism work when a referenced assembly is called?

(yes, the question could have been better, still...)
Referenced assemblies are loaded into the process and are thus locked. You can get around this with shadow copying, or just make sure you close every process that uses your assemblies before you attempt to modify them.

I ran into a situation when writing a .NET componenet to be consumed in a VB6 app where I couldn't deploy my recompiled .NET assembly while the VB6 editor was open. This really frustrated me because I wanted to be able to just make a quick change and then have the change show up in my VB6 editor. I was getting an error message that the assembly was locked by another process or thread.
I later realized that this made a lot of sense. If the referencing application (in my case, the VB6 IDE) is trusting that library to be the same each time it goes to consume it, it's going to run into serious problems if the dll changes while the application is in memory.
In my case, closing the VB6 IDE, updating the dll, and reopening the VB6 IDE worked just fine. It was a little bit of a hindrance in my workflow, but once I realized why it was happening, I got over it.

Related

Check if all required DLLs and their dependencies exist on target

Is there a good way in C# to check if all referenced DLLs are installed on the target machine?
What I want to achieve is that my software doesn't start if one of the referenced DLLs are missing on the target machine. Based on that I can be sure that my features won't break during runtime because a DLL can't be found.
My idea: Create a separate AppDomain during startup, and load ALL referenced DLLs to it. If it fails I'd shut down my software. If loading succeeds I'd unload the separate AppDomain and proceed to start the software. Is it a good idea to perform the check in such a manner, or are there some known problems/pitfalls around it.
I'm aware that I posted no corresponding piece of code, I only want to gather feedback if my idea is a good one or not.
Thx

Registration free activation of native COM (activex) component from .NET

I have a native dll (which is an activex control) that I need use with my .NET application without having to register the dll in the registry.
I have read several in depth posts about registration free activation, some of the better ones are
A lengthy one from Steve White and Leslie Muller
This one from samuel jack
And another from Mike Makarov
and from what I can see it is possible. However several hours and hundreds of tests later I just cant get it to work. I've done a bit of PInvoking and even less with ActiveX controls in .NET in my career, so would appreciate any input from anyone whom might have kicked goals on this before.
So far I'm following Steves advice, in terms of building an application that works and then trying to formulate the winning manifest file syntax via repeatedly running the regsvr32 command to add and remove the unmanaged dll's from the registry. Just a bog simple .Net console application with about 10 lines of code...
One part that I am confused about is the interop. The native dll's I have are also accompanied with managed runtime callable wrappers (RCW's). In my .NET application I add reference to these RCW's and then can consume the respective classes and functionality provided for by the unmanaged dll's. I'm not PInvoking via dllimport.
In creating the manifest files I'm unsure if I need to worry about these RCW's and how they work in a registration free scenario, or even if if they need to be in the compiled output?
I've also tried several tools such as (OLE/COM object viewer, Mt.exe from the windows sdk, and regsvr42 from codeproject). But the manifest structure and necessary GUID's all vary between tools and posts.
Current status is that I receive a InvalidCastException "Unable to cast COM object of type System.__ComObject to interface type MyFunkyDllLib.FunkyDllControl. This operation failed because the QueryInterface call on the COM component for the interface with IID '{some guid}' failed due to the following error: Library not registered.
Can anyone confirm the correct syntax for the application and dll manifest files ? Online posts even vary on the name with some using sxs in the name....
Update1:
Whilst Joe's answer below did not work it did give me some better insights into reg free COM. In the properties of the Interop dll (the one that that is added to the project reference from the list of installed COM components on the dev machine) I changed the Isolated Property to True. This has the effect of making VS dump a copy of the COM dll (not the interop, it is embeded in the exe) to the bin\debug folder. VS also then creates a myapplication.exe.manifest.
In this manifest file is supposedly sufficent information for reg free com. I found other posts indicating success with this method but in my case I still ended up with the same InvalidCastException.
Reading over Samuel Jacks post again, I tried his method of creating both a manifest for the exe and the COM dll using the clsid information from the VStudio output manifest when Isolated=true. (I also deleted the <file/> section created by VS from the exe.manifest). After unregistering the COM from the registry I now have success ! The application starts and does not error.
Why this approach works and not the Isolated=true I have no idea because it is beyond my knowledge of manifests and assemblies.
However we are still not at the wizards castle yet Toto.
Now I'm back at the same issue I posted on this SO thread. However in this scenario unit tests are not involved. Just a plain console application with 10 lines of code. Works fine when in normal registered COM mode, but not in reg free mode.
After many hours of trial and error I finally got a solution to how to successfully implement RegFree COM.
Here is a full explanation incase it helps someone else.
I create a new .NET class library in VS
Right click references and select the COM components of interest.
(Note: for the COM to be visible in the list they must be registered
on the development machine. This can be acheived by using the
Regsvr32.exe tool included with windows. Calling "regsvr32
mycomdll.dll" registers it in the windows registry)
Right click the COM reference, goto properties, and then set Isolated=True. This has the effect of causing VS to output a .manifest file supposedly containing all the registry details necessary for a consuming .exe to know what resources to load instead of querying the registry. However in my case it was incomplete. Calls to Interop methods would work, but events from the COM component would not. See step 5 for my solution)
Build the project. The .manifest should appear in the build output.
Open the manifest in notepad or similar. Within the <assembly /> tag I needed to add a <comInterfaceExternalProxyStub /> tag with appropriate IID, tlbid and proxyStubClsid32 GUID elements. Elements of the manifest are documented on msdn. In my case the proxy/stub was proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/> which is the built in windows proxy. The iid and tlbid I originally discovered via Process Monitor whilst calling regsvr32. An easier and more reliable option I later discovered was to use a tool like SxS manifest maker as it added a second <comInterfaceExternalProxyStub /> that I originally did not have.
Create an exe project in VS and reference the previously built library.
Build the exe project.
Run regsvr32 /u mycomdll.dll. To remove all registry associations.
Run the exe. In my case calls to and events from the COM component in the class library worked perfectly.
Caveats: I dont know why VS does not include the <comInterfaceExternalProxyStub /> element automatically in the .manifest. At the time of writing the only way to automatically update the manifest was to add a post build Task in VS. In my case I copied the entire XML manifest into an XML in the class library project and then just overwrote the .manifest file in the build output.
Unit (integration) testing of the COM is inconsistent. Currently in my case calls to Interop methods work, but events do not. It has something to do with the fact that the Test Runner is not compiled with knowledge of the dependencies and therefore such are not present in the activation context.
You are probably missing a typelib declaration...but ignore that for now... Instead, do the following...
After playing with this on and off for a while, I decided that the easiest way to do it is using MSBuild and a GenerateApplicationManifest task. I've been using it with a unmanaged app, but I don't see why it would not work with a managed app. I say "app" ... because my app is managed but I have both COM libraries and .NET assemblies with ComVisible classes in them.
From your description it sounds like you are dealing with having COM and don't have to worry about consuming .NET assemblies from COM. You can google for MSBUILD and GenerateApplicationManifest to get an example MSBuild file.
So, I assume you will not need to populate the "Dependencies" attribute of the task. You will need to populate the "IsolatedComReferences" attribute with a list of your COM DLLs. They can be a simple semi-colon delimited list, but usually they are in "ItemGroup" declarations in the MSBuild project file. The COM DLLs need to be registered at the time you generate the manifest.
As for your RCW, there is nothing special you need to do. IMO, they don't need to be in the manifest. .NET has a way of finding them as long as they are in the same directory as your app/DLLs.
If you use MSBuild, you won't have to generate manifests for your COM DLLs... They probably already have manifests already... Usually, the wizards automatically generate manifests and embed them. The only manifest that will need the COM type information is the manifest you generate with MSBuild.
The whole point of the manifests used in this manner is to populate the manifest space with all the COM information that would be in the registry.

How to latebind COM event without interface

I need to late bind to a 3rd party VB6 COM object in a 3.5 C# application (to avoid version dependencies that we currently have). The dll that was provided is not consumable in most non-latebound ways due to some bug that causes errors when we try to consume it normally. Currently, we are using a custom VB6 wrapper that makes things VERY version specific, however I have found that I can use late-binding to access properties and methods. Now, I am trying to late-bind to events, however everything I have read says that I need to inherit from the COM wrapper's interface to create the event sinks that are needed. Here is one such article.
So, my question is whether it is possible to perform late-bound event handling without having any reference to the dll at compile time?
UPDATE
Here are the errors I have with the VB6 wrapper (Which is still being actively updated).
In OleViewer, I get
Could not decompile selected item Error loading type library/DLL.
TYPE_E_CANTLOADLIBRARY ($80029C4A)
In Visual Studio I get:
Could not determine the dependencies of the COM reference
"3rdPartyDLL". Error loading type library/DLL. (Exception from
HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY))
From here:
I found that the problem is caused when the IDL contains an importlib
to another project's .tlb typelib.
This seems to create a dependency between one dll and the other.
If dependant dll is missing OLEView refuses to display the dependent
dll, which also manifests itself by not allowing #import from C++
code.
Therefore I would look carefully at the COM dependencies of the DLL in question and make sure they are all registered as well.
It also goes on to add:
...because both dlls are co-dependent,
components from each interact (via interface declarations on method
signatures) and use #import from each others typelib.
Therefore, unless both target dlls are present, neither can be
rebuilt. As you can imagine, this causes a terrible problem when you
try to completely rebuild the project's from scratch.
I've experimented with separating the interface definitions into
smaller IDL files...
Edit: here's a recent example of this problem coming about (I believe). I had a C# library exported to COM. Modifications to that library were made which changed the interface of several classes, but the library GUID was not changed. Also see here about risks of AutoDual which was in use.
Here's the odd part - the VB6 DLL was rebuilt referencing the modified C# DLL. It compiled fine. no errors. But its typelib was corrupt - OleView couldn't open it, failing with TYPE_E_CANTLOADLIBRARY. Changing the C# DLL GUID was necessary to get the VB6 DLL recompiled successfully.
Clearly a pitfall of VB6 / C# interop.
The problem is most probably caused by the platform you are using. I just had a similar problem yesterday. Make sure that you are setting your project platform to x86 / x64 when you are late binding a x86/x64 COM type library.
The same applies to oleview. Use the x86/x64 version to view x86/x64 type libraries. (Possibly you need to install the x64 Windows SDK if you are on an x64 system to get the correct executeable).

Debugging a dynamically-loaded DLL from another AppDomain at Runtime

Ok, after resolving how to Hot-Load a DLL in a running App at Runtime (See my previous post), I have noticed that breakpoints inserted in the freshly loaded DLL are not hit.
Situation
I have a server Application that I want to avoid terminating/re-running every time I make a change to a Dynamically loaded DLL (by Reflection)
Goal
Here is what I am trying to do (I am aware this may not be possible per se) :
Run Application.exe
Load into it Process.dll in newAppDomain and run Process
Debug Process.dll
Unload Process.dll
Edit Process code, recompile Process.dll
Dynamically reload it in Application.exe
Debug Process.dll
etc...
Problem
I have noticed that when Application.exe is launched in Debug mode, code that is loaded from another AppDomain is unreachable by the debugger attached to Application.exe
(I guess If i just launch Application.exe directly from executable file, there is no way to get VS debugger to debug anything, inluding the newly loaded DLL)
Prossible workaround
A workaround (ugly) solution is to separate the "injection" of the DLL into the running App in a separate executable, that would be, then, monitorable by the VS Debugger
I mus admit I am a bit confused.
Any efficient, clean ideas ?
Since it may help others (as this was a top search result for me), I found that adding a reference to the DLL to the "other" project made it possible to debug the assembly being "injected." While I won't deploy my solution like this, it did allow me to at least debug the code being injected to resolve a problem with otherwise stable code. This suggests the IDE looks at references when determining assembly identity (or similar.)
In this scenario a DebugBreak() does nothing, the VS debugger will not be signaled without the reference being added. I did not test, but would imagine any other debugger would have been signaled just fine, so again this suggests the IDE is explicitly ignoring the signal (other DebugBreak()s work just fine.)
As a veteran .NET developer I have to say this problem is new for me, ie. I would say it's a safe bet that if we load Windows 2000, VS.NET 2001-2002 and this same test code that the breaks signal just fine.
Based on the OPs prior post it's most likely that the assembly being loaded is actually being loaded with a distinct identity, even if it's the same assembly but loaded from a different location/mechanism (for example) the CLR will identify it as a unique assembly, consequently so will the IDE.
Some readers may or may not find LoaderOptimization of value in certain scenarios where they are loading the same assembly between appdomains and notice the same assembly is being loaded multiple times.
HTH someone, I was stumped for about an hour. Thanks.
Does putting System.Diagnostics.Debugger.Break() in your DLL where currently you have breakpoints, throw a break correctly?
http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break.aspx
If not I'm inclined to agree with Sam, that unload is failing, or you're loading a different library than you think.

Reload a reference on the fly (C# .NET)

Ok, heres the rundown...
I have a service that is running and it references a dll that is changed a lot. This service is hopefully going to have multiple clients hitting it at once so it would be inefficient to shut it down and recomplile/reload with a new reference. I was wondering if there was anyway the program could pretty much auto-detect a dll with a later version and just drop the old one and load the new one without having to be shut down.
This can be difficult to achieve in a .Net application. Once a DLL is loaded into a particular AppDomain there is no way to unload the DLL from the AppDomain. The only way to get the DLL out of the process is to unload the AppDomain itself.
You could achieve what you're trying to accomplish by having the DLL loaded into a secondary AppDomain, and restarting that AppDomain with the new DLL when you detect a change. This also involves using some advanced shadow copy features though to allow the DLL to be deleted while being used by the process.
The only way to do this is move the code that uses the assembly to its own AppDomain. You can shutdown the AppDomain and restart it with the new assembly.
See this question: How to reload an assembly in C# for a .NET Application Domain?
The Managed Extensibility Framework will allow you to do this.

Categories

Resources