tags:

views:

119

answers:

4

How can I determine if the running application is a Windows Forms or a Console application?

A: 

If it doesn't need to be done programmatically you could maybe use a program like ProcessExplorer and see if the System.Winforms.dll is loaded. I don't think this is foolproof but it may be a start.

Richard Nienaber
A: 

One option might be to check if System.Windows.Forms.Application.OpenForms contains any elements.

Another option might be to check whether Console.Title or Console.WindowTop throws an exception (it would if no console window is open).

EDIT

However, note that an application may have a console window and a form open at the same time... What kind of application is it then?

Aviad P.
+2  A: 

p/invoke:

[DllImport("shell32.dll")]
private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

Struct:

[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
    public IntPtr hIcon;
    public IntPtr iIcon;
    public uint dwAttributes;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
    public string szDisplayName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)]
    public string szTypeName;
}

Method:

private static bool IsWindowsApplication(string fileName)
{
    SHFILEINFO psfi = new SHFILEINFO();
    switch (((int) SHGetFileInfo(fileName, 0, ref psfi, (uint) Marshal.SizeOf(psfi), 0x2000)))
    {
        case 0:
            return false;

        case 0x4550:
            return false;

        case 0x5a4d:
            return false;
    }
    return true;
}

If the above method returns false, it's a console application.

-Oisin

x0n
What if there's a form and a console open at the same time? What would the function return? And would it be semantically true?
Aviad P.
@Aviad: There is no clean way to achieve this on Windows. An executable can be compiled for only one of the available subsystems, e.g. the Windows character of subsystem (a console app) or the Windows GUI subsystem (or native, OS/2 or Posix). Of course you can attach a console to a window application, but the application will still remain a window application.
0xA3
That may be true for a native executable, but not for a .NET one.
Aviad P.
.NET executables are in PE format just as native Win32 applications, therefore this holds also for .NET executables. You can check it from the VS command prompt: `dumpbin /HEADERS myapp.exe` will display the PE headers. Look for the line showing the subsystem. A value of 2 means Windows GUI and a value of 3 means Windows CUI (console app) (see http://msdn.microsoft.com/en-us/magazine/ms809762.aspx).
0xA3
Ok, but that flag is somewhat insignificant for a .NET application which may open a console, a form and a WPF host all together... That's all I'm trying to say. Maybe it answers the original poster's problem, and maybe it doesn't, that's for him to say. In my opinion tho, all things being equal, that flag is insignificant for a .NET application.
Aviad P.
And for the ones wondering about the magic numbers in x0n's source code, these are the return values of `ShGetFileInfo` as documented here (http://msdn.microsoft.com/en-us/library/bb762179%28VS.85%29.aspx). `0` actually means that the file is not in an executable format (nitpick), `0x5a4d` is ascii for MZ format (MS-DOS/bat) and `0x4550` is ascii for PE (portable executable format)
0xA3
@Aviad: Even a .NET application is *either* a console *or* a window application (although you might be able to fake a different behaviour). As this subsystem type decides how the kernel loads an application, there is no way a .NET application could change that low-level OS behavior. I recommend you this article by Raymond Chen: http://blogs.msdn.com/oldnewthing/archive/2009/01/01/9259142.aspx.
0xA3
@divo, I never doubted you, the thing is, what does the original poster want to know? Is he interested in this technical flag? Or is he interested in what the application actually presents itself as?
Aviad P.
I'm with Aviad on this one. IMAGE_SUBSYSTEM_WINDOWS_CUI does very little. It asks Windows to automatically call AllocConsole(), that's all. The ultimate denigrate case is a service, one beyond the *either* clause. xOn's code is clever but can't solve this. The proper way to output user-visible info can never be determined by a DLL.
Hans Passant
This one worked perfectly, thanks!
Diego Mijelshon
+2  A: 

You can't do this reliably. For example, start a new project from the Windows Forms Application project template. Project + Properties, change Output Type to "Console Application". Press F5 to see what that looks like. While every reasonable test will say it is a console mode application, it is very much a WF app.

The opposite is true as well, merely the presence of System.Windows.Forms.dll doesn't make it a WF app. A console app might use it to display a MessageBox for example.

Furthermore, it could be neither. Your code might be called by a service.

Punt this problem, the author of the app never has a problem telling you what your code should do. Add a property to your class to allow her to do so. Or use events. Or use dependency injection.

Hans Passant
+1 this is much more accurate than the other upvoted answer.
Aviad P.