COM Interop with ActiveX nightmare...

  • Thread starter Thread starter Wizfrog
  • Start date Start date
W

Wizfrog

Hello and thanks for reading...

I am using a C++ unmanaged ActiveX (ocx) that allows me to read a
specific file format, and get data out of those.

I use C# .Net.
To use the ActiveX, I simply added it to my toolbox, and create an
instance in a form. Until there, all is good. I can read files, get
the data etc... even if I need to 'copy' the data from the unmanaged
side to the managed side.

Now where I hit a rodblock is when I try to copy the data back to the
ActiveX:
I need to pass a float[] to the COM object to then 'save' the data in
the original (proprietary) file format.
The ActiveX function in C++ is defined as

PutValue(int dataID, float* parray, uint size)

however in C#, the converted function by the ActiveX importer becomes

PutValue(int dataID, ref float parray, int size)

All the research I've done to figure out a solution leads me to
conclude that I need to Marshal the float* parameter into "IntPtr"

That's where I am stuck:
The imported library is already in managed C#, and shows as non-
editable 'MetaData', and it doesn't seem like I can override an
Interface declaration. So I don't see a way to Marshal the parameter.

So I tried to use COM interop directly, by calling the ActiveX.ocx
using [DllImport]

[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#3")]
[return] int ID public static extern int Load(string
filename);

[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#60")]
public static extern int PutValueEx(int ID, IntPtr pt, int
size);

I first had to figure out the entry point # in order to access the
functions, but got so far.
Now, calling the ocx directly, I get "Attempted to read or write
protected memory" error when trying to load the file.

Obviously there is something else that's being done when importing an
ActiveX through the toolbox.


I also tried to import the library directly, using AXIMP.EXE
It created 2 DLLs. One seems to be the managed interop library I can
get the code from if I use the "/source" tag, the other is the actual
COM DLL.

Problem, if I reference the 1st DLL, or import the source in my
project, I see that it calls the second DLL that includes the actual
functions.
So I tried to use [DllImport] directly on that second DLL, but there
it is not able to find an entry point.

Using LibDump, I could see the type library information from the ocx
file, but I can't see anything one either of the 2 DLLs generated,
which leads me to think they are missing the interface definition.

So, I'm trying to figure out a way out of this mess:
Either by finding a way to override the interface in the imported
ActiveX control from the toolbox, and marshal the paramter properly
Or
By finding the way to generate the DLL properly so I can import it
directly with [DllImport]
Or
figure out what is wrong when calling the .ocx file directly with
[DllImport]

Any suggestion would be greatly appreciated.


Note:
1) I do not need any of the 'control' form features, only to load the
file, read the data, put data back in and save it.
2) I did ask the vendor for the file format, so I could read/write it
directly in C#, but I didn't get anywhere. Would have been my
preference but this is not an option.
 
I dont think the ActiveX would be exporting the method directly via ordinal,
they typically provide an interface though which you call the methods.

You could try declaring the interface yourself and then getting an instance
to that interface by using CoCreateInstance via p/Invoke (or
CoGetClassObject and then creating the instace).

---------
- G Himangi, LogicNP Software http://www.ssware.com
Shell MegaPack: Drop-In GUI Controls For Windows Explorer Like File And
Folder Browser Functionality
CryptoLicensing: Add licensing, copy-protection and activation to your
software
EZNamespaceExtensions: Fast and painless development of namespace extensions
EZShellExtensions: Rapid development of all shell extensions,explorer bars
and BHOs
---------


Wizfrog said:
Hello and thanks for reading...

I am using a C++ unmanaged ActiveX (ocx) that allows me to read a
specific file format, and get data out of those.

I use C# .Net.
To use the ActiveX, I simply added it to my toolbox, and create an
instance in a form. Until there, all is good. I can read files, get
the data etc... even if I need to 'copy' the data from the unmanaged
side to the managed side.

Now where I hit a rodblock is when I try to copy the data back to the
ActiveX:
I need to pass a float[] to the COM object to then 'save' the data in
the original (proprietary) file format.
The ActiveX function in C++ is defined as

PutValue(int dataID, float* parray, uint size)

however in C#, the converted function by the ActiveX importer becomes

PutValue(int dataID, ref float parray, int size)

All the research I've done to figure out a solution leads me to
conclude that I need to Marshal the float* parameter into "IntPtr"

That's where I am stuck:
The imported library is already in managed C#, and shows as non-
editable 'MetaData', and it doesn't seem like I can override an
Interface declaration. So I don't see a way to Marshal the parameter.

So I tried to use COM interop directly, by calling the ActiveX.ocx
using [DllImport]

[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#3")]
[return] int ID public static extern int Load(string
filename);

[DllImport(@"MyACTIVEX.ocx", EntryPoint = "#60")]
public static extern int PutValueEx(int ID, IntPtr pt, int
size);

I first had to figure out the entry point # in order to access the
functions, but got so far.
Now, calling the ocx directly, I get "Attempted to read or write
protected memory" error when trying to load the file.

Obviously there is something else that's being done when importing an
ActiveX through the toolbox.


I also tried to import the library directly, using AXIMP.EXE
It created 2 DLLs. One seems to be the managed interop library I can
get the code from if I use the "/source" tag, the other is the actual
COM DLL.

Problem, if I reference the 1st DLL, or import the source in my
project, I see that it calls the second DLL that includes the actual
functions.
So I tried to use [DllImport] directly on that second DLL, but there
it is not able to find an entry point.

Using LibDump, I could see the type library information from the ocx
file, but I can't see anything one either of the 2 DLLs generated,
which leads me to think they are missing the interface definition.

So, I'm trying to figure out a way out of this mess:
Either by finding a way to override the interface in the imported
ActiveX control from the toolbox, and marshal the paramter properly
Or
By finding the way to generate the DLL properly so I can import it
directly with [DllImport]
Or
figure out what is wrong when calling the .ocx file directly with
[DllImport]

Any suggestion would be greatly appreciated.


Note:
1) I do not need any of the 'control' form features, only to load the
file, read the data, put data back in and save it.
2) I did ask the vendor for the file format, so I could read/write it
directly in C#, but I didn't get anywhere. Would have been my
preference but this is not an option.
 
Someobdy suggested this:

You'll have to do some manual work to change the parameter type from ref
float to float[]. The procedure is described here
http://msdn.microsoft.com/en-us/library/ek1fb3c6.aspx

Which i followed but not I am stuck with this:

I managed to generate the tlb file with tlbimp, Changed the MSIL,
reassembled and got a DLL

now I'm trying to use it and even though I added it as a reference, I get a
'FileNotFoundException' when running.

it is looking for a filename:
"myactivexassembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
which is not the filename, so I am guessing it is looking up the DLL in the
registry and can't find it.

I tried to register the dll with regsvr32, but it says "no entry point was
found, cannot register dll.

I am told that to be registered, it needs to be a COM object, but obviously
after changing the MSIL, it is not, I guess.

So what else do I need to do from here?

also, if I wanted to use it as an actual activex, to import in my toolbox
and use in a form, how do I generate an ActiveX?
the dll generated is not an activeX, and cannot be imported in the toolbox.

Thanks for help.
 
Back
Top