क्या मैं विंडोज पर एक ctrl-C (SIGINT) एप्लिकेशन भेज सकता हूं?


91

मैं है (अतीत में) पार मंच (विंडोज / यूनिक्स) अनुप्रयोगों, जो जब कमांड लाइन से शुरू कर दिया, संभाला एक उपयोगकर्ता के द्वारा लिखे गए लिखा Ctrl- Cएक ही तरीके से संयोजन (यानी आवेदन सफाई से समाप्त करने के लिए)।

यह Windows पर संभव है एक भेजने के लिए Ctrl- Cअनुरोध करने के लिए एक और (असंबद्ध) प्रक्रिया से एक प्रक्रिया के लिए / SIGINT / बराबर है कि यह सफाई से समाप्त (यह संसाधनों आदि को साफ़ रखने का अवसर देने के)?


1
मैं केवल थ्रेडपंप प्राप्त करने के लिए java सेवा प्रक्रियाओं में Ctrl-C भेजने में रुचि रखता था। ऐसा प्रतीत होता है कि jstackइस विशिष्ट मामले के बदले मज़बूती से इस्तेमाल किया जा सकता है: stackoverflow.com/a/47723393/603516
Vadzim

जवाबों:


31

मैं एक समाधान के लिए सबसे करीब आया हूं वह SendSignal 3rd पार्टी ऐप है। लेखक स्रोत कोड और एक निष्पादन योग्य को सूचीबद्ध करता है। मैंने सत्यापित किया है कि यह 64-बिट विंडो के तहत काम करता है (32-बिट प्रोग्राम के रूप में चल रहा है, एक और 32-बिट प्रोग्राम को मार रहा है), लेकिन मुझे यह पता नहीं चला है कि कोड को विंडोज़ प्रोग्राम में कैसे एम्बेड किया जाए (32-बिट) या 64-बिट)।

यह काम किस प्रकार करता है:

डिबगर में बहुत खुदाई के बाद मुझे पता चला कि एंट्री पॉइंट जो वास्तव में ctrl-break जैसे सिग्नल से जुड़ा व्यवहार करता है, वह है kern32! CtrlRoutine। फ़ंक्शन में थ्रेडप्रोक के समान प्रोटोटाइप था, इसलिए इसे कोड इंजेक्ट किए बिना सीधे CreateRemoteThread के साथ उपयोग किया जा सकता है। हालाँकि, यह एक निर्यात प्रतीक नहीं है! यह विंडोज के विभिन्न संस्करणों पर अलग-अलग पते (और यहां तक ​​कि अलग-अलग नाम हैं) पर है। क्या करें?

यहाँ समाधान मैं अंत में के साथ आया है। मैं अपने ऐप के लिए एक कंसोल ctrl हैंडलर स्थापित करता हूं, फिर अपने ऐप के लिए एक ctrl-break सिग्नल उत्पन्न करता हूं। जब मेरे हैंडलर को कॉल किया जाता है, तो मैं कर्नेल 32 को दिए गए मापदंडों का पता लगाने के लिए स्टैक के शीर्ष पर वापस देखता हूं! मैं पहले परम को पकड़ता हूं, जो थ्रेड का वांछित प्रारंभ पता है, जो कि कर्नेल 32 का पता है! CtrlRoutine। फिर मैं अपने हैंडलर से लौटता हूं, यह दर्शाता है कि मैंने सिग्नल को संभाला है और मेरे ऐप को समाप्त नहीं किया जाना चाहिए। मुख्य धागे में वापस, मैं कर्नेल 32 के पते तक प्रतीक्षा करता हूं! CtrlRoutine पुनर्प्राप्त किया गया है। एक बार जब मुझे यह मिल जाता है, तो मैं खोज शुरू किए गए पते के साथ लक्ष्य प्रक्रिया में एक दूरस्थ धागा बनाता हूं। यह लक्ष्य प्रक्रिया में ctrl संचालकों का मूल्यांकन करने का कारण बनता है जैसे कि ctrl-break दबाया गया था!

अच्छी बात यह है कि केवल लक्षित प्रक्रिया ही प्रभावित होती है, और किसी भी प्रक्रिया (यहां तक ​​कि एक विंडो प्रक्रिया) को लक्षित किया जा सकता है। एक नकारात्मक पक्ष यह है कि मेरे छोटे ऐप का उपयोग बैच फ़ाइल में नहीं किया जा सकता है, क्योंकि यह कर्नेल-ब्रेक इवेंट को भेजने के लिए इसे मार देगा, जब कि कर्नेल 32 का पता चलता है! CtrlRoutine।

( startयदि यह एक बैच फ़ाइल में चल रहा है तो इसे रोकें ।)


2
+1 - लिंक किए गए कोड Ctrl-C के बजाय Ctrl-Break का उपयोग करते हैं, लेकिन इसके चेहरे पर (GenerateConsoleCtrlEvent के लिए दस्तावेज़ को देखकर) Ctrl-C के लिए अनुकूलित किया जा सकता है।
मैथ्यू मर्डोक

8
आपके लिए ऐसा करने के लिए वास्तव में एक फ़ंक्शन है, योग्य, "GenerateConsoleCtrlEvent"। देखें: msdn.microsoft.com/en-us/library/ms683155(v=vs.85).aspx मेरा जवाब यहाँ भी देखें: serverfault.com/a/501045/10023
Triynko

1
ऊपर दिए गए उत्तर से संबंधित Github लिंक: github.com/walware/statet/tree/master/…
meawoppl

3
यह दिमाग को चकरा देता है कि विंडोज उतना ही पुराना है और अभी तक Microsoft ने कंसोल एप्लिकेशन A से सिग्नल के लिए सुनने के लिए कंसोल एप्लिकेशन A के लिए कोई तंत्र उपलब्ध नहीं कराया है ताकि कंसोल एप्लीकेशन B कंसोल एप्लिकेशन को सफाई से बंद करने के लिए कह सके। किसी भी घटना में, एमएस को कोसते हुए, मैंने SendSignal की कोशिश की और "CreateRemoteThread 0x00000005 के साथ विफल रहा"। सिग्नल (किसी भी सिग्नल जो सुविधाजनक हो) के लिए सुनने के लिए आवेदन ए को कैसे कोडित करें, और फिर इसे कैसे सिग्नल दिया जाए कोई अन्य विचार?
डेविड आई। मैकिंटोश

3
@ DavidI.McIntosh ऐसा लगता है जैसे आप दोनों प्रक्रियाओं में नामांकित घटना बनाना चाहते हैं; तब आप दूसरे से एक संकेत दे पाएंगे। CreateEvent के लिए प्रलेखन की जाँच करें
arolson101

58

मैंने इस विषय के इर्द-गिर्द कुछ शोध किए हैं, जो मेरे अनुमान से अधिक लोकप्रिय हुए। KindDragon का जवाब निर्णायक बिंदुओं में से एक था।

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

संक्षेप में, वे डेमो प्रोग्राम निम्नलिखित करते हैं:

  • .Net का उपयोग करते हुए एक दृश्यमान विंडो के साथ एक कार्यक्रम शुरू करें, पिनवोक के साथ छिपें, 6 सेकंड के लिए दौड़ें, पिनवोक के साथ दिखाएं, नेट के साथ बंद करें।
  • विंडो का उपयोग किए बिना एक कार्यक्रम शुरू करें। नेट, 6 सेकंड के लिए चलाएं, कंसोल संलग्न करके बंद करें और कंसोल कंसोल जारी करें।

संपादित करें: यहां और अब कोड में रुचि रखने वालों के लिए KindDragon से संशोधित समाधान। यदि आप पहले एक को रोकने के बाद अन्य कार्यक्रमों को शुरू करने की योजना बनाते हैं, तो आपको Ctrl-C हैंडलिंग को फिर से सक्षम करना चाहिए, अन्यथा अगली प्रक्रिया माता-पिता की अक्षम स्थिति को इनहेरिट करेगी और Ctrl-C का जवाब नहीं देगी।

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();

[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);

delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);

// Enumerated type for the control messages sent to the handler routine
enum CtrlTypes : uint
{
  CTRL_C_EVENT = 0,
  CTRL_BREAK_EVENT,
  CTRL_CLOSE_EVENT,
  CTRL_LOGOFF_EVENT = 5,
  CTRL_SHUTDOWN_EVENT
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);

public void StopProgram(Process proc)
{
  //This does not require the console window to be visible.
  if (AttachConsole((uint)proc.Id))
  {
    // Disable Ctrl-C handling for our program
    SetConsoleCtrlHandler(null, true); 
    GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);

    //Moved this command up on suggestion from Timothy Jannace (see comments below)
    FreeConsole();

    // Must wait here. If we don't and re-enable Ctrl-C
    // handling below too fast, we might terminate ourselves.
    proc.WaitForExit(2000);

    //Re-enable Ctrl-C handling or any subsequently started
    //programs will inherit the disabled state.
    SetConsoleCtrlHandler(null, false); 
  }
}

इसके अलावा, आकस्मिक समाधान के लिए योजना अगर AttachConsole()या भेजा संकेत विफल हो, उदाहरण के लिए सो तो यह चाहिए:

if (!proc.HasExited)
{
  try
  {
    proc.Kill();
  }
  catch (InvalidOperationException e){}
}

4
इससे प्रेरित होकर, मैंने एक "स्टैंडअलोन" सीपीपी ऐप बनाया जो इसे करता है: gist.github.com/rdp/f51fb274d69c5c31b6be मामले में यह उपयोगी है। और हाँ, यह विधि ctrl + c या ctrl + break को "कोई भी" pid, जाहिरा तौर पर भेज सकती है।
रोज़गारपैक

DLL आयात "SetConsoleCtrlHandler" में से एक को याद कर रहा है, लेकिन यह काम नहीं करता है।
डर्फ़ स्क्रेन

उत्कृष्ट पोस्ट। उत्कृष्ट ब्लॉग। मैं आपके प्रयोग कार्यक्रम में StopProgramWithInv अदृश्यWindowUsingPinvoke फ़ंक्शन को पूरा करने का सुझाव दूंगा। मैंने इस विचार को लगभग त्याग दिया कि आपको कोई हल नहीं मिला है
विल्मर सेंट

बचने के लिए wait()मैंने री-इनेबल Ctrl-C ( SetConsoleCtrlHandler(null, false);) को हटा दिया । मैंने कुछ परीक्षण किए (कई कॉल, पहले से ही समाप्त प्रक्रियाओं पर भी) और मुझे कोई साइड इफेक्ट (अभी तक?) नहीं मिला।
56ka

GenerateConsoleCtrlEvent भेजने के तुरंत बाद FreeConsole को कॉल किया जाना चाहिए। जब तक यह नहीं कहा जाता है, तब तक आपका एप्लिकेशन दूसरे कंसोल से जुड़ा होगा। यदि आपके आवेदन को बंद करने से पहले अन्य कंसोल को मार दिया जाता है, तो आपके आवेदन को भी समाप्त कर दिया जाएगा!
तीमुथियुस जनाज़े

17

मुझे लगता है कि मुझे इस सवाल पर थोड़ी देर हो गई है, लेकिन मैं किसी को भी उसी समस्या के लिए कुछ भी लिखूंगा। यह वही उत्तर है जैसा मैंने इस प्रश्न को दिया था ।

मेरी समस्या यह थी कि मैं अपने आवेदन को जीयूआई अनुप्रयोग बनाना चाहूंगा लेकिन निष्पादित प्रक्रियाओं को पृष्ठभूमि में बिना किसी संवादात्मक कंसोल विंडो के चलाया जाना चाहिए। मुझे लगता है कि यह समाधान तब भी काम करना चाहिए जब मूल प्रक्रिया कंसोल प्रक्रिया हो। हालाँकि आपको "CREATE_NO_WINDOW" झंडे को हटाना पड़ सकता है।

मैं एक आवरण एप्लिकेशन के साथ GenerateConsoleCtrlEvent () का उपयोग करके इसे हल करने में कामयाब रहा । मुश्किल हिस्सा सिर्फ इतना है कि प्रलेखन वास्तव में बिल्कुल स्पष्ट नहीं है कि इसका उपयोग कैसे किया जा सकता है और इसके साथ नुकसान हो सकता है।

मेरा समाधान यहाँ वर्णित है पर आधारित है । लेकिन यह वास्तव में या तो एक त्रुटि के साथ सभी विवरणों की व्याख्या नहीं करता है, इसलिए यहां यह विवरण है कि इसे कैसे काम करना है।

एक नया सहायक एप्लिकेशन "Helper.exe" बनाएं। यह एप्लिकेशन आपके एप्लिकेशन (पैरेंट) और उस बच्चे की प्रक्रिया के बीच बैठेगा जिसे आप बंद करने में सक्षम होना चाहते हैं। यह वास्तविक बाल प्रक्रिया भी बनाएगा। आपके पास यह "मध्यम पुरुष" प्रक्रिया होनी चाहिए या GenerateConsoleCtrlEvent () विफल हो जाएगी।

माता-पिता से हेल्पर प्रक्रिया तक संचार करने के लिए किसी प्रकार के आईपीसी तंत्र का उपयोग करें कि सहायक बच्चे की प्रक्रिया को बंद कर दे। जब सहायक को यह घटना मिलती है, तो वह "GenerateConsoleCtrlEvent (CTRL_BREAK, 0)" को कॉल करता है जो स्वयं और बच्चे की प्रक्रिया को बंद कर देता है। मैंने स्वयं इसके लिए एक ईवेंट ऑब्जेक्ट का उपयोग किया, जिसे माता-पिता तब पूरा करते हैं जब वह बच्चे की प्रक्रिया को रद्द करना चाहता है।

अपना Helper.exe बनाने के लिए इसे CREATE_NO_WINDOW और CREATE_NEW_PROCESS_GROUP के साथ बनाएं। और जब बच्चे की प्रक्रिया बनाते हैं तो इसे बिना झंडे (0) के साथ बनाते हैं, जिसका अर्थ है कि यह अपने माता-पिता से सांत्वना प्राप्त करेगा। ऐसा करने में विफल होने से यह घटना को अनदेखा कर देगा।

यह बहुत महत्वपूर्ण है कि प्रत्येक चरण इस तरह से किया जाता है। मैं सभी प्रकार के संयोजनों की कोशिश कर रहा हूं, लेकिन यह संयोजन केवल एक ही है जो काम करता है। आप CTRL_C ईवेंट नहीं भेज सकते हैं। यह सफलता लौटाएगा लेकिन इस प्रक्रिया को नजरअंदाज कर दिया जाएगा। CTRL_BREAK केवल वही है जो काम करता है। वास्तव में कोई फर्क नहीं पड़ता क्योंकि वे दोनों एक्सिटप्रोसेस () को अंत में कहेंगे।

आप GenerateConsoleCtrlEvent () को चाइल्ड प्रोसेस आईडी के प्रोसेस ग्रुप आईडी के साथ सीधे हेल्पर प्रक्रिया को जारी रखने की अनुमति नहीं दे सकते। यह भी विफल हो जाएगा।

मैंने पूरा दिन इस काम में लगा दिया। यह समाधान मेरे लिए काम करता है लेकिन अगर किसी के पास कृपया जोड़ने के लिए कुछ और है। मैं सभी समान समस्याओं वाले बहुत से लोगों को खोजने के लिए नेट पर गया था लेकिन समस्या का कोई निश्चित समाधान नहीं था। GenerateConsoleCtrlEvent () कैसे काम करता है यह भी थोड़ा अजीब है, अगर किसी को इस पर अधिक जानकारी पता है तो कृपया साझा करें।


6
समाधान के लिए धन्यवाद! यह अभी तक विंडोज एपीआई का एक और उदाहरण है कि यह इतना भयानक गड़बड़ है।
vitaut

8

संपादित करें:

GUI ऐप के लिए, विंडोज के विकास में इसे संभालने का "सामान्य" तरीका प्रक्रिया की मुख्य विंडो पर WM_CLOSE संदेश भेजना होगा।

कंसोल ऐप के लिए, आपको जोड़ने के लिए SetConsoleCtrlHandler का उपयोग करना होगा CTRL_C_EVENT

यदि एप्लिकेशन ऐसा नहीं करता है, तो आप टर्मिनेटप्रोसेस को कॉल कर सकते हैं ।


मैं यह कमांड-लाइन ऐप (कोई विंडोज़ नहीं) में करना चाहता हूं। टर्मिनेटप्रोसेस एक फोर्स किल मैकेनिज्म (SIGKILL के समान) है, इसलिए टर्मिनेटिंग एप्लिकेशन को सफाई का कोई अवसर नहीं दिया जाता है।
मैथ्यू मर्डोक

@ मैट्टू मर्डोक: कंसोल ऐप में इसे कैसे हैंडल करना है, इसकी जानकारी शामिल करना। आप एक ही तंत्र के माध्यम से विंडोज़ शटडाउन, या कंसोल बंद आदि सहित अन्य घटनाओं को भी पकड़ सकते हैं। पूर्ण विवरण के लिए MSDN देखें।
रीड कोपसे

@ लीड कोपसी: लेकिन मैं इसे एक अलग प्रक्रिया से शुरू करना चाहता हूं। मैंने GenerateConsoleCtrlEvent (SetConsoleCtrlHandler से संदर्भित) पर एक नज़र डाली है, लेकिन यह केवल तभी काम करता है जब प्रक्रिया को समाप्त किया जा रहा है एक ही 'प्रक्रिया समूह' में इस प्रक्रिया को समाप्त करने की प्रक्रिया है ... कोई विचार?
मैथ्यू मर्डोक

1
मैथ्यू: इस प्रक्रिया को खोजने के लिए मेरे पास एकमात्र विचार यह होगा कि यह अभिभावक (कंसोल) ढूंढें, माता-पिता की मुख्य विंडो हैंडल (कंसोल) प्राप्त करें और इसे सीधे Ctrl + C भेजने के लिए SendKeys का उपयोग करें। CTRL_C_EVENT प्राप्त करने के लिए आपकी कंसोल प्रक्रिया का कारण होना चाहिए। हालांकि, यह कोशिश नहीं की है - यकीन नहीं है कि यह कितना अच्छा काम करेगा।
रीड कोपसे

यहाँ एक C ++ SendKeys stackoverflow.com/questions/6838363/… के बराबर है, यह भी देखें stackoverflow.com/questions/10407769/… हालांकि स्पष्ट रूप से यह तब भी काम करने की गारंटी नहीं है ...
rogerdpack

7

GenerateConsoleCtrlEvent()यदि आप इसे किसी अन्य प्रक्रिया के लिए कहते हैं, तो किसी तरह से त्रुटि वापस आती है, लेकिन आप किसी अन्य कंसोल एप्लिकेशन से जुड़ सकते हैं और सभी चाइल्ड प्रोसेस को ईवेंट भेज सकते हैं।

void SendControlC(int pid)
{
    AttachConsole(pid); // attach to process console
    SetConsoleCtrlHandler(NULL, TRUE); // disable Control+C handling for our app
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // generate Control+C event
}

और नियंत्रण वापस कैसे करें? और फिर मैं कंट्रोल-सी, स्टॉपर प्रोग्राम भेजता हूं, लेकिन मैं उसके हाथों से कुछ नहीं कर सकता।
यारोस्लाव एल।

नियंत्रण वापस कहाँ करें?
KindDragon

मुझे लगता है कि आप अपने हैंडलर को हटाने के लिए SetConsoleCtrlHandler (NULL, FALSE) को कॉल करते हैं, विभिन्न प्रतिक्रियाओं को देखें।
रॉगरडपैक

6

यहाँ कोड का उपयोग मैं अपने C ++ ऐप में कर रहा हूँ।

सकारात्मक अंक:

  • कंसोल ऐप से काम करता है
  • विंडोज सेवा से काम करता है
  • कोई देरी की आवश्यकता है
  • वर्तमान एप्लिकेशन को बंद नहीं करता है

नकारात्मक अंक:

  • मुख्य कंसोल खो गया है और एक नया बनाया गया है ( FreeConsole देखें )
  • कंसोल स्विचिंग अजीब परिणाम देता है ...

// Inspired from http://stackoverflow.com/a/15281070/1529139
// and http://stackoverflow.com/q/40059902/1529139
bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent)
{
    bool success = false;
    DWORD thisConsoleId = GetCurrentProcessId();
    // Leave current console if it exists
    // (otherwise AttachConsole will return ERROR_ACCESS_DENIED)
    bool consoleDetached = (FreeConsole() != FALSE);

    if (AttachConsole(dwProcessId) != FALSE)
    {
        // Add a fake Ctrl-C handler for avoid instant kill is this console
        // WARNING: do not revert it or current program will be also killed
        SetConsoleCtrlHandler(nullptr, true);
        success = (GenerateConsoleCtrlEvent(dwCtrlEvent, 0) != FALSE);
        FreeConsole();
    }

    if (consoleDetached)
    {
        // Create a new console if previous was deleted by OS
        if (AttachConsole(thisConsoleId) == FALSE)
        {
            int errorCode = GetLastError();
            if (errorCode == 31) // 31=ERROR_GEN_FAILURE
            {
                AllocConsole();
            }
        }
    }
    return success;
}

उपयोग उदाहरण:

DWORD dwProcessId = ...;
if (signalCtrl(dwProcessId, CTRL_C_EVENT))
{
    cout << "Signal sent" << endl;
}

4
        void SendSIGINT( HANDLE hProcess )
        {
            DWORD pid = GetProcessId(hProcess);
            FreeConsole();
            if (AttachConsole(pid))
            {
                // Disable Ctrl-C handling for our program
                SetConsoleCtrlHandler(NULL, true);

                GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // SIGINT

                //Re-enable Ctrl-C handling or any subsequently started
                //programs will inherit the disabled state.
                SetConsoleCtrlHandler(NULL, false);

                WaitForSingleObject(hProcess, 10000);
            }
        }

2

यह क्रिस्टल स्पष्ट किया जाना चाहिए क्योंकि इस समय यह नहीं है। Ctrl-C भेजने के लिए SendSignal का एक संशोधित और संकलित संस्करण है (डिफ़ॉल्ट रूप से यह केवल Ctrl + ब्रेक भेजता है)। यहाँ कुछ बायनेरिज़ हैं:

(2014-3-7): मैंने Ctrl-C के साथ 32-बिट और 64-बिट संस्करण का निर्माण किया, इसे SendSignalCtrlC.exe कहा जाता है और आप इसे यहां डाउनलोड कर सकते हैं: https://dl.dropboxusercontent.com/u/49057777/ Sendignalctrlc / x86 / SendSignalCtrlC.exe https://dl.dropboxusercontent.com/u/49065779/sendignalctrlc/x86_64/SendSignalttrlC.exe - Juraj Michalak

मैंने उन फ़ाइलों को केवल मामले में देखा है:
32-बिट संस्करण: https://www.dropbox.com/s/r96jxglhkm4sjz2/SendSignalCtrlC.exe?dl=0
64-बिट संस्करण: https://www.dropbox.com /s/hhe0io7mcgcle1c/SendSignalCtrlC64.exe?dl=0

अस्वीकरण: मैंने उन फ़ाइलों का निर्माण नहीं किया। संकलित मूल फाइलों में कोई संशोधन नहीं किया गया था। परीक्षण किया गया एकमात्र प्लेटफॉर्म 64-बिट विंडोज 7 है। यह http://www.latenighthacking.com/projects/2003/sendSignal/ पर उपलब्ध स्रोत को अनुकूलित करने और इसे स्वयं संकलित करने की सिफारिश की गई है ।


2

जावा में, कर्नेल 32.dll लाइब्रेरी के साथ JNA का उपयोग करते हुए, C ++ समाधान के समान। CtrlCSender मुख्य विधि को एक प्रक्रिया के रूप में चलाता है जो सिर्फ Ctrl + C ईवेंट को भेजने और ईवेंट को बनाने के लिए प्रक्रिया का कंसोल प्राप्त करता है। चूंकि यह कंसोल के बिना अलग से चलता है इसलिए Ctrl + C ईवेंट को अक्षम और फिर से सक्षम करने की आवश्यकता नहीं है।

CtrlCSender.java - निमो 1024 और किंडरड्रैगन के उत्तरों पर आधारित है।

एक ज्ञात प्रक्रिया आईडी को देखते हुए, यह सांत्वना एप्लिकेशन लक्षित प्रक्रिया के कंसोल को संलग्न करेगा और उस पर एक CTRL + C ईवेंट उत्पन्न करेगा।

import com.sun.jna.platform.win32.Kernel32;    

public class CtrlCSender {

    public static void main(String args[]) {
        int processId = Integer.parseInt(args[0]);
        Kernel32.INSTANCE.AttachConsole(processId);
        Kernel32.INSTANCE.GenerateConsoleCtrlEvent(Kernel32.CTRL_C_EVENT, 0);
    }
}

मुख्य अनुप्रयोग - एक अलग सांत्वना प्रक्रिया के रूप में CtrlCSender चलाता है

ProcessBuilder pb = new ProcessBuilder();
pb.command("javaw", "-cp", System.getProperty("java.class.path", "."), CtrlCSender.class.getName(), processId);
pb.redirectErrorStream();
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
Process ctrlCProcess = pb.start();
ctrlCProcess.waitFor();

हम्म, अगर मैं इसे एक पॉलीशेल प्रक्रिया के खिलाफ चलाता हूं तो यह प्रक्रिया जीवित रहती है। दूसरी ओर, दिलचस्प रूप से, जेवीएम पर इन-प्रोसेस रनिंग वास्तव में वीएम को नीचे लाता है! क्या आपके पास कोई विचार है कि क्यों एक पॉवरशेल प्रक्रिया इस तकनीक का जवाब नहीं देगी?
ग्रोस्तव

2

हाँ। windows-killपरियोजना वास्तव में करता है कि आप क्या चाहते:

windows-kill -SIGINT 1234

इस परियोजना में यहाँ डाउनलोड करने के लिए रिलीज़ बायनेरिज़ का उपयोग करने के लिए तैयार शामिल हैं: github.com/alirdn/windows-kill/releases - इस उत्तर में और अधिक
अपडेट

1

एक समाधान जो मैंने यहाँ से पाया है वह बहुत सरल है यदि आपके पास आपकी कमांड लाइन में अजगर 3.x उपलब्ध है। सबसे पहले, एक फ़ाइल (ctrl_c.py) सामग्री के साथ सहेजें:

import ctypes
import sys

kernel = ctypes.windll.kernel32

pid = int(sys.argv[1])
kernel.FreeConsole()
kernel.AttachConsole(pid)
kernel.SetConsoleCtrlHandler(None, 1)
kernel.GenerateConsoleCtrlEvent(0, 0)
sys.exit(0)

फिर कॉल करो:

python ctrl_c.py 12345

अगर वह काम नहीं करता है, तो मैं विंडोज़-किल प्रोजेक्ट को आज़माने की सलाह देता हूं: https://github.com/alirdn/windows-kill


0

मेरे एक दोस्त ने समस्या को हल करने का एक अलग तरीका सुझाया और यह मेरे लिए काम कर गया। नीचे दिए गए शब्द का उपयोग करें। यह शुरू होता है और आवेदन करता है, इसे 7 सेकंड तक चलने दें और ctrl + c का उपयोग करके इसे बंद कर दें ।

'VBScript उदाहरण

Set WshShell = WScript.CreateObject("WScript.Shell")

WshShell.Run "notepad.exe"

WshShell.AppActivate "notepad"

WScript.Sleep 7000

WshShell.SendKeys "^C"

यह काम करता है यदि एप्लिकेशन में एक विंडो है तो आप AppActive (अग्रभूमि में ला सकते हैं)।
रोगरडपैक

0

मैंने यह सब बहुत जटिल पाया और SendKeys को एक वर्कअराउंड के रूप में कमांड लाइन विंडो (यानी cmd.exe विंडो) में एक की CTRL- Cस्ट्रोक भेजने के लिए इस्तेमाल किया ।


0
// Send [CTRL-C] to interrupt a batch file running in a Command Prompt window, even if the Command Prompt window is not visible,
// without bringing the Command Prompt window into focus.
// [CTRL-C] will have an effect on the batch file, but not on the Command Prompt  window itself -- in other words,
// [CTRL-C] will not have the same visible effect on a Command Prompt window that isn't running a batch file at the moment
// as bringing a Command Prompt window that isn't running a batch file into focus and pressing [CTRL-C] on the keyboard.
ulong ulProcessId = 0UL;
// hwC = Find Command Prompt window HWND
GetWindowThreadProcessId (hwC, (LPDWORD) &ulProcessId);
AttachConsole ((DWORD) ulProcessId);
SetConsoleCtrlHandler (NULL, TRUE);
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0UL);
SetConsoleCtrlHandler (NULL, FALSE);
FreeConsole ();

0

SIGINT को सिंटैक्स द्वारा विंडोज़-किल , प्रोग्राम का उपयोग करके भेजा जा सकता है windows-kill -SIGINT PID, जहाँ PIDMicrosoft के pslist द्वारा प्राप्त किया जा सकता है ।

SIGINTs को पकड़ने के बारे में, अगर आपका प्रोग्राम Python में है तो आप इस समाधान में SIGINT प्रसंस्करण / पकड़ने को लागू कर सकते हैं


-1

प्रोसेस आईडी के आधार पर, हम जबरदस्ती या इनायत या किसी अन्य सिग्नल को समाप्त करने के लिए प्रक्रिया को सिग्नल भेज सकते हैं।

सभी प्रक्रिया को सूचीबद्ध करें:

C:\>tasklist

प्रक्रिया को मारने के लिए:

C:\>Taskkill /IM firefox.exe /F
or
C:\>Taskkill /PID 26356 /F

विवरण:

http://tweaks.com/windows/39559/kill-processes-from-command-prompt/


वास्तव में इस sigterm भेजता है?
टेकनोपुल

टास्किल CTRL-C नहीं भेजता है। Windows संकेतों की जाँच करें।
जोसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.