tags:

views:

36

answers:

3

In a C# application, I'd like to determine whether another .NET application is a Console application or not.

Can this be done using the reflection APIs?

EDIT: OK, it doesn't look like I'm going to get a good answer to this question because it doesn't look like the framework exposes the functionality I want. I dug around in the PE/COFF spec and came up with this:

/// <summary>
/// Parses the PE header and determines whether the given assembly is a console application.
/// </summary>
/// <param name="assemblyPath">The path of the assembly to check.</param>
/// <returns>True if the given assembly is a console application; false otherwise.</returns>
/// <remarks>The magic numbers in this method are extracted from the PE/COFF file
/// format specification available from http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx
/// </remarks>
bool AssemblyUsesConsoleSubsystem(string assemblyPath)
{
    using (var s = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read))
    {
        var rawPeSignatureOffset = new byte[4];
        s.Seek(0x3c, SeekOrigin.Begin);
        s.Read(rawPeSignatureOffset, 0, 4);
        int peSignatureOffset = rawPeSignatureOffset[0];
        peSignatureOffset |= rawPeSignatureOffset[1] << 8;
        peSignatureOffset |= rawPeSignatureOffset[2] << 16;
        peSignatureOffset |= rawPeSignatureOffset[3] << 24;
        var coffHeader = new byte[24];
        s.Seek(peSignatureOffset, SeekOrigin.Begin);
        s.Read(coffHeader, 0, 24);
        byte[] signature = {(byte)'P', (byte)'E', (byte)'\0', (byte)'\0'};
        for (int index = 0; index < 4; index++)
        {
            Assert.That(coffHeader[index], Is.EqualTo(signature[index]),
                "Attempted to check a non PE file for the console subsystem!");
        }
        var subsystemBytes = new byte[2];
        s.Seek(68, SeekOrigin.Current);
        s.Read(subsystemBytes, 0, 2);
        int subSystem = subsystemBytes[0] | subsystemBytes[1] << 8;
        return subSystem == 3; /*IMAGE_SUBSYSTEM_WINDOWS_CUI*/
    }
}
A: 

I don't think there's a scientific way to determine it, the closest workaround that comes to my mind is using reflection to check if the application references and loads the WinForms assembly, but I'm not entirely sure. Might give it a try.

Matteo Mosca
you can't definitely find it out using reflection. you should inspect the exe file header.
Andrey
My "anwser" was obviously thought when you have access to the program you are inspecting, not the compiled exe. Sorry for the misunderstanding.
Matteo Mosca
That won't work because you could use WinForms (or WPF) from a console application, and a non-console application does not need to use WinForms (for instance, a Windows service uses neither). Checking the .exe header is the only way.
Ruben
+1  A: 

I suppose it should the same as for native apps so then you might be able to adapt this article from C++ to C# to read the PE headers: How To Determine Whether an Application is Console or GUI

ho1
+2  A: 

this is out of scope of managed code. From .net view console and win applications are same, you have to peek into PE file header. search for work "Subsystem" on this page http://msdn.microsoft.com/en-us/magazine/bb985997.aspx

Andrey
Yes -- in native code I usually use the dbghelp apis for this, but I'm not in native code :(
Billy ONeal
@Billy ONeal the structure of headers is very simple and well known. it takes few lines of code in c++ (+ headers) to find out the subsystem. i guess in c# i should not take much more.
Andrey