Trouble calling C# 32 bit Com from 64 bit C# application - c#

First thing, I know there are several articles about doing what I want to do. It is nothing special. But I have read numerous articles here and elsewhere and read multiple examples and I seem to get conflicting information as well as very mediocre success. I am asking people familiar with COM to be patient and help somebody who is just getting into COM for the first time.
I will explain what I believe to be what needs done based on my research and ask knowledgeable people to point out what I am doing wrong and help me fill in the knowledge gaps. My application uses third party 32-bit DLLs and 64-bit DLLs. There are a bunch of the 64-bit and only one 32-bit. This is why I am using a 64-bit application. If anyone cares, it is the Minolta kmsecs200.dll. The web site is clear that they do not have a 64 bit version.
The first step is to create the 32 bit COM wrapper. At this point, my sample code does not wrap anything. It just has one simple function. Here are the steps I took to create the DLL:
Create a new C#, windows, class Library (.Net Framework), .NET Framework 4
Name the project “SimpleCom”, rename the class and CS file to “JustOne”
In the project properties:
On Application Tab: Click "Assembly Information" and set “Make assembly COM-Visible”
On Build tab: Set Platform target to x86
On Signing tab: Select "Sign the assembly" and create a new Strong Name Key file named "StrongSimpleCom", no password protection
This is the JustOne.cs code:
using System.Runtime.InteropServices;
namespace SimpleCom
{
[Guid("EAA4976A-45C3-4BC5-BC0B-E47474C3C83F")]
public interface IJustOne
{
[DispId(1)]
string AddName(string name);
}
[Guid("0D53A3E8-E51A-49C7-BC0B-E47474C3C83F"),
ClassInterface(ClassInterfaceType.None)]
public class JustOne : IJustOne
{
public JustOne() { }
public string AddName(string name)
{ return "My name is: " + name; }
}
}
Register the 32-bit Assembly on the target machine:
From an administrative command prompt, navigate to the DLL folder
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe SimpleCom.dll /codebase /tlb:myTlb.tlb
I used /codebase because I do not yet know how to call the third party DLL if I put my DLL in GAC. I do not really understand what the tlb file is for once registered. I would like to know if someone can tell me.
At this point, the COM object shows up in Visual Studio but I can not call it that way and I understand that. It just tells me it is registered at least in some sense of the word.
So I think I should be able to Invoke the 32 bit C# DLL that I wrote from a 32 bit C# application. But I just can not figure out how to do it. I can't seem to even find a good example of using invoke. I would really appreciate help on how to invoke "IJustOne" in a simple application.
Once that works, I can add some registry entries to make it out of process and make the 32 bit application into a 64 bit application. Here is one of the ways I have heard to modify the registry to make the 32 bit COM oup of process and use the DLLhost as the surrogate.
Techtalk.gfi.com method from 2009*
Navigate to: HKEY_CLASSES_ROOT\WOW6432Node\CLSID{EAA4976A….}
• Add “AppID” with value set to Guid
Navigate to: HKEY_CLASSES_ROOT\WOW6432Node\AppID
• Create a new key using the Guid as the name
• In the key, Add “DllSurrogate” with no value
Navigate to: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID
• Create a new key using the Guid as the name
Again I am having trouble finding good straight forward examples of how to invoke the COM object. I have created a C# DLL wrapper that I can directly include in a simple C# 32 bit application so I am comfortable with wrapping the unmanaged 3rd party DLL. I would like to know how to ensure my wrapper DLL can find their DLL.
I do not know what I am doing wrong with registering the DLL and I do not know how to invoke it in a 64 bit application, or a 32 bit for that matter. I appreciate any assistance. I have spent several days trying to chase this down but in the end, my knowledge base is just not strong enough. But a recap of the big picture:
I am using 3rd part 32 bit unmanaged DLL. I need to call it from my 64 bit C# application. I believe the way to do it is wrap it in a managed C# 32 bit DLL wrapper and make it an out of process COM object the uses DLLhost as the surrogate.
Thanks again,
Dave

Simon pointed me in the right direction above. My DLL was registered just fine. I added it as a component through component services and everything worked after that. Thank You Simon.

Related

How to create a program that converts 1 dll file into another dll file?

So I want to make a mod installer that doesn't contain any game code but still installs the full modded dll. Everyone with the official game always starts with the same dll (written in C# and unity).
My initial idea was to decompile using ILspy (as we only have access to .dlls) and recompile but that doesn’t work (build errors). I have thought about using something like winMerge to save changes between .dlls but not 100% sure how to use it and my final idea is to convert the whole binary from storred file into a normal number and find the difference between the 2 files.
Anyone have any idead of whats the best way to go about this?
It been a while but i want to get back to how i solved this. I ended up making an installer that compares the different in hash (binary) between 2 binary files and creates a patch. Now this patch can then be applied in the installer itself to make the output dll! Here is the github if anyone is interested - https://github.com/dan771/Snowtopia-Mod-Installer
My best luck has come from ildasm / patch / ilasm. You can do essentially the same thing with Mono.Cecil. It's quite automatable even in the face of an obfuscated dll provided that the original dll has no native code.

Creating .Net Wrappers for Windows API and COM DLLs

Let me start by saying that I don't know what I don't know at this point, so rather than specific answers, I'm also looking for better questions to ask, I think. My .Net/C# is solid enough, and my C/C++ is meh.
Lately, I'm finding that there are no libraries in the standard .Net framework to accomplish certain tasks, and while it's easy enough to download a third party library, I'd like to understand how to do it myself if one doesn't already exist.
In one recent case, I need to deal with MIDI in windows at a relatively low-level, and I accidentally found out that "winmm.dll" is the library I'll need to use by downloading a .net wrapper for MIDI and browsing through the source. I understand that I'll have to make a wrapper class and do the whole P/Invoke thing to make that happen.
The next thing I did was to search for documentation on the Windows API to figure out what was going on in the mystery box of "winmm.dll," and to my delight, there was a whole Windows SDK that I was able to download and read through. I went through the "getting started" section of "Windows Development" which covered some of the basics via C++. It talked a bit about COM, windows header files, and I know enough C++ to get the gist.
Now, I need help connecting the dots on a few issues:
1) The Windows SDK, so far, seems to suggest that I want to program to specific header files rather than the dlls themselves, but the .net wrappers I've found typically point to a specific .dll rather that a header file...
/// <summary>
/// Returns the number of MIDI input devices on this system.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711608(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern UInt32 midiInGetNumDevs();
I was under the impression that a header file and DLL needed to be in the same folder, but the windows SDK includes a folder with all the windows header files, and no DLLs (I'm guessing the registry comes into play here for mapping to specific libraries?)? How do those header files eventually get mapped to actual libraries, and why does it seem like I don't even need to deal with header files to create a .Net wrapper?
2) I can't seem to find documentation on winmm.dll, but I have found references to the functions I'll likely need in the "Windows API" list in the Windows SDK, and I'm pretty sure that the code for those functions are in winmm.dll. How do I find the documentation for the specific libraries I'll need to begin creating my wrapper? If I didn't know that I was going to need winmm.dll to access windows MIDI functionality, how could I have figured that out myself?
3) Some DLLs are COM, some are plain windows DLLs, some are .net DLLs... how can I tell the different going forward? It seems that creating wrappers for the former two would require a different approach.
4) There is no page on MSDN for "Winmm.dll" listing all of its API, and I assume there's a good and practical reason for that, but I'm not sure what it is? I'm used to .Net land where I can figure out what a library does and how to use it almost without effort.
Thanks in advance for any insights.
The bible on this is Adam Nathans excellent book '.Net and COM the complete interoperability guide'
Includes PInvoke and several audio-type examples
1) The windows API documentation includes the header, library, and dll file for each method/enum/etc. I just didn't scroll down far enough when I read through to notice this. A header file doesn't necessarily have to be in the same directory as the dll; its contents are simply copy/pasted into the .c file when the program is compiled. The part I was missing here was the linking stage of compilation which I read about here
2) The documentation was there--I just had to look for it a little bit harder.
3) How can I detect the type of a dll? (COM, .NET, WIN32)
4) The api for audio could theoretically span multiple dlls, so the best course of action is to find the API documentation, find the methods you want to wrap, then figure out what dlls those methods are in, and then import each of those DLLs.

need unmanaged dll version that is being imported with DllImport

I am working on an application that imports an unmanaged dll into C#. It has a wrapper class that loads the methods so it can be called. The methods work fine in the program from the dll. I want to add saving the version of the dll that is being used. I found that I need to use FileVersionInfo.GetVersionInfo("my.dll") thanks to C# getting version of unmanaged dll. However, when running this function it exceptions saying it can't find "my.dll". The dll is in a folder off the root of the c:. This folder is in the PATH and according to http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx#search_order_for_desktop_applications it should find it.
Knowing that the my.dll file is loaded and working why can't I also call GetVersionInfo() inside the same wrapper class and find my.dll so I can get the same file's version number? Thanks for the help as I have been looking for a couple of days.
It requires the full path, it won't search for the DLL. That's too risky, the Windows search rules for a DLL are intricate and subject to configuration. If you need to do this before pinvoking any function then the best way is by pinvoking SearchPath(). Which uses the same algorithm as LoadLibrary uses if you set the first argument to null.
If you need to do this after pinvoking a function then the best way is by using the loaded DLL. Iterate Process.GetCurrentProcess().Modules to retrieve the ProcessModule.FileName.
From MSDN, the parameter for GetVersionInfo is:
The fully qualified path and name of the file to retrieve the version
information for.
So it's pretty clear. You need to pass the full path, as it seems this function relies on it. Otherwise it will most likely look for the file in the current directory (so your app's dir).
As a side note, keeping the native DLL in C:\ is bad practice.
You should store it in your application's folder. Then this function would work and your app would be more self contained. No files spread around the disk.
Of course, this is true unless you have a good reason for storing it in the root of your C drive.

rfid programming

I have 2 readers for RFID and some cards (from a Chinese company called "Daily RFID"). They
kind of work because they came with some demo software written in Delphi that reads the id of the card (myfare compatible, ISO14443A). The problem is that if I try to use the demo to write to them, it doesnt seem to work.
They have another demo written in C#, it compiles and runs, but when click on Connect, I get this error:
Unhanded exception.. unable to load
DLL 'BasicB.DLL'
So I put the DLL in %WINDOWS%/system32, but when I tried to run regsvr32 BasicB.dll, I got another error:
the module "BasicB.dll" was loaded but
hte entry-point DllRegisterServer was
not found. Make sure that "BasicB.dll"
is a valid DLL or OCX file and then
try again
I have written to the company but got no response.
I program in Objective-C, so I kind of understand c#, but how to make these cards work?
Should I continue with Delphi, and try to write to them with it? Or should I continue trying with C#? Either way, would I have to write the code to read/write to them, or is there any software to work with these modules?
You only use regsvr32 to register ActiveX (COM) DLLs. The DLL you're trying to register isn't one.
Putting the DLL in the %WINDOWS%\system32folder should be enough. In fact, it can be in your applications folder or anywhere on the PATH.

Cannot create ADODB.Connection with complicated programming chain

Ok so this is a really complicated problem, I will try my best to explain.
We have a c++ application which communicates with Sql Connection like so:
CoCreateInstance(_T("ADODB.Connection"))
This works fine.
We recently made all of our backend code into a Com Object. If I write a Vb program to load our Com Object and do some database operations everything works fine, CoCreateInstance(_T("ADODB.Connection"))
still works.
We use fitnesse for testing so I wrote a fixture that:
1) Takes a string of vb code input into an html page.
2) compiles the vb code
3) runs the vb code that uses our Com Object.
* fitnesse is a java application so the code path travels through Java as well.
Now when any operation touches the database the Com Object hits an exception. Uses message boxes, and removing code I narrowed the problem down to this line of code:
CoCreateInstance(_T("ADODB.Connection"))
normally the return code is 0, but with this chain of code calling code I get the return code: 800401F3 which says that it cannot find the object to load.
I am pulling my hair out trying to figure out whats going on. Any bit of insight would be greatly appreciated.
It is telling you that it cannot find the ProgId in the registry. That's not very healthy, it is a pretty standard component on any Windows install. Verify this, fire up regedit.exe and navigate to HKLM\Software\Classes\ADODB.Connection
If that is missing then you need to install the dbase providers on that machine. Download the MDAC 2.8 installer from Microsoft and run it. If it is not missing then you have a more mysterious problem, perhaps something to do with this being a 64-bit operating system. Look in HKLM\Software\Wow6432Node then. Get additional diagnostics by using the SysInternals' ProcMon tool to see what it is poking at in the registry.
As an alternative, you don't say whether your com "object" is a .dll. If it is, then make sure it is either "self-registering" or you'll need to run this at the command prompt.
regsvr32 myobject.dll
If it's an exe with COM objects, register the objects by running the program with the "/RegServer" command line option like this:
myobject.exe /RegServer
HTH

Categories

Resources