2010-06-24 7 views
5

In un'applicazione C#, vorrei determinare se un'altra applicazione .NET è un'applicazione Console o meno.Come è possibile determinare il sottosistema utilizzato da un determinato assembly .NET?

È possibile farlo utilizzando le API di riflessione?

MODIFICA: OK, non sembra che avrò una buona risposta a questa domanda perché non sembra che il framework esponga la funzionalità che voglio. Ho scavato intorno nel PE/COFF spec e arrivato fino a questo:

/// <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*/ 
    } 
} 

risposta

4

questo è fuori del campo di applicazione del codice gestito. Dalla console di visualizzazione .net e vincere le applicazioni sono le stesse, devi dare un'occhiata all'intestazione del file PE. ricerca di lavoro "sottosistema" in questa pagina http://msdn.microsoft.com/en-us/magazine/bb985997.aspx

+0

Sì, nel codice nativo di solito utilizzo gli apis dbghelp per questo, ma non sono nel codice nativo :( –

+0

@Billy ONeal la struttura delle intestazioni è molto semplice e ben conosciuta. Richiede poche righe di codice in C++ (+ headers) per trovare il sottosistema, credo che in C# non dovrei prendere molto di più – Andrey

0

Non credo ci sia un modo scientifico per determinare esso, la soluzione più vicina che mi viene in mente sta usando la riflessione per verificare se la riferimenti alle applicazioni e carica l'assembly WinForms, ma non ne sono del tutto sicuro. Potrebbe fare un tentativo.

+1

non è possibile individuarlo con la riflessione. dovresti controllare l'intestazione del file exe. – Andrey

+0

Il mio "anser" era ovviamente pensato quando si ha accesso al programma che si sta ispezionando, non all'exe compilato. Scusa per il fraintendimento. –

+0

Non funzionerà perché è possibile utilizzare WinForms (o WPF) da un'applicazione console e un'applicazione non console non deve utilizzare WinForms (ad esempio, un servizio Windows non ne usa nessuno). Il controllo dell'intestazione .exe è l'unico modo. – Ruben

1

La funzione SHGetFileInfo può fare questo:

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

Poi, secondo la specifica, se è solo MZ o PE, si apre in console, altrimenti (se una versione è specificata), è aperta in una finestra.

ExeType type = GetExeType("program.exe"); 
if(type == ExeType.PE || type == ExeType.MZ) return "console"; 
else return "window"; 
+0

-1: PEs può ancora usare il sottosistema della console - dovresti controllare la parte del sottosistema nelle intestazioni PE. –

+0

(intendo , NE e LE possono essere solo app console, PE può essere uno dei 3 sottosistemi –

+0

@BillyONeal E chi dice di no? La specifica dice (in sostanza) se non c'è alcun numero di versione nel codice di ritorno ('ExeType' qui), è un'applicazione console. – IllidanS4

Problemi correlati