views:

911

answers:

3

In C#, it is possible to retrieve assembly related information like product name, version etc using reflection:

string productName = Assembly.GetCallingAssembly().GetName().Name;
string versionString = Assembly.GetCallingAssembly().GetName().Version.ToString();

How do I do the equivalent if the executing assembly is written in unmanaged C++ (say)? Is it even possible? Assume that I have a .NET dll which is being invoked in unmanaged code via a COM interface.

edit:
To make things absolutely clear, this is my scenario:

  • I have an executable written in unmanaged C++
  • I have a dll written in C#/.NET
  • The dll is invoked by the executable via a COM interface
  • Within the .NET dll I want to be able to retrieve information like the product name and version of the calling executable.

Possible?

A: 

Hi,

you could use the following code in VB.Net to retrieve extended document properties:

Sub Main()
    Dim arrHeaders(41)

    Dim shell As New Shell32.Shell
    Dim objFolder As Shell32.Folder

    objFolder = shell.NameSpace("C:\tmp\")

    For i = 0 To 40
        arrHeaders(i) = objFolder.GetDetailsOf(objFolder.Items, i)
    Next
    For Each strFileName In objfolder.Items
        For i = 0 To 40
            Console.WriteLine(i & vbTab & arrHeaders(i) & ": " & objFolder.GetDetailsOf(strFileName, i))
        Next
    Next

End Sub

Add a COM reference to Microsoft Shell Controls and Automation to your project to compile.

The output of the above program will be a list of the meta data assigned to all files in C:\tmp such as

0       Name: dpvoice.dll
1       Size: 208 KB
2       Type: Application Extension
3       Date Modified: 14.04.2008 04:41
4       Date Created: 14.04.2008 04:41
5       Date Accessed: 01.12.2008 09:56
6       Attributes: A
7       Status: Online
8       Owner: Administrators
9       Author:
10      Title:
11      Subject:
12      Category:
13      Pages:
14      Comments:
15      Copyright:
16      Artist:
17      Album Title:
18      Year:
19      Track Number:
20      Genre:
21      Duration:
22      Bit Rate:
23      Protected:
24      Camera Model:
25      Date Picture Taken:
26      Dimensions:
27      :
28      :
29      Episode Name:
30      Program Description:
31      :
32      Audio sample size:
33      Audio sample rate:
34      Channels:
35      Company: Microsoft Corporation
36      Description: Microsoft DirectPlay Voice
37      File Version: 5.3.2600.5512
38      Product Name: Microsoftr Windowsr Operating System
39      Product Version: 5.03.2600.5512
40      Keywords:

Regards, divo

0xA3
A: 

Let's assume you're after an EXE/DLL's PE header data that @divo's calls return e.g. Company, Product etc... These btw. are derived from calling Win32 Version Info API's - details up on MSDN:

http://msdn.microsoft.com/en-us/library/ms646981.aspx

The next challenge you face is enumerating the callstack to discover your caller's module context. I've not tried - but if you examine your own callstack, I doubt you'll see the unmanaged caller's frames marshalled into there. Suspect it stops at transitional frame injected before switching into the CCW. Also since it's COM, conceivably the caller could call from out of process - your caller would be a proxy process.

If that fails - you'd need the debugging API's to unwind the external stack - that introduces other constraints:

  • elevated security permissions required to traverse the stack
  • potential performance impact unwinding the stack.

On a call-by-call basis either of these could make the debugger approach impractical.

Update

Some research indicates there are plenty of bugs and gotchas for reading the stack above the CCW transitional frame even in the debugger. e.g.

http://support.microsoft.com/kb/317221

Mixed Unmanaged/Managed symbol resolution is pretty ugly - some thoughts here on how to do it... DaveBr's blog on debugging is pretty awesome too.

http://bytes.com/groups/net-vc/280340-stackwalk-callstack-symbol-resolve-managed-unmanaged-code-dbghelp-etc

http://blogs.msdn.com/davbr/archive/2005/10/06/478006.aspx

There is plenty of fodder on the steps taken marshalling calls between unmanaged/managed clients - e.g.

http://msdn.microsoft.com/en-us/library/ms973872.aspx

stephbu
+1  A: 

Walking the stack is not necessary to find out what process you are in. You simply make a single Win32 API call:

HMODULE hEXE = GetModuleHandle(NULL);

According to the documentation for this call:

If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).

You can turn this module handle into a filename with GetModuleFileName(), another standard Win32 API. File name in hand, you can then call GetFileVersionInfo() to retrieve the VS_VERSIONINFO structure for that file. The information you want is in there.

Now since you are in .NET you could use P/Invoke signatures for GetModuleHandle(), GetModuleFileName(). For GetFileVersionInfo() you can use System.Diagnostics.FileVersionInfo.

But actually the easiest way to do it is probably to stick with the System.Diagnostics namespace, everything you need is there. Call System.Diagnostics.Process.GetCurrentProcess() to return a Process object for the process you are running in. Then you can retrieve a ProcessModule from the MainModule property. ProcessModule has a property called FileVersionInfo. The information you want is there.

Tim Farley
Exactly what I need. If I could upvote this more than once I would!! Thanks!!!
jpoh