简体   繁体   English

确定程序集是否是GUI应用程序

[英]Determine whether assembly is a gui application

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. 我试图确定C#程序集是GUI还是控制台应用程序,以便构建可以自动重新创建丢失的快捷方式的工具。

Currently, I have a routine which recursively steps all directories in Program Files (and the x86 directory). 当前,我有一个例程可以递归地执行程序文件中的所有目录(和x86目录)。

For each EXE it finds, the tool calls IsGuiApplication, passing the name of the EXE. 对于找到的每个EXE,该工具都会调用IsGuiApplication,并传递EXE的名称。

From there, I create an Assembly object using LoadFrom. 从那里,我使用LoadFrom创建一个Assembly对象。 I want to check whether this assembly is has a GUI output, but I'm unsure how to test this in C#. 我想检查该程序集是否具有GUI输出,但是不确定如何在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. 我当前的想法是使用GetStdHandle,但是我不确定如何将其应用于正在运行的应用程序之外的程序集。

My experience with reflection in C# is limited, so any help would be appreciated. 我在C#中进行反射的经验有限,因此不胜感激。

 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). 为了安全起见,@ Killany和@Nissim建议的方法并非100%准确,因为控制台应用程序可以引用System.Windows。* dll(由于错误或由于“系统”提供的其他功能的需要.Windows的程序集)。

I'm not sure a 100% method exist, as some applications can be given a parameter to run with/without ui (ie silently) 我不确定是否存在100%的方法,因为可以为某些应用程序提供一个可以使用ui或不使用ui的参数(即静默运行)

As several times mentioned before, you can read the Subsystem Field. 如前所述,您可以阅读子系统字段。

    private PEFileKinds GetFileType(string inFilename)
    {
        using (var fs = new FileStream(inFilename, FileMode.Open, FileAccess.Read))
        {
            var buffer = new byte[4];
            fs.Seek(0x3C, SeekOrigin.Begin);
            fs.Read(buffer, 0, 4);
            var peoffset = BitConverter.ToUInt32(buffer, 0);
            fs.Seek(peoffset + 0x5C, SeekOrigin.Begin);
            fs.Read(buffer, 0, 1);
            if (buffer[0] == 3)
            {
                return PEFileKinds.ConsoleApplication;
            }
            else if (buffer[0] == 2)
            {
                return PEFileKinds.WindowApplication;
            }
            else
            {
                return PEFileKinds.Dll;
            }
        }
    }

Use GetReferencedAssemblies() to get all referenced assemblies and look for the system.windows.forms assembly 使用GetReferencedAssemblies()获取所有引用的程序集并查找system.windows.forms程序集

    AssemblyName[] referencedAssemblies = assm.GetReferencedAssemblies();
    foreach (var assmName in referencedAssemblies)
    {
      if (assmName.Name.StartsWith("System.Windows"))
       //bingo
    }

A basic idea to detect GUI apps is that GUI apps always use assembly System.Windows.* . 检测GUI应用程序的基本思想是GUI应用程序始终使用程序集System.Windows.*

bool isGui(Assembly exeAsm) {
   foreach (var asm in exeAsm.GetReferencedAssemblies()) {
       if (asm.FullName.Contains("System.Windows"))
          return true;
   }
   return false;
}

This will detect all .NET applications that are windows forms, or even WPF 这将检测所有是Windows窗体甚至WPF的.NET应用程序

One thing you could check is the .subsystem of the file's PE header. 您可以检查的一件事是文件PE标头的.subsystem If you open up the file in ILDASM and check the manifest, you'll see this if it uses the Windows GUI subsystem: 如果在ILDASM中打开文件并检查清单,则如果使用Windows GUI子系统,则会看到以下内容:

在此处输入图片说明

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. 我认为Assembly类中没有任何方法可以检查此内容,因此您可能需要检查文件本身。

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) or System.Windows.Window (WPF): 检查的另一种方法是检查程序集中的类型,并查看它们中的任何一个是否派生自System.Windows.Forms.Form (Windows窗体)或System.Windows.Window (WPF):

private static bool HasGui(Assembly a)
{
    return a.DefinedTypes
        .Any(t => typeof(System.Windows.Forms.Form).IsAssignableFrom(t) ||
                  typeof(System.Windows.Window).IsAssignableFrom(t));
}

Note that you'll need to add references to System.Windows.Forms.dll and PresentationFramework.dll to gain access to these types. 请注意,您需要添加对System.Windows.Forms.dllPresentationFramework.dll引用才能访问这些类型。

You can use Assembly.LoadFrom(string) to load the assembly. 您可以使用Assembly.LoadFrom(string)来加载程序集。 I tested this method myself and it seemed a bit slow so perhaps you can make it faster by involving Parallel.ForEach . 我自己测试了此方法,它似乎有点慢,因此也许可以通过使用Parallel.ForEach使其更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何确定 Windows 应用程序是否在屏幕外? - How to determine whether a Windows application is offscreen? 如何确定Web应用程序当前是否正在运行 - How to determine whether a web application is currently running C#VS2010在应用程序中确定是否正在调试 - C# VS2010 Determine in application whether being debugged 如何确定我的域计算机上是否安装了特定的应用程序 - How to determine whether a specific application is installed on my domain computers 确定控制台应用程序是从命令行还是从 Powershell 运行 - Determine whether Console Application is run from command line or Powershell 如何确定来自其他应用程序的窗口是否可见? - How can I determine whether a window from another application is visible? 如何确定我的应用程序是否处于活动状态(有焦点) - How to determine whether my application is active (has focus) 如何确定一个类是在控制台应用程序或wpf中实例化的? - How to determine whether a class is instantiated within a console application or wpf? 确定是否从基于Windows的应用程序中调用类库 - Determine whether the class library is called from a windows based application 如何使用.NET中的反射来确定和检查程序集中的类型是自定义类型还是基元类型? - How to determine and check whether a type in assembly is Custom type or Primitive type using reflection in .NET?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM