আমি কি উইন্ডোজের একটি অ্যাপ্লিকেশনটিতে একটি সিটিআরএল-সি (সিগিন্ট) প্রেরণ করতে পারি?


91

আমার কাছে (অতীতে) লিখিত ক্রস-প্ল্যাটফর্ম (উইন্ডোজ / ইউনিক্স) অ্যাপ্লিকেশন রয়েছে যা কমান্ড লাইন থেকে শুরু করার সাথে সাথে একটি ব্যবহারকারী-টাইপড পরিচালনা করে Ctrl - Cএকই পদ্ধতিতে সমন্বয় করে (অর্থাত্ পরিষ্কারভাবে অ্যাপ্লিকেশনটি সমাপ্ত করতে)।

এটা Windows এ সম্ভব একটি পাঠাতে Ctrl- Cঅনুরোধ অন্য (সম্পর্কহীন) প্রক্রিয়া থেকে একটি প্রক্রিয়া / SIGINT / সমমান এটি পরিচ্ছন্ন বিনষ্ট (এটা সম্পদ ইত্যাদি আপ পরিপাটি একটি সুযোগ দান)?


4
আমি কেবল থ্রেডডাম্পগুলি পেতে জাভা পরিষেবা প্রসেসগুলিতে Ctrl-C প্রেরণে আগ্রহী ছিলাম। এটি প্রদর্শিত হয় যা jstackএই নির্দিষ্ট বিষয়টির পরিবর্তে নির্ভরযোগ্যতার সাথে ব্যবহার করা যেতে পারে: stackoverflow.com/a/47723393/603516
ভাদজিম

উত্তর:


31

আমি সলিউশনে যে নিকটে এসেছি সেটি হ'ল সেন্ড সিগন্যাল 3 য় পক্ষের অ্যাপ। লেখক উত্স কোড এবং একটি এক্সিকিউটেবল তালিকাবদ্ধ। আমি যাচাই করেছি যে এটি 64৪-বিট উইন্ডোর অধীনে কাজ করে (৩২-বিট প্রোগ্রাম হিসাবে চলমান, অন্য ৩২-বিট প্রোগ্রামটি হত্যা করে) তবে কীভাবে কোডটি উইন্ডোজ প্রোগ্রামে এম্বেড করা যায় তা আমি বের করতে পারি না (হয় 32-বিট হয়) বা -৪-বিট)।

কিভাবে এটা কাজ করে:

ডিবাগারে প্রায় খনন করার পরে আমি আবিষ্কার করেছি যে এন্ট্রি পয়েন্টটি আসলে সিটিআরএল-ব্রেকের মতো সিগন্যালের সাথে সম্পর্কিত আচরণটি কর্নেল 32! CtrlRoutine। ফাংশনে থ্রেডপ্রোকের মতো একই প্রোটোটাইপ ছিল, সুতরাং এটি কোড ইনজেক্ট না করে সরাসরি ক্রিয়েট্রেমোটথ্রেডের সাথে ব্যবহার করা যেতে পারে। তবে, এটি কোনও রফতানি প্রতীক নয়! এটি উইন্ডোজের বিভিন্ন সংস্করণে বিভিন্ন ঠিকানায় (এবং এমনকি বিভিন্ন নামও রয়েছে) রয়েছে। কি করো?

এই সমাধানটি আমি শেষ পর্যন্ত নিয়ে এসেছি। আমি আমার অ্যাপ্লিকেশনের জন্য একটি কনসোল সিটিআরএল হ্যান্ডলার ইনস্টল করি, তারপরে আমার অ্যাপ্লিকেশনের জন্য একটি সিটিআরএল-ব্রেক সিগন্যাল তৈরি করি। যখন আমার হ্যান্ডলারটি কল হবে, আমি কার্নেল 32 এ পরামিতিগুলি পরামিতিগুলি অনুসন্ধান করতে স্ট্যাকের শীর্ষে ফিরে তাকাব! বেসথ্রেডস্টার্ট। আমি প্রথম প্যারাম ধরলাম, যা থ্রেডের পছন্দসই সূচনা ঠিকানা, যা কার্নেল 32 এর ঠিকানা! CtrlRoutine। তারপরে আমি আমার হ্যান্ডলার থেকে ফিরে আসছি, এটি নির্দেশ করে যে আমি সিগন্যালটি পরিচালনা করেছি এবং আমার অ্যাপ্লিকেশনটি শেষ করা উচিত নয়। মূল থ্রেডে ফিরে, আমি কার্নেল 32 এর ঠিকানা না পাওয়া পর্যন্ত অপেক্ষা করব! CtrlRoutine পুনরুদ্ধার করা হবে। আমি এটি পেয়ে গেলে, আমি আবিষ্কারের শুরুর ঠিকানা দিয়ে লক্ষ্য প্রক্রিয়ায় একটি দূরবর্তী থ্রেড তৈরি করি। এটি লক্ষ্য প্রক্রিয়ায় সিআরটিএল হ্যান্ডলারগুলি এমনভাবে মূল্যায়িত করে যে সিটিআরএল-ব্রেক চাপানো হয়েছে!

সুন্দর জিনিসটি হ'ল কেবলমাত্র লক্ষ্য প্রক্রিয়াটি প্রভাবিত হয় এবং যে কোনও প্রক্রিয়া (এমনকি একটি উইন্ডোড প্রক্রিয়াও) লক্ষ্যবস্তু হতে পারে। একটি খারাপ দিক হ'ল আমার ছোট অ্যাপটি ব্যাচ ফাইলে ব্যবহার করা যাবে না, কারণ এটি কার্নেল 32 এর ঠিকানা আবিষ্কার করার জন্য সিটিটিএল-ব্রেক ইভেন্ট প্রেরণ করলে এটি মারা যাবে!

(এটি startএকটি ব্যাচ ফাইলের মধ্যে চালনা করা হয় যদি আগে তা আগে।)


4
+1 - লিঙ্কযুক্ত কোডটি Ctrl-C ব্যবহার না করে Ctrl-Break ব্যবহার করে তবে এর মুখে (GenerateConsoleCtrlEvent এর জন্য ডকুমেন্টেশন দেখে) Ctrl-C এর জন্য অভিযোজিত হতে পারে।
ম্যাথু মারডোক

8
আসলে আপনার জন্য এটি করার একটি ফাংশন রয়েছে, হ্যাঁ, "জেনারেটকনসোলসিআরটিএলেন্ট"। দেখুন: msdn.microsoft.com/en-us/library/ms683155(v=vs.85).aspx এখানে আরও দেখুন আমার উত্তর: serverfault.com/a/501045/10023
Triynko

4
উপরের উত্তর সম্পর্কিত গিথুব
meawoppl

4
এটি মনের মধ্যে বিস্মিত হয় যে উইন্ডোজ যতটা পুরানো তারপরেও মাইক্রোসফ্ট কনসোল অ্যাপ্লিকেশন বি থেকে একটি সংকেত শোনার জন্য কনসোল অ্যাপ্লিকেশন এ-এর জন্য কোনও ব্যবস্থা সরবরাহ করেনি যাতে কনসোল অ্যাপ্লিকেশন বি কনসোল অ্যাপ্লিকেশন এটিকে পরিষ্কারভাবে শাটডাউন করতে বলতে পারে। যে কোনও ইভেন্টে, এমএস -কে বাশিত করে, আমি প্রেরণ সিগন্যাল চেষ্টা করেছি এবং "ক্রিয়েটরেমোটথ্রেড 0x00000005 দিয়ে ব্যর্থ হয়েছে"। সিগন্যাল শোনার জন্য অ্যাপ্লিকেশন এ কোড কীভাবে করা যায় সে সম্পর্কে অন্য কোনও ধারণা (সুবিধাজনক যে কোনও সংকেত) এবং কীভাবে এটি সিগন্যাল করবেন?
ডেভিড আই ম্যাকইনটোশ

4
@ ডেভিডআই.এমসিআইনটোশ মনে হচ্ছে আপনি উভয় প্রক্রিয়াতে একটি নামকৃত ইভেন্ট তৈরি করতে চান; আপনি তখন অন্যটির থেকে একটিতে সংকেত দিতে সক্ষম হবেন। ক্রিয়েটএভেন্টের জন্য ডকুমেন্টেশন চেক করুন
arolson101

58

আমি এই বিষয়টিকে ঘিরে কিছু গবেষণা করেছি, যা আমার প্রত্যাশার চেয়ে বেশি জনপ্রিয় হয়েছিল। KindDragon এর উত্তর ছিল মূল বিষয়গুলির মধ্যে একটি।

আমি এই বিষয়ে একটি দীর্ঘ ব্লগ পোস্ট লিখেছি এবং একটি ওয়ার্কিং ডেমো প্রোগ্রাম তৈরি করেছি, যা দেখায় যে এই ধরণের সিস্টেমটি কয়েক ফ্যাশনের মাধ্যমে একটি কমান্ড লাইন অ্যাপ্লিকেশনটি বন্ধ করতে হবে। এই পোস্টটি আমার গবেষণায় ব্যবহৃত বহিরাগত লিঙ্কগুলিও তালিকাভুক্ত করে।

সংক্ষেপে, এই ডেমো প্রোগ্রামগুলি নিম্নলিখিতটি করে:

  • । নেট ব্যবহার করে একটি দৃশ্যমান উইন্ডো দিয়ে একটি প্রোগ্রাম শুরু করুন, নেট, পিনভোক দিয়ে আড়াল করুন, 6 সেকেন্ড চলুন, পিনভোক দিয়ে দেখান, নেট দিয়ে থামুন stop
  • । নেট ব্যবহার করে উইন্ডো ছাড়া একটি প্রোগ্রাম শুরু করুন, 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 + ব্রেক প্রেরণ করতে পারে।
রজারডপ্যাক

ডিএলএলগুলির মধ্যে একটি অনুপস্থিত "সেটকনসোলসিআরটিএল হ্যান্ডলার" আমদানি করে তবে এটি কাজ করে।
Derb Skren

দুর্দান্ত পোস্ট দুর্দান্ত ব্লগ আমি আপনার পরীক্ষামূলক প্রোগ্রামের স্টপপ্রগ্রাম উইথআইনভিজিবল উইন্ডোউসিংপিনভোক ফাংশনটি শেষ করার পরামর্শ দেব। আপনি কোনও সমাধান খুঁজে পেয়েছেন না এই ভেবে আমি প্রায় এই ধারণাটি ত্যাগ করেছি
উইলমার সেন্ট

এড়াতে wait()আমি পুনরায় সক্ষম Ctrl-C সরিয়েছি (SetConsoleCtrlHandler(null, false); ) । আমি কয়েকটি পরীক্ষা করেছি (একাধিক কল, ইতিমধ্যে সমাপ্ত প্রক্রিয়াগুলিতেও) এবং আমি কোনও পার্শ্ব প্রতিক্রিয়া পাই নি (এখনও?)।
56ka

জেনারেটকনসোলসিআরটিএলটি পাঠানোর সাথে সাথেই ফ্রি কনসোলকে কল করা উচিত। এটি কল না হওয়া পর্যন্ত আপনার অ্যাপ্লিকেশনটি অন্য কনসোলের সাথে সংযুক্ত থাকবে। অন্য কনসোলটি বন্ধ হয়ে যাওয়ার আগে যদি মারা যায় তবে আপনার অ্যাপ্লিকেশনটিও বন্ধ হয়ে যাবে!
টিমোথি জান্নেস

17

আমার ধারণা আমি এই প্রশ্নে কিছুটা দেরি করেছি তবে যে কেউ একই সমস্যা রয়েছে তার জন্য আমি যাইহোক কিছু লিখব। আমি এই প্রশ্নের উত্তর হিসাবে এটি একই উত্তর ।

আমার সমস্যাটি হ'ল আমি চাইছিলাম আমার অ্যাপ্লিকেশনটি জিইউআই অ্যাপ্লিকেশন হোক তবে সম্পাদিত প্রক্রিয়াগুলি কোনও ইন্টারেক্টিভ কনসোল উইন্ডো সংযুক্ত না করে ব্যাকগ্রাউন্ডে চালানো উচিত। আমি মনে করি যখন পিতামাতার প্রক্রিয়াটি কনসোল প্রক্রিয়া হয় তখন এই সমাধানটিও কাজ করা উচিত। আপনাকে যদিও "CREATE_NO_WINDOW" পতাকাটি সরাতে হতে পারে।

আমি একটি মোড়কের অ্যাপ্লিকেশন সহ জেনারেটকনসোলসিআরটিএল () ব্যবহার করে এটি সমাধান করতে সক্ষম হয়েছি । জটিল অংশটি হ'ল ডকুমেন্টেশনটি কীভাবে এটি ব্যবহার করা যেতে পারে এবং এর সাথে কী কী সমস্যা রয়েছে সে সম্পর্কে প্রকৃতপক্ষে স্পষ্ট নয়।

আমার সমাধান এখানে বর্ণিত কিসের উপর ভিত্তি করে । তবে এটি কোনও ত্রুটি সহ সত্যই সমস্ত বিবরণ ব্যাখ্যা করে না, সুতরাং এটি কীভাবে কাজ করা যায় সে সম্পর্কে বিশদ এখানে।

একটি নতুন সহায়ক অ্যাপ্লিকেশন "হেল্পার। এক্স" তৈরি করুন। এই অ্যাপ্লিকেশনটি আপনার অ্যাপ্লিকেশন (পিতামাতা) এবং আপনি যে শিশু প্রক্রিয়াটি বন্ধ করতে সক্ষম হতে চান তার মধ্যে বসবে। এটি আসল শিশু প্রক্রিয়াও তৈরি করবে। আপনার অবশ্যই এই "মিডল ম্যান" প্রক্রিয়া বা জেনারেটকনসোলসিআরটিএলেন্ট () ব্যর্থ হবে।

অভিভাবক থেকে সহায়তাকারী প্রক্রিয়াটিতে যোগাযোগের জন্য কোনও ধরণের আইপিসি মেকানিজম ব্যবহার করুন যা সহায়কটির সন্তানের প্রক্রিয়াটি বন্ধ করা উচিত। সহায়ক যখন এই ইভেন্টটি পাবে তখন এটি "জেনারেটকনসোলসিআরটিএলেন্ট (সিটিআরএল_BREAK, 0)" কল করে যা নিজে এবং শিশু প্রক্রিয়াটি বন্ধ করে দেয়। আমি এটির জন্য নিজের জন্য একটি ইভেন্ট অবজেক্টটি ব্যবহার করেছি যা সন্তানের প্রক্রিয়া বাতিল করতে চাইলে পিতামাতার সম্পূর্ণ হয়।

আপনার হেল্পার তৈরি করতে। এক্সই CREATE_NO_WINDOW এবং CREATE_NEW_PROCESS_GROUP দিয়ে এটি তৈরি করুন। এবং শিশু প্রক্রিয়া তৈরি করার সময় এটিকে কোনও পতাকা (0) দিয়ে তৈরি করুন যার অর্থ এটি তার পিতামাতার কাছ থেকে কনসোলটি গ্রহণ করবে। এটি করতে ব্যর্থ হওয়ায় এটি ইভেন্টটিকে উপেক্ষা করবে।

প্রতিটি পদক্ষেপটি এইভাবে করা খুব জরুরি is আমি বিভিন্ন ধরণের সংমিশ্রণ চেষ্টা করে যাচ্ছি তবে এই সংমিশ্রণটি কেবলমাত্র কাজ করে। আপনি কোনও CTRL_C ইভেন্ট প্রেরণ করতে পারবেন না। এটি সাফল্য ফিরে আসবে তবে প্রক্রিয়া দ্বারা উপেক্ষা করা হবে। CTRL_BREAK একমাত্র কাজ করে। তারা উভয়ই শেষ পর্যন্ত এক্সিটপ্রসেস () কল করবে তাই আসলে কিছু যায় আসে না।

আপনি সরাসরি শিশু প্রক্রিয়া আইডির একটি প্রসেস গ্রুপড আইডি সহ জেনারেটকনসোলসিআরএলভেন্ট () কে কল করতে পারবেন না সরাসরি সাহায্যকারী প্রক্রিয়া চালিয়ে যাওয়ার অনুমতি দেয়। এটি পাশাপাশি ব্যর্থ হবে।

আমি এই কাজটি করার চেষ্টা করে পুরো দিন কাটিয়েছি। এই সমাধানটি আমার পক্ষে কাজ করে তবে যদি কারও কাছে যোগ করার মতো অন্য কিছু থাকে তবে দয়া করে করুন। আমি একই রকম সমস্যাযুক্ত অনেক লোককে খুঁজে পেয়ে নেট ঘুরে দেখলাম, তবে সমস্যার কোনও নির্দিষ্ট সমাধান নেই। জেনারেটকনসোলসিআরটিএলভেন্ট () কীভাবে কাজ করে তাও কিছুটা অদ্ভুত তাই কেউ যদি এ সম্পর্কে আরও বিশদ জেনে থাকে তবে দয়া করে শেয়ার করুন।


6
সমাধানের জন্য ধন্যবাদ! উইন্ডোজ এপিআই এর এত ভয়ঙ্কর জগাখিচুড়ি হওয়ার এটি আরও একটি উদাহরণ।
ভিটাউট

8

সম্পাদনা করুন:

একটি জিইউআই অ্যাপ্লিকেশানের জন্য, উইন্ডোজ বিকাশের ক্ষেত্রে এটি পরিচালনা করার "স্বাভাবিক" উপায়টি হ'ল প্রক্রিয়াটির মূল উইন্ডোয় একটি ডব্লুএম_সিএলএসইএস বার্তা প্রেরণ করা হবে।

একটি কনসোল অ্যাপ্লিকেশন জন্য, আপনি ব্যবহার করতে হবে SetConsoleCtrlHandler একটি যোগ করার জন্যCTRL_C_EVENT

যদি অ্যাপ্লিকেশন এটি সম্মান করে না, আপনি টার্মিনেটপ্রসেস কল করতে পারেন ।


আমি কমান্ড-লাইন অ্যাপে (উইন্ডো নেই) এটি করতে চাই টার্মিনেটপ্রোসেস একটি ফোর্স কিল মেকানিজম (সিগ্কিলের অনুরূপ) তাই সমাপ্তি অ্যাপ্লিকেশনটিকে পরিষ্কার করার কোনও সুযোগ দেয় না।
ম্যাথিউ মুরডোক

@ ম্যাথেজ মুরডোক: কীভাবে এটি কনসোল অ্যাপ্লিকেশনটিতে পরিচালনা করতে হয় তার তথ্য অন্তর্ভুক্ত করার জন্য আপডেট হয়েছে। আপনি একই প্রক্রিয়াটির মাধ্যমে উইন্ডোজ শাটডাউন, বা কনসোল বন্ধ ইত্যাদি সহ অন্যান্য ইভেন্টগুলিও ধরতে পারেন। পূর্ণ বিবরণের জন্য এমএসডিএন দেখুন।
রিড কোপসী

@ রিড কোপসি: তবে আমি এটি একটি পৃথক প্রক্রিয়া থেকে শুরু করতে চাই। আমি জেনারেটকনসোলসিআরটিএলভেন্ট (সেটকনসোলসিআরটিএলএইচেন্ডার থেকে রেফারেন্স করা) দেখেছি তবে প্রক্রিয়াটি সমাপ্ত হওয়া প্রক্রিয়াটি সমাপ্তির মতো একই 'প্রক্রিয়া গ্রুপে' থাকলে কেবল কাজ করা মনে হয় ... কোনও ধারণা?
ম্যাথু মুরডোক 21

4
ম্যাথু: কেবলমাত্র আমি ধারণাটি হ'ল প্রক্রিয়াটি সন্ধান করা, এটির প্যারেন্ট (কনসোল) সন্ধান করা, পিতা-মাতার প্রধান উইন্ডো হ্যান্ডেল (কনসোল) পাওয়া এবং এটিতে সরাসরি Ctrl + C প্রেরণের জন্য সেন্ডকি ব্যবহার করুন। এটির ফলে আপনার কনসোল প্রক্রিয়াটি একটি CTRL_C_EVENT নেবে receive এটি চেষ্টা করে দেখেনি, যদিও - এটি কতটা ভাল কাজ করবে তা নিশ্চিত নয়।
রিড কোপসি

এখানে একটি সি এর ++, 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

আমি মনে করি আপনি আপনার হ্যান্ডলারটি সরাতে সেটকনসোলসিআরটিএল হ্যান্ডলারকে (NULL, FALSE) কল করেছেন, অন্যান্য বিভিন্ন প্রতিক্রিয়া দেখুন।
রজারডপ্যাক

6

আমি আমার সি ++ অ্যাপ্লিকেশনটিতে কোডটি এখানে ব্যবহার করব।

ইতিবাচক বিষয়:

  • কনসোল অ্যাপ থেকে কাজ করে
  • উইন্ডোজ পরিষেবা থেকে কাজ করে
  • কোন বিলম্ব প্রয়োজন
  • বর্তমান অ্যাপটি বন্ধ করে না

নেতিবাচক পয়েন্ট:

  • মূল কনসোলটি হারিয়ে গেছে এবং একটি নতুন তৈরি করা হয়েছে (দেখুন ফ্রি কনসোল )
  • কনসোল স্যুইচিং অদ্ভুত ফলাফল দেয় ...

// 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 প্রেরণের জন্য সেন্ডসিগনালের একটি সংশোধিত এবং সংকলিত সংস্করণ রয়েছে (ডিফল্টরূপে এটি কেবলমাত্র Ctrl + ব্রেক প্রেরণ করে)। এখানে কিছু বাইনারি রয়েছে:

(২০১৪-৩-:): আমি 32-বিট এবং 64-বিট উভয় সংস্করণ Ctrl-C দিয়ে তৈরি করেছি, একে সেন্ডসাইনালসিআরটিএলসি.এক্সই বলা হয় এবং আপনি এটি এখানে ডাউনলোড করতে পারেন: https://dl.rodboxusercontent.com/u/49065779/ sendsignalctrlc / x86 / SendSignalCtrlC.exe https://dl.rodboxusercontent.com/u/49065779/sendsignalctrlc/x86_64/SendSignalCtrlC.exe - জুরাজ মিশালাক

আমি এই ফাইলগুলিকে কেবল ক্ষেত্রেই মিরর করে রেখেছি:
32-বিট সংস্করণ: https : //www.DPboxboxss/r96jxglhkm4sjz2/SendSignalCtrlC.exe?
dl =0 64৪-বিট সংস্করণ: https://www.roidbox.com /s/hhe0io7mcgcle1c/SendSignalCtrlC64.exe?dl=0

দাবি অস্বীকার: আমি এই ফাইলগুলি তৈরি করি নি। সংকলিত মূল ফাইলগুলিতে কোনও পরিবর্তন করা হয়নি। একমাত্র পরীক্ষিত প্ল্যাটফর্মটি হ'ল -৪-বিট উইন্ডোজ 7.। এটি http://www.latenighthacking.com/projects/2003/sendSignal/ এ উপলব্ধ উত্সটি অভিযোজিত করে নিজেই সংকলন করার পরামর্শ দেওয়া হয় ।


2

জাভাতে, কার্নেল 32.ডিল লাইব্রেরির সাথে জেএনএ ব্যবহার করে, C ++ সমাধানের মতো similar একটি প্রক্রিয়া হিসাবে CtrlCSender মূল পদ্ধতি চালায় যা কেবলমাত্র Ctrl + C ইভেন্টে প্রেরণের জন্য প্রক্রিয়াটির কনসোল পায় এবং ইভেন্টটি উত্পন্ন করে। এটি কনসোল ছাড়াই পৃথকভাবে চলায় Ctrl + C ইভেন্টটি আবার অক্ষম করা এবং সক্ষম করার দরকার নেই।

CtrlCSender.java - Nemo1024 এর এবং KindDragon এর উত্তরের উপর ভিত্তি করে ।

একটি পরিচিত প্রক্রিয়া আইডি দেওয়া, এই কনসোলস অ্যাপ্লিকেশন লক্ষ্যযুক্ত প্রক্রিয়াটির কনসোল সংযুক্ত করবে এবং এটিতে একটি CTRL + C ইভেন্ট তৈরি করবে gene

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 চালায় ender

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

আমি এখানে থেকে একটি সমাধান পেয়েছি যে খুব সহজ যদি আপনার কমান্ড লাইনে পাইথন ৩.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

আমার এক বন্ধু সমস্যা সমাধানের সম্পূর্ণ ভিন্ন উপায়ের পরামর্শ দিয়েছিল এবং এটি আমার পক্ষে কাজ করে। নীচের মত একটি vbscript ব্যবহার করুন। এটি শুরু হয় এবং প্রয়োগ হয়, এটি 7 সেকেন্ডের জন্য চালানো যাক এবং ctrl + c ব্যবহার করে এটি বন্ধ করুন ।

'ভিবিএস স্ক্রিপ্ট উদাহরণ

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

WshShell.Run "notepad.exe"

WshShell.AppActivate "notepad"

WScript.Sleep 7000

WshShell.SendKeys "^C"

অ্যাপ্লিকেশনটির উইন্ডো থাকলে আপনি AppActive করতে পারেন (অগ্রভাগে আনুন) এটি কাজ করে।
রজারডপ্যাক


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

উইন্ডোজ-কিল ব্যবহার করে সিগিন্টকে প্রোগ্রামে প্রেরণ করা যেতে পারে , সিনট্যাক্স দ্বারা windows-kill -SIGINT PID, যেখানে PIDমাইক্রোসফ্টের পিএসলিস্ট দ্বারা প্রাপ্ত করা যেতে পারে ।

সিগিন্টগুলি ধরা সম্পর্কে, যদি আপনার প্রোগ্রামটি পাইথনে থাকে তবে আপনি এই দ্রবণে সাইন ইন প্রসেসিং / ক্যাচিং বাস্তবায়ন করতে পারেন ।


-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 প্রেরণ?
টেকনোপল

টাস্কিল সিটিআরএল-সি প্রেরণ করে না। উইন্ডোজ সিগন্যাল পরীক্ষা করে দেখুন।
জোসি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.