How to make my dll loadable from codebase only?
Asked Answered
L

2

25

My project(some kind of processing engine) is separated into 2 dlls: one with interface declarations and one with functionality.Usually the project is used by external Delphi project via COM technology.

Lets say my program slices fruits. External delphi programm creates Fruit object and fills its properties: weight (int), Name (string) and ProgressUpdater (of type IProgressUpdater which is declared in second dll with interfaces).After this exst programm creater Slicer, makes Slicer.AddFruit(newFruit) and calls Slicer.Slice().

Nothing special. In real life delphi project is Outlook addin. But here is the problem - sometimes some VSTO addins makes Outlook work in "shadow copy files" mode, so when delphi project starts and creats Slicer object, our c# assembly will be put in temp folder and assembly will be created with this local path. Well... this is still not an issue. But the problem is when delphi project creates newFruit and then passes ProgressUpdater object, in my Slicer assembly I can not get external ProgressUpdater: "Return argument has an invalid type", but still can get field with simple types(Weight, Name).

It only happens when shadowCopyFiles mode is on. So my guess is - external ProgressUpdater's assembly and Slicer assembly are placed to different places, so they can not be passed. My question is how to avoid my dll being "shadow copied"? Or is there some different solution?

Lobster answered 17/8, 2015 at 8:24 Comment(11)
I'm not very familliar with COM technology, but shouldn't assemblies be taken from GAC? Like hereDyann
Hmm, you are the victim of another addin's questionable practices. Not much you can do about that if you don't have a telephone number. But one thing, use the GAC. Always a good idea when you write ComVisible assemblies.Discourteous
@HansPassant the problem is my assembly is already registered in GAC. But in one case Assembly.GetExecutingAssembly().Location; shows codebase path (the path where it was registered with regasm for COM interop). but in another (after that VSTO add-in) - some temp path on system drive. I think I will not have such problem if I can force .net to load my assembly only from codebase path.Lobster
That's not possible, GAC assemblies are never shadow-copied. You'll need to stop talking about fruit slicing and provide hard facts instead of stories and guesses. Show the content of the Excel.exe.config file and show the trace you get from Fuslogvw.exe when you log all binds.Discourteous
@HansPassant Quite fairly! Previously when I was calling Gacutil.exe with key /ldl I was able to see both my dlls in the list of loaded assemblies. But strange thing - no successfully probing for assemblies in GAC ( I see it using FUSLOGVW utility you advised me)... So I decide to install my assemblies to GAC using full path and that did the trick! Problem is solved now, many thanks.Lobster
@HansPassant I think you can post an answer like "Use GAC, GAC assemblies are never shadow-copied" because actually this points me where to find solution, and grab your bounty.Lobster
Don't forget to keep in mind that using the GAC can give you some other problems...Middlemost
Firstly OP can you post how you found the solution and what it is? eg I used the GAC as GAC assemblies are never copied. Secondly @Middlemost your comment is completely useless, if you are going to say using the GAC can give you some problems (when it is being accepted as the answer) - at least say what the other problems are?Okie
@Jermy, The GAC has real issues and should never have been invented. The recommendations from Microsoft is don't use it since almost noting you create needs to be globally accessible by all applications on the computer. to quote the documentation "As a general guideline, keep assembly dependencies private, and locate assemblies in the application directory unless sharing an assembly is explicitly required." msdn.microsoft.com/en-us/library/yf1d93sz(v=vs.110).aspxMiddlemost
Is your "functionality dll" referencing you "interface dll" ? If so you could perhaps solve this problem by requiring specific version for references. If not already done check your references target "Specific version". You could also maybe use strong name for all your dll.Eradis
@Koresh yes, but my dll has no "specific version" property , i think because both of them are COM dlls. They both are strong name.Lobster
L
2

So as a result I still have no answer for exact question. But the problem is solved (thanks to HansPassant) by using GAC, because assemblies at GAC will be never shadow-copied (actually linker will always first probe assemblies in GAC and then in other places).

Possible answer to the question is to go currentDomain.AssemblyResolve way, but I could not apply this solution to dll which contains public interfaces(types) only. Maybe it will be suitable solution for some cases.

Lobster answered 27/8, 2015 at 7:48 Comment(0)
L
1

You can use reflection to load DLL dynamically from any location you want. If you can go this way, I can provide further code for loading DLLs.

Laynelayney answered 29/8, 2015 at 8:56 Comment(2)
Yes, pls provide an example. My situation is that my dll contains only interfaces(no methods) and will be used by Delphi via COM. So how can I guarantee that when guy on Delphi end performs MyComDll.IProgressUpdater it will be load from codebase?Lobster
@Lobster to load assembly via reflection you can do something like this: Assembly.Load(File.ReadAllBytes(path)) - only once before the first call. You can also check out my article: wojciechkulik.pl/csharp/embedded-class-libraries-dll (it's about something else, but maybe some part of it will be useful).Bolick

© 2022 - 2024 — McMap. All rights reserved.