c# मुझे कंसोल एप्लिकेशन की विंडो का हैंडल कैसे मिलेगा




console hwnd (5)

क्या कोई मुझे बता सकता है कि C # में Windows कंसोल एप्लिकेशन का हैंडल कैसे प्राप्त किया जाए? Windows प्रपत्र अनुप्रयोग में, मैं सामान्य रूप से यह कोशिश this.Handle


यहाँ ऐसा करने का एक मजबूत तरीका है:

कंसोल Win32 एपीआई से संबंधित कार्य हैं:

[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() पर्याप्त है
  • कंसोल के लिए एक और प्रक्रिया जुड़ी हुई है, इसके साथ ही AttachConsole साथ AttachConsole करें, AttachConsole को कॉल करें, उन्हें तुरंत FreeConsole साथ अलग करें।

अतिरिक्त सावधानी के लिए, संलग्न करने से पहले एक कंसोल ईवेंट हैंडलर को पंजीकृत करें (और इसे अलग करने के बाद अनरजिस्टर्ड करें) साथ ही आप गलती से समाप्त नहीं हो जाते हैं यदि एक कंसोल इवेंट आपके द्वारा कंसोल से जुड़े छोटे समय फ्रेम में होता है:

[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 (या विस्टा के बाद प्रत्येक सत्र के लिए एक की भीड़) द्वारा प्रबंधित की जाती है, इसलिए इसे ReadProcessMemory की पसंद से पुनर्प्राप्त नहीं किया जा सकता है। csrss एलपीसी एपीआई है कि सभी csrss उजागर करता है। पूर्ण API सूची में केवल एक प्रासंगिक फ़ंक्शन है, SrvGetConsoleWindow । और यह एक पीआईडी ​​को स्वीकार नहीं करता है, लेकिन कॉलिंग पार्टी को निर्धारित करता है कि वैकल्पिक कार्यान्वयन या फ़ंक्शन के डिस्क्रास को winsrv.dll


इसे इस्तेमाल करे:

[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);

मुझे नहीं लगता कि ऐसी कोई बात है। कंसोल विंडो अनुप्रयोग के लिए पहुँच योग्य नहीं है। आप अपने स्वयं के प्रक्रिया नाम की तलाश में प्रक्रिया सूची को पुनरावृत्त करने की कोशिश करते हैं। Process वर्ग IIRC में प्रोग्राम के मुख्य विंडो हैंडल के लिए एक संपत्ति होती है, जो कंसोल अनुप्रयोगों के लिए कंसोल विंडो हो सकती है - जो मुझे यकीन नहीं है।


एक कंसोल एप्लिकेशन में जो कंसोल के लिए डायगोस्टिक्स को स्ट्रीम करता है, और जिसके लिए मैं माउस इनपुट को अक्षम करना चाहता था, मैंने GetConsoleWindow(), Process.GetCurrentProcess().MainWindowHandle, and FindWindowByCaption(IntPtr.Zero, Console.Title) । इनमें से प्रत्येक ने एक ही गैर-शून्य हैंडल लौटाया, लेकिन जब मैंने उस हैंडल को SetConsoleMode में उपयोग करने की कोशिश की, तो उसने "अमान्य हैंडल" अपवाद को फेंक दिया। अंत में मैंने SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | ENABLE_EXTENDED_FLAGS)) की कोशिश की SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | ENABLE_EXTENDED_FLAGS)) STD_INPUT_HANDLE को -10 के रूप में परिभाषित किया और यह काम किया। MS का दस्तावेज़ीकरण बताता है कि कंसोल को हैंडल पुन: असाइन किया जा सकता है, और मैं इस समाधान के साथ सहज या खुश नहीं हूं, लेकिन अभी तक यह एकमात्र ऐसी चीज है जो मैंने पाया है कि मुझे त्वरित रूप से संपादन मोड को अक्षम करने की अनुमति मिलती है। GetStdHandle(STD_INPUT_HANDLE) '3' लौटाता है, अन्य कॉल 7 अंकों का मान लौटाते हैं जो हर बार प्रोग्राम चलने पर बदलता है।


मैंने अभी अपने लिए इस समस्या को हल किया है (दुर्भाग्य से थॉमस के उत्तर को देखने से पहले जो बहुत तेज है)। खैर, यहां उन लोगों के लिए एक और तरीका है जो उसके जवाब से संतुष्ट नहीं हैं। मैं यह उत्तर इसलिए लिख रहा हूं क्योंकि यदि आप अपने कंसोल को विंडो के रूप में मान रहे हैं तो मैं एक और उत्तर + Program क्लास को डिजाइन करने का एक बेहतर तरीका प्रदान करना चाहता हूं। आइए उस डिज़ाइन से शुरू करें:

मैंने Program क्लास की डिफ़ॉल्ट शैली को बदल दिया है। मैंने वास्तव में इसे एक वर्ग में बनाया है, जिसमें इसका एक कार्यक्रम है, न कि केवल एक विधि, जो इसका प्रतिनिधित्व करती है और सामग्री के लिए अन्य वर्गों का उपयोग करती है। (यदि आप नहीं जानते कि मेरा क्या मतलब है, महत्वपूर्ण नहीं)।

इसका कारण मुझे यह करना पड़ा क्योंकि मैं निम्नलिखित ईवेंट हैंडलर लिखना चाहता था:

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

यह इस पद्धति को MessageBox.Show(IWin32Window, String, String) ओवरलोड करता है।

क्योंकि कंसोल 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();
}

अब, समस्या यह है कि आप वास्तव में इसे Main नहीं कह सकते हैं, एक स्थिर विधि है, इसलिए जो कुछ भी मैं Main में था उसे Start नामक एक नई विधि में ले जाया गया है और सभी Main एक नया Program और Start कॉल कर रहे हैं।

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

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

    throw new Exception();
}

परिणाम, निश्चित रूप से, एक मालिक के रूप में मेरे कंसोल की खिड़की के साथ एक संदेश-बॉक्स था।
संदेश-बॉक्स के लिए इस पद्धति का उपयोग करना, निश्चित रूप से इस पद्धति का केवल एक अनुप्रयोग है।





window-handles