2009-08-14 3 views

답변

47

는 확실하지가 작동하지만 당신은 시도 할 수 있습니다 :

IntPtr handle = Process.GetCurrentProcess().MainWindowHandle; 
+0

이 기능을 사용 했습니까? 그냥 호기심, 왜냐하면 나는 몇 곳에서 이것을 사용할 수 있기 때문에 :) – Pwninstein

+0

2-22 년 후에 다른 사람을 찾고; 예, 이것은 (나를 위해) 효과가있었습니다. –

+6

이것은 프로세스가 콘솔을 시작한 경우에만 작동하는 것으로 보입니다. 다른 콘솔에서 실행하면 항상 0이됩니다. 다른 상황에서 findwindowbycaption을 사용해야 할 것 같습니다 (http://support.microsoft.com/kb/124103 참조). –

1

그런 일은 없을 것이라고 생각합니다. 응용 프로그램에서 콘솔 창에 액세스 할 수 없습니다. 자신의 프로세스 이름을 찾는 프로세스 목록을 반복하려고 할 수도 있습니다. Process 클래스 IIRC에는 프로그램의 주 창 핸들에 대한 속성이 포함되어 있습니다. 일 수 있습니다.은 콘솔 응용 프로그램의 콘솔 창입니다. 잘 모르겠습니다.

+0

"자신의 프로세스 이름을 찾는 프로세스 목록을 반복하십시오"=> 매우 효율적인 접근법이 아닙니다 ... PID를 사용하여 찾을 수 있습니다.} –

+0

Whoops - Thomas Levesque의 대답은 훨씬 더 우아합니다.동일한 속성에 의존하면서 반복 할 필요가 없습니다. 나는 현재 프로세스에 직접 액세스 할 수 있다는 것을 잊었습니다. –

+0

@Thomas : 죄송합니다. 전에 귀하의 코멘트를 보지 못했습니다. 물론 반복은 훨씬 비효율적입니다. GetCurrentProcess() 메서드를 기억하지 못했습니다 ... –

9

이 시도 : 난 그냥 나 자신 (이 문제를 해결했습니다

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] 
public static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName); 
… 

Console.Title = "Test"; 
… 

IntPtr handle = FindWindowByCaption(IntPtr.Zero, Console.Title); 
8

을 불행하게도 더 빨리되는 Thomas's answer을보기 전에). 글쎄, 그의 대답에 만족하지 않는 사람들을위한 또 다른 방법이있다. 이 답을 쓰고 있는데 왜냐하면 콘솔을 윈도우로 다루는 경우 Program 클래스를 디자인하는 또 다른 대답 + 더 좋은 방법을 제공하고 싶기 때문입니다. 그 디자인부터 시작해 보겠습니다.

Program 클래스의 기본 스타일이 변경되었습니다. 저는 실제로 프로그램을 가지고있는 클래스에 그것을 만들었습니다. 그리고 그것을 표현하고 다른 클래스를 컨텐트에 사용하는 하나의 메소드가 아닙니다. (당신이 무슨 뜻인지 모르는 경우 중요하지 않습니다.)

나는 다음과 같은 이벤트 핸들러 쓰고 싶었 기 때문에 내가이해야 할 일을했을 이유 :이 방법 MessageBox.Show(IWin32Window, String, String)를 오버로드

private void CatchUnhandled(Object sender, UnhandledExceptionEventArgs e) 
{ 
    var exception = e.ExceptionObject as Exception; 
    MessageBox.Show(this, exception.Message, "Error"); // Check out 1st arg. 
} 

합니다. 콘솔 IWin32Window를 구현하지 않기 때문에

, 난 그냥 1 인수에 this를 호출하기 위해, 물론, 그것을 자신을 구현했다.

참고 :이 코드는 사용자가 액세스 수정을 자유롭게 변경할 느낄 수있는, 내 응용 프로그램에서 붙여 넣은 복사입니다

Program 클래스 선언 다음

은 그것의 구현 및 다른 모든 것들입니다 :

internal class Program : IWin32Window 
{ 
    ... 
} 

IWin32Window 구현 :

public IntPtr Handle 
{ 
    get { return NativeMethods.GetConsoleWindow(); } 
} 

그것은 다음과 같은 클래스 사용

internal static class NativeMethods 
{ 
    [DllImport("kernel32.dll")] 
    internal static extern IntPtr GetConsoleWindow(); 
} 

이제 문제는 당신이 실제로 정적 메서드 인, Mainthis를 호출 할 수 있다는 것입니다을, 그래서이 이동 한 Main에 있었다 어떤 Start이라는 새로운 메서드와 모든 Main이 수행하는 것은 Program을 새로 만들고 Start을 호출하는 것입니다.

private static void Main() 
{ 
    new Program().Start(); 
} 

private void Start() 
{ 
    AppDomain.CurrentDomain.UnhandledException += CatchUnhandled; 

    throw new Exception(); 
} 

결과는 물론 내 콘솔의 창을 소유자로 한 메시지 상자였습니다.
메시지 상자에이 방법을 사용하는 것은 당연히이 방법을 한 번 적용하는 것입니다.

+2

간단히 대답은 : [DllImport ("kernel32.dll")] 내부 정적 extern IntPtr GetConsoleWindow(); –

12

여기이 할 수있는 강력한 방법 본질적으로 신뢰할 수 :

Console Win32 API에서 관련 기능

은 다음과 같습니다

[DllImport("kernel32.dll", SetLastError = true)] 
static extern bool AttachConsole(uint dwProcessId); 
[DllImport("kernel32.dll")] 
static extern IntPtr GetConsoleWindow(); 
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)] 
static extern bool FreeConsole(); 
현재 프로세스가 부착 된 콘솔
  • , 그냥 GetConsoleWindow() 그 즉시 FreeConsole로 분리, GetConsoleWindow 전화, AttachConsole와 같은 잘 부착, 다른 프로세스에 첨부 된 콘솔
  • 충분하다.
  • 여분의주의를 들면

뿐만 아니라 콘솔 이벤트 당신이에 연결하고있는 작은 시간 프레임에서 일어나는 경우에 당신이 실수로 종료되지 않도록 연결하기 전에 콘솔 이벤트 핸들러를 등록 (및 분리 후 등록을 취소) 콘솔 :

[DllImport("kernel32.dll")] 
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, 
    bool Add); 
delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType); 
enum CtrlTypes : uint { 
    CTRL_C_EVENT = 0, 
    CTRL_BREAK_EVENT, 
    CTRL_CLOSE_EVENT, 
    CTRL_LOGOFF_EVENT = 5, 
    CTRL_SHUTDOWN_EVENT 
} 

bool is_attached=false;  
ConsoleCtrlDelegate ConsoleCtrlDelegateDetach = delegate(CtrlType) { 
    if (is_attached = !FreeConsole()) 
     Trace.Error('FreeConsole on ' + CtrlType + ': ' + new Win32Exception()); 
    return true; 
}; 

뭔가를 읽고 현재의 프로세스를 변경하기는이 콘솔 프로세스가있는 경우는 현재 콘솔을 종료 피하기 위해 도우미 프로세스를 필요로하기 때문에,이 정말 추한 도착 (오히려 추한). 그럼에도 불구하고 추가 조사 결과 csrss 프로세스 또는 대상 프로세스에 주입 할 수있는 다른 방법이 없다는 것을 보여줍니다.

콘솔 대응 정보는 csrss.exe (또는 Vista 이후 각 세션마다 하나씩)에 관리되고 있으므로 ReadProcessMemory과 같이 검색 할 수 없습니다. 모든 csrss 노출은 CSRSS LPC API입니다. 전체 API 목록에는 관련 함수가 하나만 있습니다 (SrvGetConsoleWindow). 그리고 PID를 허용하지는 않지만 an alternative implementation에 표시된 발신자 또는 해당 장치의 해체를 winsrv.dll으로 결정합니다.

+3

이것은 허용 된 대답이어야합니다. 이 작업을 수행하는 올바른 방법은 GetConsoleWindow입니다. 여기에있는 다른 답변 중 많은 부분은 단순한 구피입니다. –

+1

IDE와 달리 콘솔에서 응용 프로그램을 실행할 때 응용 프로그램이 작동하지 않는 이유를 파악하는 데 시간을 낭비하지 않는 한 정답입니다. 이반 감사합니다. – WiredEarp

0

콘솔에 진단 도구를 스트리밍하고 콘솔에서 마우스 입력을 사용하지 않으려는 콘솔 응용 프로그램에서 GetConsoleWindow(), Process.GetCurrentProcess().MainWindowHandle, and FindWindowByCaption(IntPtr.Zero, Console.Title)을 시도했습니다. 이들 각각은 0이 아닌 핸들을 반환했지만 SetConsoleMode에서 해당 핸들을 사용하려고하면 "잘못된 핸들"예외가 발생합니다. 마지막으로 STD_INPUT_HANDLE이 -10으로 정의 된 SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | ENABLE_EXTENDED_FLAGS))을 시도해 보았습니다. MS의 문서에 따르면 콘솔에 대한 핸들이 다시 할당 될 수 있으며이 솔루션에 만족스럽지 않거나 만족스럽지 않지만 지금까지는 빠른 편집 모드를 프로그래밍 방식으로 사용하지 않도록 설정할 수있는 유일한 방법입니다. GetStdHandle(STD_INPUT_HANDLE)이 '3'을 반환하면 다른 호출은 프로그램이 실행될 때마다 달라지는 7 자리 값을 반환합니다.

관련 문제