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!
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