如何知道一个“.exe”进程是用C++还是C#编写的?

15

2
我已经可以说有一种方法,因为Process Explorer可以做到这一点。现在我们需要找到如何做:p - Kevin Gosse
尝试使用Reflector打开exe文件,看看会出现什么。 - user153923
1
请注意,使用VB.NET编写的程序生成与使用C#编写的程序相同的可执行文件,“非托管应用程序”的创建方式只能靠猜测。就像其他人提到的那样,您可以区分托管代码和非托管代码。 - C.Evenhuis
通过编写自己的代码或使用其他工具? - Nasreddine
3
您希望以编程方式还是手动操作完成这个任务? - Lynn Crumbling
显示剩余3条评论
4个回答

9
如果您想确定一个进程是否为.NET进程,我可以建议一种解决方案,灵感来自Dave Van den Eynde在这个主题中的回答:如何判断win32应用程序是否使用.NET运行时。"如果一个应用程序需要mscoree.dll才能运行,则它是一个.NET可执行文件。" 因此,您可以检查进程的模块,以查看是否列出了mscoree。
        foreach (var process in Process.GetProcesses())
        {
            if (process.Modules.OfType<ProcessModule>().Any(m => m.ModuleName.Equals("mscoree.dll", StringComparison.OrdinalIgnoreCase)))
            {
                Console.WriteLine("{0} is a .NET process", process.ProcessName);
            }
        }

"mscoree.dll" 是 C# 托管代码二进制文件的主要 DLL 资源吗?我可以相信没有使用相同DLL的C++二进制文件吗? - Diogo
这不是一个托管库,但是这个dll中的所有内容都与.NET Framework相关。它不能保证该进程是纯粹的.NET应用程序,但至少它托管了一些.NET代码。例如,如果在Microsoft Word中加载一个.NET插件,即使Word本身不是一个.NET应用程序,这个dll也会出现在模块中。 - Kevin Gosse
1
为什么使用这种检查方式时,用C#编写的控制台应用程序不显示为托管应用程序? - dragonfly02
虽然这是一个好的答案,但使用==比较字符串可能会产生误导,因为某些进程模块名称是MSCOREE.DLL。将==更改为m.ModuleName.Equals("mscoree.dll", StringComparison.InvariantCultureIgnoreCase)是一个更安全的选择。 - dragonfly02
你的示例代码是使用 .Net c# 并且使用了 mscoree.dll,如果它使用了在 .Net 中编写的 COM,也会加载 mscoree.dll 等等... 我所看到的唯一方法是检查进程映像并检查 PE IMAGE HEADER 是否设置了 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 描述符。 请参考 HABJAN 的答案。 - SoLaR

5

链接描述了正确的方式。 - SoLaR

2

您可以在Visual Studio命令行环境中使用peverify或ildasm(可用)运行文件,如果它不是托管代码,则会给出错误。请注意,在某些使用保护系统加密IL和隐藏CLR bootloader的情况下,此方法可能会失败,但大多数程序都没有这种保护。


1

如果它是一个.NET .exe(或.dll),它将依赖于mscoree.dll,您可以通过使用Dependency Walker或类似工具来检查它。

如果您想以编程方式执行此操作,可以以this VB project为起点。

但这并不能确定程序的语言。您无法确定C#与VB.NET(或其他.NET语言)程序之间的区别,也无法确定C++与C程序(或其他非.NET语言)之间的区别。有些事情可以排除其中一种语言的可能性,或使其中一种语言更有可能。甚至可能存在以某种奇怪的方式使用mscoree.dll的非托管代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接