Как определить подсистему, используемую данной сборкой .NET? - PullRequest
5 голосов
/ 24 июня 2010

В приложении 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*/
    }
}

Ответы [ 4 ]

4 голосов
/ 24 июня 2010

Это выходит за рамки управляемого кода. С точки зрения .NET приложения Console и Windows UI одинаковы. Вы должны заглянуть в заголовок файла PE. Поиск работы "Подсистема" на этой странице http://msdn.microsoft.com/en-us/magazine/bb985997.aspx

1 голос
/ 08 ноября 2014

Функция SHGetFileInfo может сделать это:

[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),
}

Затем, согласно спецификации, если это только MZ или PE, он открывается в консоли, в противном случае (если версияуказано), открыто в окне.

ExeType type = GetExeType("program.exe");
if(type == ExeType.PE || type == ExeType.MZ) return "console";
else return "window";
1 голос
/ 24 июня 2010

Полагаю, оно должно быть таким же, как и для нативных приложений, поэтому вы можете адаптировать эту статью с C ++ на C # для чтения заголовков PE: Как определить, является ли приложение консольным или графическим интерфейсом пользователя

0 голосов
/ 24 июня 2010

Я не думаю, что есть научный способ определить это, самый близкий обходной путь, который мне приходит в голову, - это использование отражения для проверки, ссылается ли приложение и загружает ли сборку WinForms, но я не совсем уверен.Можно попробовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...