Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何确定给定.NET程序集使用的子系统?_C#_Reflection - Fatal编程技术网

C# 如何确定给定.NET程序集使用的子系统?

C# 如何确定给定.NET程序集使用的子系统?,c#,reflection,C#,Reflection,在C#应用程序中,我想确定另一个.NET应用程序是否是控制台应用程序 这可以使用反射API来完成吗 编辑:好的,看起来我不会很好地回答这个问题,因为它看起来不像框架公开了我想要的功能。我仔细研究了PE/COFF规范,得出了以下结论: /// <summary> /// Parses the PE header and determines whether the given assembly is a console application. /// </summary>

在C#应用程序中,我想确定另一个.NET应用程序是否是控制台应用程序

这可以使用反射API来完成吗

编辑:好的,看起来我不会很好地回答这个问题,因为它看起来不像框架公开了我想要的功能。我仔细研究了PE/COFF规范,得出了以下结论:

/// <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*/
    }
}
//
///解析PE头并确定给定程序集是否为控制台应用程序。
/// 
///要检查的程序集的路径。
///如果给定程序集是控制台应用程序,则为True;否则就错了。
///此方法中的幻数是从PE/COFF文件中提取的
///格式规范可从http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx
/// 
bool assemblyUseConsolesSubsystem(字符串assemblyPath)
{
使用(var s=newfilestream(assemblyPath,FileMode.Open,FileAccess.Read))
{
var rawPeSignatureOffset=新字节[4];
s、 Seek(0x3c,SeekOrigin.Begin);
s、 读取(rawPeSignatureOffset,0,4);
int-peSignatureOffset=rawPeSignatureOffset[0];

peSignatureOffset |=rawPeSignatureOffset[1]我认为没有科学的方法来确定它,我想到的最接近的解决方法是使用反射来检查应用程序是否引用并加载WinForms程序集,但我不完全确定。可以尝试一下。

我想它应该与本机应用程序相同,这样您就可以修改本文了OM C++到C语言读取PE标题:

这超出了托管代码的范围。从.NET透视图来看,控制台和Windows UI应用程序是相同的。你必须浏览PE文件头。在这个页面上搜索“子系统”这个词“/p>< p>函数可以这样做:

[DllImport("shell32.dll", CharSet=CharSet.Auto, EntryPoint="SHGetFileInfo")]
public static extern ExeType GetExeType(string pszPath, uint dwFileAttributes = 0, IntPtr psfi = default(IntPtr), uint cbFileInfo = 0, uint uFlags = 0x2000);

[Flags]
public enum ExeType
{
    None = 0,
    WinNT = 0x04000000,
    PE = ((int)'P') | ((int)'E' << 8),
    NE = ((int)'N') | ((int)'E' << 8),
    MZ = ((int)'M') | ((int)'Z' << 8),
}

你不能用反射来确定它。你应该检查exe文件头。当你有权访问你正在检查的程序时,我的“anwser”显然是被认为的,而不是被编译的exe。很抱歉误解了。这不起作用,因为你可以使用WinForms(或WPF)从控制台应用程序,非控制台应用程序不需要使用WinForms(例如,Windows服务两者都不使用)。检查.exe头是唯一的方法。是的--在本机代码中,我通常使用dbghelp API来实现此目的,但我不在本机代码中:(Billy ONeal)标头的结构非常简单,众所周知。在C++(+头)中需要几行代码来找出子系统。我猜在C i中不应该占用更多。- 1:PES仍然可以使用控制台子系统——您需要检查PE头中的子系统部分。(我的意思是,NE和LE只能是控制台应用程序;PE可以是所有3个子系统中的一个子系统。@BillyONeal,谁说他们没有呢?规范说(基本上)如果返回代码中没有版本号(
ExeType
),它就是控制台应用程序。@BillyONeal感谢您的示例。☺关于ExeType enum的一点说明。上面的定义掩盖了一个事实,即
SHGetFileInfo
函数的返回类型是
DWORD_PTR
,测试的一个重要部分是高阶字必须为0(这是“无版本号”测试)因此,为了更具描述性,可以将枚举名称更改为PE_控制台和MZ_控制台,并添加描述性注释,如
//high word==0表示控制台子系统
ExeType type = GetExeType("program.exe");
if(type == ExeType.PE || type == ExeType.MZ) return "console";
else return "window";