Search code examples
c#winformsconsole-application

How to check if an executable is a Console or GUI App?


Apologies in advance if this question isn't the most understandable, I'm still very new to C# and Windows Forms.

I'm making a program that allows the user to run multiple Console App programs (in my case, Discord bots) in one organized place. I'm working on the "Open File" dialog right now, and I was wondering if there was a way to determine if the .exe file chosen was a console app? If this check isn't in place, my program would crash if the user chose an .exe file that isn't a console app.

If anyone could point me in the right direction, I'd greatly appreciate it! Thanks!


Solution

  • Targeting .NET Core or .NET 5+, you can make use of the System.Reflection.PortableExecutable namespace, part of the System.Reflection.Metadata assembly.

    Its PEReader class (not available in .NET Framework) allows to read the PE Headers without the need to PInvoke, e.g., ImageLoad() or MapAndLoad() etc.

    It's quite simple to use.
    Initialize a PEReader class using a Stream you have opened using, e.g., File.Open() or initializing a FileStream, passing the full path of an image file, then read the content of the PEHeaders object you get back.

    A minimal implementation (.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;
    }
    

    Of course you could return a PEHeader class object and inspect all the other properties available. You, mostly, have what you would get from a LOADED_IMAGE struct