代码之家  ›  专栏  ›  技术社区  ›  jpoh

从C/.NET中的非托管执行应用程序检索产品信息

  •  0
  • jpoh  · 技术社区  · 16 年前

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

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

    如果执行程序集是用非托管C++编写的,那么如何进行等效?有可能吗?假设我有一个.NET DLL,它通过COM接口在非托管代码中被调用。

    编辑:
    为了让事情完全清楚,这是我的设想:

    • 我有一个可执行文件 非托管C++
    • 我写了一个动态链接库 在C/.NET中
    • DLL由调用 可通过COM接口执行
    • 在.NET dll中 能够检索信息,比如 产品名称和版本 正在调用可执行文件。

    可能吗?

    3 回复  |  直到 6 年前
        1
  •  1
  •   Tim Farley    16 年前

    不需要遍历堆栈来了解您所处的过程。您只需进行一次win32 api调用:

    HMODULE hEXE = GetModuleHandle(NULL);
    

    根据 documentation for this call :

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

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

    既然您在.NET中,那么可以使用p/invoke签名 GetModuleHandle() , GetModuleFileName() . 对于getFileVersionInfo(),可以使用 System.Diagnostics.FileVersionInfo .

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

        2
  •  0
  •   Dirk Vollmar    8 年前

    可以在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:
    
        3
  •  0
  •   valiano    6 年前

    假设您正在处理一个exe/dll的pe头数据,@divo的调用返回该数据,例如公司、产品等…这些btw.是从调用win32 version info api的-details up on msdn派生的:

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

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

    如果失败(您需要调试API来释放外部堆栈),这将引入其他约束:

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

    在逐个调用的基础上,这两种方法都可能使调试器方法不切实际。

    更新

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

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

    混合非托管/托管符号解析非常糟糕-这里有一些关于如何实现它的想法…戴夫的调试博客也相当棒。

    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