P/Invoke dynamic DLL search path - c#

I have an existing app which P/Invokes to a DLL residing in the same directory as the app itself.
Now (due to the fact that Canon produces one of the crappiest API's around) I need to support two versions of this API and determine at run-time which one I should use (old or new). Since the DLLs have the same name (the first one loads other DLLs with same names so just renaming the first one won't help me) I must keep them in different directories.
Hence my question: what options do I have to control what directory the DLL given in a DllImport declaration uses?
I guess I can start out by trying any of these two ideas:
1) Use "SetDllDirectory" to set my desired directory before doing the first P/Invoke and then reset it afterwards.
2) Load the desired DLL manually using "LoadLibraryEx" and hope that that will do the trick.
But are there any more ".NET:ish way" to try out first?
UPDATE: I realize that I can stuff all access to the DLLs in two separate .Net assemblies and then place each one of them in a separate directory with the corresponding API files. Then I can load the proper .Net assembly dynamically and the loading of the correct DLL whould happen automatically. Any reason that shouldn't work?
I can think of one: how would I go about debugging this stuff? It is possible to tell Visual Studio that an assembly (contained in my solution) shall be placed in a subdirectory and debugged from there?

My condolences, I've seen one of the APIs and it was indeed shockingly bad. The bigger problem is that you'll need to be able to convince Windows to find the DLL. They won't be in your .exe directory so the default won't work. Using SetDllDirectory() would work, using Environment.CurrentDirectory does too. LoadLibrary cannot work, the P/Invoke marshaller will use LoadLibrary itself.
If it is at all an option, you can use different names for the two P/Invoke declarations, using different arguments for the DllImport() constructor and using the EntryPoint attribute. Doesn't sound like that will fly.

I think 2nd option will work, but it will require to write a lot of code to manage dll loading in .net.
First one might work also, but i either don't like it.
Here is my suggestion: you can specify full path (and may be relative) in DllImport [DllImport(#"C:\dll\a32.dll"]

Your first option (P/Invoke with SetDllDirectory) is the option I personally prefer. Unfortunately, there isn't a ".NETish" way to handle loading native DLLs...which does make sense.

Starting with .NET Core 3.0, and also works with .NET 5 & .NET 6, you can use NativeLibrary.Load(string) to dynamically load DLLs at runtime, and use via P/Invoke normally.
Check this answer for more details: https://stackoverflow.com/a/69958827/211672

Related

Include TFS path in .NET assembly

When troubleshooting our applications, in many situations I cannot be sure what branch the assemblies originally come from, due to an imperfect release cycle and human error.
(We have quite a lot of different bugfix/feature/test/release branches etc. in our TFS).
The PDB-files can help sometimes, in a test environment at least, but sometimes they're missing or outdated / belong to assemblies from another branch.
So, I was trying to think of a way to include the source branch information inside the assembly directly.
Surprisingly, I could not easily find a straight forward way online to accomplish this.
My answer below explains my approach. I would be happy about feedback or alternative solutions.
In short: I created a custom attribute that I put intoAssemblyInfo.cs. Inside the attribute's constructor, the server path for the current assembly is queried from TFS and compiled into it.
It's basically a combination of the following:
Can I add custom version strings to a .net DLL?
How do I get the path of the assembly the code is in?
Get TFS mapped folder of a local sub folder of the solution?
(Note: I cannot post the actual source code due to company restrictions, but I think it's pretty straight forward.)
To get the attribute's value later is unfortunately not as easy as getting the version number from the DLL-file's properties, but at least it is possible now to get the information I need with minimum effort. (I use a small PowerShell script for that.)

MarkdownSharp errors in a Windows 8 app

I was trying to play with MardownSharp in a Windows 8 app. But I'm getting errors in the Mardown.cs file. It doesn't have System.Configuration and RegexOptions.Compiled.
You have two issues here.
System.Configuration is not one of the .NET namespaces available
for Windows Store applications. The good news is that it seems
to be used only in one of the overloaded constructors of the
Markdown class:
public Markdown(bool loadOptionsFromConfigFile)
Comment out that constructor (and the using statement). You could
rewrite that constructor to make use of app local storage which
would allow analogous functionality to a config file but not with
quite the same implementation. I suspect you may not be using that
overload anyway
The code makes heavy use of the Compiled flag for regular
expressions, which also isn't supported in this context. You should
be able to safely remove all references to that flag.
With those modifications I was able to at least compile the code, I didn't take it further.

Change resources in other Win32-dll/exe

There is a Resource Hacker program which allow to change the resources in the other win32(64) dll and exe files.
I need to do the same thing, but programmaticaly. Is it possible to do it using .Net framework? What is the good starting point to do it?
You must use the BeginUpdateResource, UpdateResource and EndUpdateResource WinApi functions, try this page to check the pinvoke .Net signature of these functions, also you can check this project ResourceLib.
The author points to another tool "XN Resource Editor" which comes with source code (although Delphi, not .NET).
This should be enough to see which functions being used and use the .NET equivalent of them.
Take a look at Anolis.Resourcer. It seems to be the thing you need
A ResHacker clone developed as a testbed for Anolis.Core and to replace ResHacker (because ResHacker doesn't support x64, XN Resource Editor (ResHacker's spiritual sequel) doesn't support multiple-language resources and crashes a lot, and other utilities rest cost actual money. It has a powerful yet simplified UI that doesn't duplicate commands or confuse the users with special-case handlers (which ResHacker and XN have in spades).
Note that none of these will work if you're dealing with signed EXEs or DLLs.
Well, as I see it is not easy task, so I'll use command line interface of Resource Hacker.

Can you extract dll version numbers from bundeled dlls

I need to bone up on my CLR compiling knowledge, so i'm going to speak in generalities... Appologies if I'm not being specific enough.
I'm working on an application that references a COM Library dll which has a number of dlls rolled into it. My question is, is it possible using Reflection to get a reference to the sub dll's assembly, namely to obtain the version number?
Or, if this question makes no sense, i'll try to rephrase.
No can do, you've got no way to find out what DLLs the COM server might be using. There isn't anything like Assembly.GetReferencedAssemblies() in unmanaged code. Process.Modules is about as close as you can get but there's no way to find out that the module you'll iterate was actually associated with the server instead of being loaded by, for example, OpenFileDialog or some obscure virus scanner crap.
If you know the DLL names and where they are located then you can use the FileVersionInfo class to obtain their unmanaged version resource info.

Forcing my app to use a specific version of a dll

I have application which needs to use a dll (also written by me) which has be independently verified by a government agency. We plan to modify the dll very rarely due to the re-verification which would be required. I want to prevent inadvertent modifications to this dll being picked up by my application. Is there a way to create a hash code for the dll and set up my application to only use this specific version.
This way if someone modified some of the code for the dll, when we build and run the application the app would fail to load the dll (because it had changed).
Any ideas/suggestions?
Cheers,
James
Using Strong Names does part of this and prevent anyone else tampering with your assembly, but doesn't stop you doing it by accident and then resigning.
We use an independent process to start our main application. Before launching the main app, the start up app MD5's all the assmeblies and compares them against a list of those it expects to see, if something has changed, the MD5 fails and the main app is not loaded.
If you really wanted compile time checking, you could probably write a pre-build step that did the same MD5 comparison and failed the build if it had changed.
I know that if you click on a dll Reference in your project you can select 'Specific Version' in its properties and set it to True, will this not do what you are after?
Phill
As Colin mentioned Strong Naming your assemblies will be the key as this includes both versioning & signing the assembly. The following couple of blog posts may help you with strong naming & versioning:
http://www.csharp411.com/net-assembly-faq-part-3-strong-names-and-signing/ (might be also worth reading the next part of this about the Global Assembly Cache)
http://philippetruche.wordpress.com/2008/08/12/net-assembly-versioning-lifecycle/

Categories

Resources