Some interop Questions - C# to unmanaged DLL

G

Greg Roberts

Hi

1. Is there any way to access a static function in a class via the
[DllImport] syntax ?
e.g. in C#

[DllImport("testum.dll")]
static extern void MyClass::MyFunc();

The compiler does not like the class reference ...
Of course a pure static function is OK ...

2. When the C# is run, i get a
"The specified module could not be found. (Exception from HRESULT:
0x8007007E)"
for the DLL, even though testum.dll has been exported at build time to the
same directory as the C# program.
Dependency Walker shows the function is in testum.dll .
3. Can specific [marshall.xxxx] be done on the return value ? I have seen
examples showing this for the
the function arguments, but have not seen one with marshalling on the return
value below the [DLLImport ...] statement.

Thanks in advance

NB: I should mention that the C# program is an actual VS2005 team system
test project
 
W

Willy Denoyette [MVP]

| Hi
|
| 1. Is there any way to access a static function in a class via the
| [DllImport] syntax ?
| e.g. in C#
|
| [DllImport("testum.dll")]
| static extern void MyClass::MyFunc();
|
| The compiler does not like the class reference ...
| Of course a pure static function is OK ...
|

No, you can't call C++ class methods from C#, you can only call non member
functions.

| 2. When the C# is run, i get a
| "The specified module could not be found. (Exception from HRESULT:
| 0x8007007E)"
| for the DLL, even though testum.dll has been exported at build time to the
| same directory as the C# program.
| Dependency Walker shows the function is in testum.dll .
| >> Tips on what to do ?
|

That indicates that your DLL or one of it's dependecies aren't found
(probably a dependency).
When using VC8 (vs2005) make sure you embed the assembly manifest, or you'll
have to statically link the CRT, failing to do one of these will throw the
same error when loading the DLL.

| 3. Can specific [marshall.xxxx] be done on the return value ? I have seen
| examples showing this for the
| the function arguments, but have not seen one with marshalling on the
return
| value below the [DLLImport ...] statement.
|

[return:MarshalAs(UnmanagedType.Bool)] int someFunction(....)

Check MSDN for details on PInvoke marshaling.

Willy.
 
G

Greg Roberts

Thanks for the feedback

I am having trouble trying to get the manifest part correct.

I have found SampleC.dll.intermediate.manifest & SampleC.dll.embed.manifest
and seem to have successfully added a reference
in the C# project refs to SampleC.dll.embed.manifest but now get link
errors

Warning 1 Assembly '..\debug\SampleC.dll.embed.manifest' has mismatched
identity 'SampleC', expected file name: 'SampleC.manifest'. UnitTestofCSharp

My unmanaged settings manifest line is
/nologo /identity:"SampleC" /out:".\Debug\SampleC.dll.embed.manifest"
/notify_update

The object browser for the SampleC entry can see everything

The unmanaged DLL is a non MFC dynamic linked library

Thanks


Willy Denoyette said:
| Hi
|
| 1. Is there any way to access a static function in a class via the
| [DllImport] syntax ?
| e.g. in C#
|
| [DllImport("testum.dll")]
| static extern void MyClass::MyFunc();
|
| The compiler does not like the class reference ...
| Of course a pure static function is OK ...
|

No, you can't call C++ class methods from C#, you can only call non member
functions.

| 2. When the C# is run, i get a
| "The specified module could not be found. (Exception from HRESULT:
| 0x8007007E)"
| for the DLL, even though testum.dll has been exported at build time to
the
| same directory as the C# program.
| Dependency Walker shows the function is in testum.dll .
| >> Tips on what to do ?
|

That indicates that your DLL or one of it's dependecies aren't found
(probably a dependency).
When using VC8 (vs2005) make sure you embed the assembly manifest, or
you'll
have to statically link the CRT, failing to do one of these will throw the
same error when loading the DLL.

| 3. Can specific [marshall.xxxx] be done on the return value ? I have
seen
| examples showing this for the
| the function arguments, but have not seen one with marshalling on the
return
| value below the [DLLImport ...] statement.
|

[return:MarshalAs(UnmanagedType.Bool)] int someFunction(....)

Check MSDN for details on PInvoke marshaling.

Willy.
 
W

Willy Denoyette [MVP]

You don't have to set a reference to the manifest file, all you have to do
is set "Embed Manifest " to true in your project settings(see Manifest
Tool - Input And Output).
The manifest tool (MT.EXE) will embed the manifest into the assembly when
done.

Willy.


| Thanks for the feedback
|
| I am having trouble trying to get the manifest part correct.
|
| I have found SampleC.dll.intermediate.manifest &
SampleC.dll.embed.manifest
| and seem to have successfully added a reference
| in the C# project refs to SampleC.dll.embed.manifest but now get link
| errors
|
| Warning 1 Assembly '..\debug\SampleC.dll.embed.manifest' has mismatched
| identity 'SampleC', expected file name: 'SampleC.manifest'.
UnitTestofCSharp
|
| My unmanaged settings manifest line is
| /nologo /identity:"SampleC" /out:".\Debug\SampleC.dll.embed.manifest"
| /notify_update
|
| The object browser for the SampleC entry can see everything
|
| The unmanaged DLL is a non MFC dynamic linked library
|
| >> Any futher tips of an URL of this working sucessfully would be
| >> appreciated
|
| Thanks
|
|
| | >
| > | > | Hi
| > |
| > | 1. Is there any way to access a static function in a class via the
| > | [DllImport] syntax ?
| > | e.g. in C#
| > |
| > | [DllImport("testum.dll")]
| > | static extern void MyClass::MyFunc();
| > |
| > | The compiler does not like the class reference ...
| > | Of course a pure static function is OK ...
| > |
| >
| > No, you can't call C++ class methods from C#, you can only call non
member
| > functions.
| >
| > | 2. When the C# is run, i get a
| > | "The specified module could not be found. (Exception from HRESULT:
| > | 0x8007007E)"
| > | for the DLL, even though testum.dll has been exported at build time to
| > the
| > | same directory as the C# program.
| > | Dependency Walker shows the function is in testum.dll .
| > | >> Tips on what to do ?
| > |
| >
| > That indicates that your DLL or one of it's dependecies aren't found
| > (probably a dependency).
| > When using VC8 (vs2005) make sure you embed the assembly manifest, or
| > you'll
| > have to statically link the CRT, failing to do one of these will throw
the
| > same error when loading the DLL.
| >
| > | 3. Can specific [marshall.xxxx] be done on the return value ? I have
| > seen
| > | examples showing this for the
| > | the function arguments, but have not seen one with marshalling on the
| > return
| > | value below the [DLLImport ...] statement.
| > |
| >
| > [return:MarshalAs(UnmanagedType.Bool)] int someFunction(....)
| >
| > Check MSDN for details on PInvoke marshaling.
| >
| > Willy.
| >
| >
|
|
 
G

Greg Roberts

Willy,

I sorted the manifest out and it links OK, Still getting the same error

Interesting if i rename the C dll so it won't be found, i get the same error
!!

At this stage i think my only hope is finding someone with a simple ZIPed
C# / C DLL sample which works to reverse engineer why it works .

I have used the DllImport before myself to get at OS Win32 DLL functions
no probs but not my own DLL ?

Thanks

Willy Denoyette said:
You don't have to set a reference to the manifest file, all you have to do
is set "Embed Manifest " to true in your project settings(see Manifest
Tool - Input And Output).
The manifest tool (MT.EXE) will embed the manifest into the assembly when
done.

Willy.


| Thanks for the feedback
|
| I am having trouble trying to get the manifest part correct.
|
| I have found SampleC.dll.intermediate.manifest &
SampleC.dll.embed.manifest
| and seem to have successfully added a reference
| in the C# project refs to SampleC.dll.embed.manifest but now get link
| errors
|
| Warning 1 Assembly '..\debug\SampleC.dll.embed.manifest' has mismatched
| identity 'SampleC', expected file name: 'SampleC.manifest'.
UnitTestofCSharp
|
| My unmanaged settings manifest line is
| /nologo /identity:"SampleC" /out:".\Debug\SampleC.dll.embed.manifest"
| /notify_update
|
| The object browser for the SampleC entry can see everything
|
| The unmanaged DLL is a non MFC dynamic linked library
|
| >> Any futher tips of an URL of this working sucessfully would be
| >> appreciated
|
| Thanks
|
|
| | >
| > | > | Hi
| > |
| > | 1. Is there any way to access a static function in a class via the
| > | [DllImport] syntax ?
| > | e.g. in C#
| > |
| > | [DllImport("testum.dll")]
| > | static extern void MyClass::MyFunc();
| > |
| > | The compiler does not like the class reference ...
| > | Of course a pure static function is OK ...
| > |
| >
| > No, you can't call C++ class methods from C#, you can only call non
member
| > functions.
| >
| > | 2. When the C# is run, i get a
| > | "The specified module could not be found. (Exception from HRESULT:
| > | 0x8007007E)"
| > | for the DLL, even though testum.dll has been exported at build time
to
| > the
| > | same directory as the C# program.
| > | Dependency Walker shows the function is in testum.dll .
| > | >> Tips on what to do ?
| > |
| >
| > That indicates that your DLL or one of it's dependecies aren't found
| > (probably a dependency).
| > When using VC8 (vs2005) make sure you embed the assembly manifest, or
| > you'll
| > have to statically link the CRT, failing to do one of these will throw
the
| > same error when loading the DLL.
| >
| > | 3. Can specific [marshall.xxxx] be done on the return value ? I
have
| > seen
| > | examples showing this for the
| > | the function arguments, but have not seen one with marshalling on
the
| > return
| > | value below the [DLLImport ...] statement.
| > |
| >
| > [return:MarshalAs(UnmanagedType.Bool)] int someFunction(....)
| >
| > Check MSDN for details on PInvoke marshaling.
| >
| > Willy.
| >
| >
|
|
 
W

Willy Denoyette [MVP]

| Willy,
|
| I sorted the manifest out and it links OK, Still getting the same error
|
| Interesting if i rename the C dll so it won't be found, i get the same
error
| !!
|

That's normal, the error is returned when the DLL (called a module) or one
of it's dependencies is not found.
As your native DLL is dynamically linked with the CRT msvcr80.dll (or it's
debyg version msvcr80d.dll), this one becomes a dependency. It's also
important to know this when you move your DLL to another box which doesn't
have VS2005 installed, the DLL will fail to load the dependent msvcr80.dll
as it's not available.

| At this stage i think my only hope is finding someone with a simple ZIPed
| C# / C DLL sample which works to reverse engineer why it works .
|

I think, the easiest is to create a simple C# program and a native dll and
build both from the command line.


[CPP]
// simple.cpp
#include <windows.h>
#include <cstdio>
extern "C" {
__declspec( dllexport ) int __stdcall Empty();
}

int __stdcall Empty() {return 0;}

[CS]
// usesimple.cs
[DllImport("simple.dll")]
extern static int Empty();
static void Main()
{
Console.WriteLine(Empty());
}

[build.cmd]

cl /LD /MD /EHsc simple.cpp
mt -manifest simple.dll.manifest /nologo /outputresource:"simple.dll;#2"
del simple.dll.manifest
csc /t:exe usesimple.cs

Willy.
 
G

Greg Roberts

Willy thanks for perservering ..

Latest update

I built a simple vc8 testc.exe console program and could load and use the
samplec.dll i have talked about .

I then used filemon.exe to trace file activity, and to my suprise the
execution path tries about 30 odd
directories (some often repeated) for the samplec.dll but NONE of them where
the directory
that MSTestProject.dll and SampleC.dll lived in !! These are in a common
debug or release directory

Go figure !!

It would seem the process starts from "UnitTesting.vshost.exe" which loads
and calls the MSTestProject.dll
which when running can't find samplec.dll

SO as a temp. measure i added the debug directory to the windows PATH env.
and restarted the vs2005 IDE

Now the process finds samplec.dll and now i have the new error set ....

"A first chance exception of type 'System.DllNotFoundException' occurred in
MSTestProject.dll

Additional information: Unable to load DLL 'SampleC.dll': This application
has failed to start because the application configuration is incorrect.
Reinstalling the application may fix this problem. (Exception from HRESULT:
0x800736B1)"

I seem to have the correct manifest settings ..

NB: While in debug and changing exceptions to always thrown, several of the
following occured before the issue above.

"Managed Debugging Assistant 'LoadFromContext' has detected a problem in
'E:\Program Files\Microsoft Visual Studio 8\Common7\IDE\vstesthost.exe'.
Additional Information: The assembly named
'Microsoft.VisualStudio.QualityTools.ExecutionCommon' was loaded from
'file:///E:/Program Files/Microsoft Visual Studio
8/Common7/IDE/PrivateAssemblies/Microsoft.VisualStudio.QualityTools.ExecutionCommon.DLL'
using the LoadFrom context. The use of this context can result in unexpected
behavior for serialization, casting and dependency resolution. In almost all
cases, it is recommended that the LoadFrom context be avoided. This can be
done by installing assemblies in the Global Assembly Cache or in the
ApplicationBase directory and using Assembly.Load when explicitly loading
assemblies."

Thanks
 
W

Willy Denoyette [MVP]

Greg,

native dll's are loaded by the OS loader (using LoadLibrary Win32 API) not
by the CLR loader (fusion). The paths scanned are those defined by the
loader rules (these can be found in MSDN - search for "Dynamic-Link Library
Search Order").


Willy.


|
| Willy thanks for perservering ..
|
| Latest update
|
| I built a simple vc8 testc.exe console program and could load and use the
| samplec.dll i have talked about .
|
| I then used filemon.exe to trace file activity, and to my suprise the
| execution path tries about 30 odd
| directories (some often repeated) for the samplec.dll but NONE of them
where
| the directory
| that MSTestProject.dll and SampleC.dll lived in !! These are in a common
| debug or release directory
|
| Go figure !!
|
| It would seem the process starts from "UnitTesting.vshost.exe" which loads
| and calls the MSTestProject.dll
| which when running can't find samplec.dll
|
| SO as a temp. measure i added the debug directory to the windows PATH env.
| and restarted the vs2005 IDE
|
| Now the process finds samplec.dll and now i have the new error set ....
|
| "A first chance exception of type 'System.DllNotFoundException' occurred
in
| MSTestProject.dll
|
| Additional information: Unable to load DLL 'SampleC.dll': This application
| has failed to start because the application configuration is incorrect.
| Reinstalling the application may fix this problem. (Exception from
HRESULT:
| 0x800736B1)"
|
| >> So even if i get past this issue, i don't understand why the system did
| >> not try the directory that all the binaries where living in .
|
| I seem to have the correct manifest settings ..
|
| NB: While in debug and changing exceptions to always thrown, several of
the
| following occured before the issue above.
|
| "Managed Debugging Assistant 'LoadFromContext' has detected a problem in
| 'E:\Program Files\Microsoft Visual Studio 8\Common7\IDE\vstesthost.exe'.
| Additional Information: The assembly named
| 'Microsoft.VisualStudio.QualityTools.ExecutionCommon' was loaded from
| 'file:///E:/Program Files/Microsoft Visual Studio
|
8/Common7/IDE/PrivateAssemblies/Microsoft.VisualStudio.QualityTools.ExecutionCommon.DLL'
| using the LoadFrom context. The use of this context can result in
unexpected
| behavior for serialization, casting and dependency resolution. In almost
all
| cases, it is recommended that the LoadFrom context be avoided. This can be
| done by installing assemblies in the Global Assembly Cache or in the
| ApplicationBase directory and using Assembly.Load when explicitly loading
| assemblies."
|
| Thanks
|
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top