0

在 C# 中,可以使用反射检索程序集相关信息,如产品名称、版本等:

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

如果正在执行的程序集是用非托管 C++ 编写的(比如说),我该怎么做?甚至可能吗?假设我有一个 .NET dll,它通过 COM 接口在非托管代码中被调用。

编辑:
为了让事情变得非常清楚,这是我的场景:

  • 我有一个用非托管 C++ 编写的可执行文件
  • 我有一个用 C#/.NET 编写的 dll
  • 可执行文件通过 COM 接口调用 dll
  • 在 .NET dll 中,我希望能够检索调用可执行文件的产品名称和版本等信息。

可能的?

4

3 回答 3

1

无需遍历堆栈即可找出您所在的进程。您只需进行一次 Win32 API 调用:

HMODULE hEXE = GetModuleHandle(NULL);

根据此调用的文档

如果此参数为 NULL,GetModuleHandle 返回用于创建调用进程的文件(.exe 文件)的句柄。

您可以使用另一个标准 Win32 API GetModuleFileName()将此模块句柄转换为文件名。手头有文件名,然后您可以调用GetFileVersionInfo()来检索该文件的 VS_VERSIONINFO 结构。你想要的信息就在里面。

现在,由于您在 .NET 中,您可以对GetModuleHandle()GetModuleFileName()使用 P/Invoke 签名。对于 GetFileVersionInfo() 您可以使用System.Diagnostics.FileVersionInfo

但实际上最简单的方法可能是坚持使用 System.Diagnostics 命名空间,您需要的一切都在那里。调用System.Diagnostics.Process.GetCurrentProcess()以返回您正在运行的进程的 Process 对象。然后您可以从MainModule属性中检索 ProcessModule。ProcessModule 有一个名为FileVersionInfo的属性。你想要的信息就在那里。

于 2008-12-01T18:38:10.123 回答
0

您可以在 VB.Net 中使用以下代码来检索扩展文档属性:

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

将对 Microsoft Shell 控件和自动化的 COM 引用添加到要编译的项目中。

上述程序的输出将是分配给 C:\tmp 中所有文件的元数据列表,例如

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:
于 2008-12-01T09:01:53.720 回答
0

假设您正在寻找@divo 调用返回的EXE/DLL 的PE 标头数据,例如公司、产品等……顺便说一句。源自调用 Win32 版本信息 API - MSDN 上的详细信息:

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

您面临的下一个挑战是枚举调用堆栈以发现调用者的模块上下文。我没有尝试过 - 但如果你检查自己的调用堆栈,我怀疑你会看到非托管调用者的帧编组到那里。怀疑它在切换到 CCW 之前在注入的过渡帧处停止。此外,由于它是 COM,因此可以想象调用者可以从进程外调用 - 您的调用者将是一个代理进程。

如果失败 - 您需要调试 API 来展开外部堆栈 - 这会引入其他约束:

  • 遍历堆栈所需的提升的安全权限
  • 展开堆栈的潜在性能影响。

在逐个调用的基础上,其中任何一个都可能使调试器方法不切实际。

更新

一些研究表明,即使在调试器中读取 CCW 过渡帧上方的堆栈时也存在大量错误和陷阱。例如

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

混合非托管/托管符号解析非常难看 - 这里有一些关于如何做到这一点的想法...... DaveBr 关于调试的博客也非常棒。

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

在非托管/托管客户端之间编组呼叫所采取的步骤有很多素材 - 例如

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

于 2008-12-01T09:20:42.340 回答