I am trying to determine whether a C# assembly is a GUI or a Console application in order to build a tool which will automatically recreate lost short cuts.
Currently, I have a routine which recursively steps all directories in Program Files (and the x86 directory).
For each EXE it finds, the tool calls IsGuiApplication, passing the name of the EXE.
From there, I create an Assembly object using LoadFrom. I want to check whether this assembly is has a GUI output, but I'm unsure how to test this in C#.
My current idea is to use GetStdHandle, but I'm not sure how to apply this to an assembly outside of the running application.
My experience with reflection in C# is limited, so any help would be appreciated.
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace BatchShortcutBuild
{
class Program
{
//I'm uncertain that I need to use this method
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
static void Main(string[] args) {
BuildShortcuts();
Console.ReadLine();
}
public static void BuildShortcuts() {
String dirRoot = "C:\\Program Files\\";
processRoot(dirRoot);
dirRoot = "C:\\Program Files (x86)\\";
processRoot(dirRoot);
Console.WriteLine("Finished enumerating files");
Console.ReadLine();
}
public static void processRoot(String path) {
try {
foreach (String theDir in Directory.EnumerateDirectories(path)) {
processRoot(theDir);
}
foreach (String theFile in Directory.EnumerateFiles(path, "*.exe")) {
if (IsGuiApplication(theFile)) {
//I would generate a shortcut here
}
}
} catch { }
}
public static bool IsGuiApplication(String filePath) {
Console.WriteLine(filePath);
Assembly a = Assembly.LoadFrom(filePath);
//How to get the program type from the assembly?
return false;
}
}
}
Just to be safe here, the method suggested by @Killany and @Nissim suggest is not 100% accurate, as console applications can reference the System.Windows.* dlls (either by mistake or by a need of other functionality given by the 'System.Windows' assembly).
I'm not sure a 100% method exist, as some applications can be given a parameter to run with/without ui (i.e. silently)
A basic idea to detect GUI apps is that GUI apps always use assembly
System.Windows.*
.This will detect all .NET applications that are windows forms, or even WPF
Use
GetReferencedAssemblies()
to get all referenced assemblies and look for the system.windows.forms assemblyAs several times mentioned before, you can read the Subsystem Field.
One thing you could check is the
.subsystem
of the file's PE header. If you open up the file in ILDASM and check the manifest, you'll see this if it uses the Windows GUI subsystem:I don't think there's any method in the
Assembly
class to check this, so you'll probably need to check the file itself.Another way to check would be to go through the types in the assembly and see if any of them derive from
System.Windows.Forms.Form
(Windows Forms) orSystem.Windows.Window
(WPF):Note that you'll need to add references to
System.Windows.Forms.dll
andPresentationFramework.dll
to gain access to these types.You can use
Assembly.LoadFrom(string)
to load the assembly. I tested this method myself and it seemed a bit slow so perhaps you can make it faster by involvingParallel.ForEach
.