winforms 如何检查.exe文件是否为控制台应用程序?

zzoitvuj  于 2023-06-24  发布在  其他
关注(0)|答案(2)|浏览(134)

如果这个问题不是最容易理解的,我提前道歉,我对C#和Windows窗体还是个新手。
我正在做一个程序,允许用户在一个有组织的地方运行多个控制台应用程序(在我的情况下,Discord机器人)。我现在正在处理“打开文件”对话框,我想知道是否有一种方法来确定所选的.exe文件是否是控制台应用程序?如果不进行此检查,如果用户选择的.exe文件不是控制台应用程序,则程序将崩溃。
如果有人能给我指出正确的方向,我将不胜感激!谢谢!

wf82jlnq

wf82jlnq1#

针对.NET Core或.NET 5+,您可以使用System.Reflection.PortableExecutable命名空间(System.Reflection.Metadata程序集的一部分)。
它的PEReader类(在.NET Framework中不可用)允许读取PE Headers,而无需PInvoke,例如ImageLoad()MapAndLoad()等。
使用起来很简单。
使用您使用File.Open()或初始化FileStream打开的Stream初始化PEReader类,传递图像文件的完整路径,然后读取您返回的PEHeaders对象的内容。
最小实现(.NET 5+,C# 8.0+):

using System.Reflection.PortableExecutable;

string imagePath = @"[Full path of executable file]"
bool isConsoleApp = GetExeType(imagePath, out bool isDll) == Subsystem.WindowsCui;

// [...]

public Subsystem GetExeType(string imagePath, out bool isDll) {
    using var stream = File.Open(imagePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    using var reader = new PEReader(stream);
    isDll = reader.PEHeaders.IsDll;
    return reader?.PEHeaders?.PEHeader != null ? reader.PEHeaders.PEHeader.Subsystem : Subsystem.Unknown;
}

当然,您可以返回一个PEHeader类对象并检查所有其他可用的属性。通常,您会从LOADED_IMAGE结构中得到什么

b1payxdu

b1payxdu2#

在C#中,您可以通过检查其子系统类型来确定可执行文件是否是控制台应用程序。控制台应用程序的子系统类型为IMAGE_SUBSYSTEM_WINDOWS_CUI。另一方面,Windows窗体应用程序的子系统类型为IMAGE_SUBSYSTEM_WINDOWS_GUI
要检查可执行文件的子系统类型,可以使用C#中的System. Diagnostics. FileVersionInfo类。下面是一个示例,说明如何做到这一点:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = @"C:\path\to\your\executable.exe";

        bool isConsoleApp = IsConsoleApplication(filePath);

        if (isConsoleApp)
        {
            Console.WriteLine("The selected executable is a console application.");
            // Proceed with running the console application
        }
        else
        {
            Console.WriteLine("The selected executable is not a console application.");
            // Show an error message or handle it as appropriate
        }

        Console.ReadLine();
    }

    static bool IsConsoleApplication(string filePath)
    {
        using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            using (BinaryReader reader = new BinaryReader(stream))
            {
                // Check the PE signature
                if (reader.ReadUInt16() != 0x5A4D) // "MZ" in ASCII
                    return false;

                // Skip to the PE header
                stream.Seek(0x3C, SeekOrigin.Begin);
                int peHeaderOffset = reader.ReadInt32();
                stream.Seek(peHeaderOffset, SeekOrigin.Begin);

                // Check the PE signature
                if (reader.ReadUInt32() != 0x00004550) // "PE\0\0" in ASCII
                    return false;

                // Skip to the optional header
                stream.Seek(20, SeekOrigin.Current);

                // Read the subsystem value
                ushort subsystem = reader.ReadUInt16();

                // Check if it's a console application
                return subsystem == 0x0003; // 0x0003 represents IMAGE_SUBSYSTEM_WINDOWS_CUI
            }
        }
    }
}

在上面的示例中,您可以将**@"C:\path\to\your\executable.exe "**替换为用户使用“打开文件”对话框选择的. exe文件的路径。
请注意,这种方法依赖于可执行文件的元数据中指定的子系统类型,因此如果信息丢失或不正确,它将无法确定可执行文件的类型。
我希望这对你的项目有帮助!如果你还有什么问题就告诉我。

相关问题