2010-06-24 2 views
5

C# 응용 프로그램에서 다른 .NET 응용 프로그램이 콘솔 응용 프로그램인지 여부를 확인하고 싶습니다.주어진 .NET 어셈블리에서 사용하는 하위 시스템을 어떻게 결정합니까?

리플렉션 API를 사용하여 수행 할 수 있습니까?

EDIT : 프레임 워크가 원하는 기능을 제공하지 않는 것처럼 보이지 않으므로이 질문에 대한 좋은 대답을 얻지 못할 것 같습니다. 나는 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

이 관리되는 코드의 범위를 벗어납니다. .net보기 콘솔과 응용 프로그램이 동일하면 PE 파일 헤더를 들여다 봐야합니다. 이 페이지의 작업 "서브 시스템"에 대한 검색 http://msdn.microsoft.com/en-us/magazine/bb985997.aspx

+0

예 - 네이티브 코드에서 저는 보통 dbghelp apis를 사용합니다. 그러나 기본 코드가 아닙니다 : ( –

+0

@Billy ONeal 헤더 구조는 매우 간단하고 잘 알려져 있습니다. C++에서 몇 줄의 코드가 필요합니다. + 헤더) 하위 시스템을 찾을 수 있습니다. 나는 C#에서 나는 더 많은 것을 가져서는 안된다. – Andrey

0

응용 프로그램은 WinForms 어셈블리를 참조하고로드하지만 완전히 확신 할 수는 없습니다. 시도해 볼 수도 있습니다.

+1

당신은 그것을 리플렉션을 사용하여 확실히 찾을 수 없습니다. exe 파일 헤더를 검사해야합니다. – Andrey

+0

내 "anwser"는 컴파일 된 exe가 아닌 검사중인 프로그램에 액세스 할 때 분명히 생각되었습니다. 오해를해서 죄송합니다. –

+0

콘솔 응용 프로그램에서 WinForms (또는 WPF)를 사용할 수 있고 비 콘솔 응용 프로그램이 WinForms를 사용할 필요가 없기 때문에 (예를 들어 Windows 서비스는 둘 다 사용하지 않음) 작동하지 않습니다. .exe 헤더를 확인하는 것이 유일한 방법입니다. – Ruben

1

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의 경우는 true, 그렇지 않은 경우 (버전이 지정된 경우), 이는 창에서 열립니다.

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

-1 : PE는 여전히 콘솔 서브 시스템을 사용할 수있다. PE 헤더의 서브 시스템 부분을 확인해야한다. –

+0

NE와 LE는 단지 콘솔 어플리케이션 일뿐 PE는 3 개의 서브 시스템 중 하나가 될 수 있습니다 –

+0

@BillyONeal 그리고 누가 그렇지 않습니까? 사양은 리턴 코드에 버전 번호가 없다면 (기본적으로) 여기에'ExeType'가 있습니다), 콘솔 응용 프로그램입니다. – IllidanS4

관련 문제