Tôi có thể gửi ctrl-C (SIGINT) đến một ứng dụng trên Windows không?


91

Tôi đã viết (trước đây) các ứng dụng đa nền tảng (Windows / Unix), khi bắt đầu từ dòng lệnh, xử lý tổ hợp do người dùng nhập Ctrl- Ctheo cách tương tự (nghĩa là chấm dứt ứng dụng một cách rõ ràng).

Có thể nào trên Windows gửi Ctrl- C/ SIGINT / tương đương với một quy trình từ một quy trình khác (không liên quan) để yêu cầu nó kết thúc sạch sẽ (tạo cơ hội cho nó dọn dẹp tài nguyên, v.v.)?


1
Tôi quan tâm đến việc gửi Ctrl-C tới các quy trình dịch vụ java chỉ để lấy các luồng. Dường như jstackcó thể được tin cậy sử dụng thay cho vấn đề cụ thể này: stackoverflow.com/a/47723393/603516
Vadzim

Câu trả lời:


31

Gần nhất mà tôi đã tìm ra giải pháp là ứng dụng bên thứ 3 SendSignal . Tác giả liệt kê mã nguồn và một tệp thực thi. Tôi đã xác minh rằng nó hoạt động trong các cửa sổ 64 bit (chạy như một chương trình 32 bit, giết chết một chương trình 32 bit khác), nhưng tôi chưa tìm ra cách nhúng mã vào một chương trình windows (32 bit hoặc 64-bit).

Làm thế nào nó hoạt động:

Sau khi tìm hiểu nhiều trong trình gỡ lỗi, tôi phát hiện ra rằng điểm vào thực sự thực hiện hành vi liên quan đến tín hiệu như ctrl-break là kernel32! CtrlRoutine. Hàm có cùng nguyên mẫu với ThreadProc, vì vậy nó có thể được sử dụng trực tiếp với CreateRemoteThread mà không cần phải chèn mã. Tuy nhiên, đó không phải là một biểu tượng được xuất khẩu! Nó ở các địa chỉ khác nhau (và thậm chí có các tên khác nhau) trên các phiên bản Windows khác nhau. Để làm gì?

Đây là giải pháp cuối cùng tôi đã đưa ra. Tôi cài đặt trình xử lý ctrl bảng điều khiển cho ứng dụng của mình, sau đó tạo tín hiệu ctrl-break cho ứng dụng của mình. Khi trình xử lý của tôi được gọi, tôi nhìn lại phía trên cùng của ngăn xếp để tìm ra các tham số được truyền cho kernel32! BaseThreadStart. Tôi lấy tham số đầu tiên, là địa chỉ bắt đầu mong muốn của luồng, là địa chỉ của kernel32! CtrlRoutine. Sau đó, tôi quay lại từ trình xử lý của mình, cho biết rằng tôi đã xử lý tín hiệu và ứng dụng của tôi sẽ không bị chấm dứt. Quay lại luồng chính, tôi đợi cho đến khi địa chỉ của kernel32! CtrlRoutine được truy xuất. Khi tôi đã có nó, tôi tạo một chuỗi từ xa trong quy trình đích với địa chỉ bắt đầu được phát hiện. Điều này làm cho các trình xử lý ctrl trong tiến trình đích được đánh giá như thể ctrl-break đã được nhấn!

Điều tốt đẹp là chỉ có quy trình đích bị ảnh hưởng và bất kỳ quy trình nào (thậm chí là quy trình cửa sổ) đều có thể được nhắm mục tiêu. Một nhược điểm là ứng dụng nhỏ của tôi không thể được sử dụng trong một tệp loạt, vì nó sẽ giết nó khi gửi sự kiện ctrl-break để phát hiện ra địa chỉ của kernel32! CtrlRoutine.

(Bắt buộc trước startnếu chạy nó trong một tệp hàng loạt.)


2
+1 - Mã được liên kết sử dụng Ctrl-Break thay vì Ctrl-C nhưng về mặt nó (xem tài liệu về GenerateConsoleCtrlEvent) có thể được điều chỉnh cho Ctrl-C.
Matthew Murdoch,

8
Thực ra có một chức năng để làm việc này cho bạn, lol, "GenerateConsoleCtrlEvent". Xem: msdn.microsoft.com/en-us/library/ms683155(v=vs.85).aspx Xem thêm câu trả lời của tôi tại đây: serverfault.com/a/501045/10023
Triynko

1
Liên kết github liên quan đến câu trả lời ở trên: github.com/walware/statet/tree/master/…
urwoppl

3
Nó làm suy nghĩ rằng Windows vẫn cũ như cũ và Microsoft vẫn chưa cung cấp cơ chế cho ứng dụng console A lắng nghe tín hiệu từ ứng dụng console B để ứng dụng console B có thể yêu cầu ứng dụng console A tắt sạch. Trong mọi trường hợp, gạt MS sang một bên, tôi đã thử SendSignal và nhận được "CreateRemoteThread không thành công với 0x00000005". Bất kỳ ý tưởng nào khác về cách viết mã ứng dụng A để lắng nghe tín hiệu (bất kỳ tín hiệu nào thuận tiện), và sau đó làm thế nào để phát tín hiệu?
David I. McIntosh

3
@ DavidI.McIntosh, có vẻ như bạn muốn tạo một sự kiện được đặt tên trong cả hai quy trình; sau đó bạn sẽ có thể báo hiệu cái này từ cái kia. Kiểm tra tài liệu cho CreateEvent
arolson101

58

Tôi đã thực hiện một số nghiên cứu xung quanh chủ đề này, hóa ra nó phổ biến hơn tôi dự đoán. Câu trả lời của KindDragon là một trong những điểm mấu chốt.

Tôi đã viết một bài đăng trên blog dài hơn về chủ đề này và tạo một chương trình demo hoạt động, trong đó thể hiện việc sử dụng loại hệ thống này để đóng một ứng dụng dòng lệnh theo một số cách hay. Bài đăng đó cũng liệt kê các liên kết bên ngoài mà tôi đã sử dụng trong nghiên cứu của mình.

Tóm lại, các chương trình demo đó thực hiện như sau:

  • Khởi động chương trình với cửa sổ hiển thị bằng .Net, ẩn bằng pinvoke, chạy trong 6 giây, hiển thị bằng pinvoke, dừng bằng .Net.
  • Khởi động chương trình không có cửa sổ bằng .Net, chạy trong 6 giây, dừng bằng cách gắn bảng điều khiển và phát hành ConsoleCtrlEvent

Chỉnh sửa: Giải pháp sửa đổi từ KindDragon dành cho những ai quan tâm đến mã tại đây và ngay bây giờ. Nếu bạn định bắt đầu các chương trình khác sau khi dừng chương trình đầu tiên, bạn nên bật lại xử lý Ctrl-C, nếu không quá trình tiếp theo sẽ kế thừa trạng thái bị vô hiệu hóa của chương trình gốc và sẽ không phản hồi với 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); 
  }
}

Ngoài ra, hãy lập kế hoạch cho một giải pháp dự phòng nếu AttachConsole()hoặc tín hiệu đã gửi không thành công, ví dụ như đang ngủ sau đó:

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

4
Lấy cảm hứng từ điều này, tôi đã tạo một ứng dụng cpp "độc lập" để thực hiện nó: gist.github.com/rdp/f51fb274d69c5c31b6be trong trường hợp nó hữu ích. Và có, phương pháp này có thể gửi ctrl + c hoặc ctrl + break tới pid "bất kỳ", rõ ràng.
rogerdpack

Thiếu một trong các nhập DLL "SetConsoleCtrlHandler", nhưng điều này hoạt động.
Derf Skren

bài xuất sắc. blog xuất sắc. Tôi khuyên bạn nên hoàn thành chức năng StopProgramWithInvisibleWindowUsingPinvoke trong chương trình thử nghiệm của bạn. Tôi gần như từ bỏ suy nghĩ ý tưởng bạn đã không tìm thấy một giải pháp
Wilmer Saint

Để tránh, wait()tôi đã xóa Ctrl-C ( SetConsoleCtrlHandler(null, false);) bật lại. Tôi đã thực hiện một vài thử nghiệm (nhiều cuộc gọi, cũng trên các quy trình đã bị chấm dứt) và tôi không tìm thấy bất kỳ tác dụng phụ nào (chưa?).
56ka

FreeConsole sẽ được gọi ngay sau khi gửi GenerateConsoleCtrlEvent. Cho đến khi nó được gọi, ứng dụng của bạn sẽ được gắn vào bảng điều khiển khác. Nếu bảng điều khiển khác bị giết trước khi hoàn tất việc đóng ứng dụng của bạn cũng sẽ bị chấm dứt!
Timothy Jannace

17

Tôi đoán là tôi hơi muộn với câu hỏi này nhưng dù sao thì tôi cũng sẽ viết một cái gì đó cho bất kỳ ai có cùng vấn đề. Đây là câu trả lời giống như tôi đã đưa ra cho câu hỏi này .

Vấn đề của tôi là tôi muốn ứng dụng của mình là một ứng dụng GUI nhưng các quy trình được thực thi phải chạy ở chế độ nền mà không có bất kỳ cửa sổ bảng điều khiển tương tác nào được đính kèm. Tôi nghĩ rằng giải pháp này cũng sẽ hoạt động khi quy trình mẹ là một quy trình bảng điều khiển. Tuy nhiên, bạn có thể phải xóa cờ "CREATE_NO_WINDOW".

Tôi đã quản lý để giải quyết vấn đề này bằng cách sử dụng GenerateConsoleCtrlEvent () với một ứng dụng trình bao bọc. Phần khó khăn chỉ là tài liệu không thực sự rõ ràng về cách chính xác nó có thể được sử dụng và những cạm bẫy với nó.

Giải pháp của tôi dựa trên những gì được mô tả ở đây . Nhưng điều đó cũng không thực sự giải thích tất cả các chi tiết và có lỗi, vì vậy đây là chi tiết về cách làm cho nó hoạt động.

Tạo một ứng dụng trợ giúp mới "Helper.exe". Ứng dụng này sẽ nằm giữa ứng dụng của bạn (cha mẹ) và quy trình con mà bạn muốn có thể đóng. Nó cũng sẽ tạo ra tiến trình con thực tế. Bạn phải có quy trình "người trung gian" này nếu không GenerateConsoleCtrlEvent () sẽ thất bại.

Sử dụng một số loại cơ chế IPC để giao tiếp từ cha mẹ đến quy trình trợ giúp mà người trợ giúp sẽ đóng quy trình con. Khi trình trợ giúp nhận được sự kiện này, nó gọi "GenerateConsoleCtrlEvent (CTRL_BREAK, 0)" sẽ tự đóng và quy trình con. Tôi đã tự mình sử dụng một đối tượng sự kiện cho đối tượng này mà đối tượng phụ huynh hoàn thành khi nó muốn hủy tiến trình con.

Để tạo Helper.exe của bạn, hãy tạo nó với CREATE_NO_WINDOW và CREATE_NEW_PROCESS_GROUP. Và khi tạo tiến trình con, hãy tạo nó không có cờ (0) nghĩa là nó sẽ lấy giao diện điều khiển từ cha của nó. Không làm điều này sẽ khiến nó bỏ qua sự kiện.

Điều rất quan trọng là mỗi bước được thực hiện như thế này. Tôi đã thử tất cả các kiểu kết hợp khác nhau nhưng cách kết hợp này là cách duy nhất hoạt động. Bạn không thể gửi sự kiện CTRL_C. Nó sẽ trả lại thành công nhưng sẽ bị quá trình bỏ qua. CTRL_BREAK là công cụ duy nhất hoạt động. Không thực sự quan trọng vì cuối cùng cả hai đều sẽ gọi ExitProcess ().

Bạn cũng không thể gọi GenerateConsoleCtrlEvent () với id nhóm quy trình của id quy trình con trực tiếp cho phép quy trình trợ giúp tiếp tục hoạt động. Điều này cũng sẽ thất bại.

Tôi đã dành cả ngày để cố gắng làm việc này. Giải pháp này phù hợp với tôi nhưng nếu ai có bất kỳ điều gì khác để thêm, vui lòng làm. Tôi đã đi khắp mạng tìm kiếm rất nhiều người có vấn đề tương tự nhưng không có giải pháp chắc chắn cho vấn đề. Cách hoạt động của GenerateConsoleCtrlEvent () cũng hơi lạ nên nếu ai biết chi tiết hơn thì chia sẻ nhé.


6
Cảm ơn vì giải pháp! Đây là một ví dụ khác về Windows API là một mớ hỗn độn khủng khiếp.
vitaut vào

8

Biên tập:

Đối với Ứng dụng GUI, cách "bình thường" để xử lý vấn đề này trong quá trình phát triển Windows là gửi thông báo WM_CLOSE đến cửa sổ chính của quy trình.

Đối với ứng dụng bảng điều khiển, bạn cần sử dụng SetConsoleCtrlHandler để thêm CTRL_C_EVENT.

Nếu ứng dụng không tuân theo điều đó, bạn có thể gọi TerminaProcess .


Tôi muốn thực hiện việc này trong một ứng dụng dòng lệnh (không có cửa sổ). TerminaProcess là một cơ chế tiêu diệt lực lượng (tương tự như SIGKILL) vì vậy không cho ứng dụng kết thúc bất kỳ cơ hội nào để dọn dẹp.
Matthew Murdoch

@Matthew Murdoch: Đã cập nhật để bao gồm thông tin về cách xử lý vấn đề này trong ứng dụng bảng điều khiển. Bạn cũng có thể theo dõi các sự kiện khác, bao gồm cả việc tắt cửa sổ hoặc đóng bảng điều khiển, v.v., thông qua cơ chế tương tự. Xem MSDN để biết đầy đủ chi tiết.
Reed Copsey

@Reed Copsey: Nhưng tôi muốn bắt đầu việc này từ một quy trình riêng biệt. Tôi đã xem qua GenerateConsoleCtrlEvent (được tham chiếu từ SetConsoleCtrlHandler) nhưng điều này dường như chỉ hoạt động nếu quá trình bị kết thúc nằm trong cùng một 'nhóm quy trình' với quy trình đang thực hiện kết thúc ... Có ý kiến ​​nào không?
Matthew Murdoch

1
Matthew: Ý tưởng duy nhất mà tôi có là tìm quy trình, tìm nó là cha mẹ (bảng điều khiển), lấy tay cầm cửa sổ chính của cha mẹ (bảng điều khiển) và sử dụng SendKeys để gửi Ctrl + C trực tiếp đến nó. Điều đó sẽ khiến quy trình bảng điều khiển của bạn nhận CTRL_C_EVENT. Tuy nhiên, bạn chưa thử - không chắc nó hoạt động tốt như thế nào.
Reed Copsey

Dưới đây là một c ++ tương đương với SendKeys stackoverflow.com/questions/6838363/... xem thêm stackoverflow.com/questions/10407769/... mặc dù rõ ràng là nó không được bảo đảm để làm việc thậm chí sau đó ...
rogerdpack

7

Bằng cách nào đó, GenerateConsoleCtrlEvent()trả về lỗi nếu bạn gọi nó cho một quy trình khác, nhưng bạn có thể đính kèm vào một ứng dụng bảng điều khiển khác và gửi sự kiện đến tất cả các quy trình con.

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
}

và làm thế nào để trả lại quyền kiểm soát? và sau đó tôi gửi chương trình control-c, stopar, nhưng tôi không thể làm gì với tay anh ta.
Yaroslav L.

Trả lại quyền kiểm soát ở đâu?
KindDragon

Tôi nghĩ rằng bạn gọi SetConsoleCtrlHandler (NULL, FALSE) để xóa trình xử lý của bạn, hãy xem các phản hồi khác nhau.
rogerdpack

6

Đây là mã tôi sử dụng trong ứng dụng C ++ của mình.

Điểm tích cực :

  • Hoạt động từ ứng dụng bảng điều khiển
  • Hoạt động từ dịch vụ Windows
  • Không cần chậm trễ
  • Không đóng ứng dụng hiện tại

Điểm tiêu cực:

  • Bảng điều khiển chính bị mất và một bảng điều khiển mới được tạo (xem FreeConsole )
  • Việc chuyển đổi bảng điều khiển cho kết quả kỳ lạ ...

// 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;
}

Ví dụ sử dụng:

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

Nó nên được làm rõ ràng bởi vì hiện tại nó không phải là. Có một phiên bản SendSignal được sửa đổi và biên dịch để gửi Ctrl-C (theo mặc định nó chỉ gửi Ctrl + Break). Dưới đây là một số mã nhị phân:

(2014-3-7): Tôi đã tạo cả phiên bản 32 bit và 64 bit bằng Ctrl-C, nó được gọi là SendSignalCtrlC.exe và bạn có thể tải xuống tại: https://dl.dropboxusercontent.com/u/49065779/ sendignalctrlc / x86 / SendSignalCtrlC.exe https://dl.dropboxusercontent.com/u/49065779/sendsignalctrlc/x86_64/SendSignalCtrlC.exe - Juraj Michalak

Tôi cũng đã nhân bản các tệp đó trong trường hợp:
phiên bản 32-bit: https://www.dropbox.com/s/r96jxglhkm4sjz2/SendSignalCtrlC.exe?dl=0 Phiên bản
64-bit: https://www.dropbox.com /s/hhe0io7mcgcle1c/SendSignalCtrlC64.exe?dl=0

Tuyên bố từ chối trách nhiệm: Tôi không xây dựng các tệp đó. Không có sửa đổi nào được thực hiện đối với các tệp gốc đã biên dịch. Nền tảng duy nhất được thử nghiệm là Windows 7. 64-bit, bạn nên điều chỉnh nguồn có sẵn tại http://www.latenighthacking.com/projects/2003/sendSignal/ và tự biên dịch.


2

Trong Java, sử dụng JNA với thư viện Kernel32.dll, tương tự như giải pháp C ++. Chạy phương thức chính CtrlCSender dưới dạng một Quy trình mà chỉ cần giao diện điều khiển của quy trình gửi sự kiện Ctrl + C đến và tạo sự kiện. Vì nó chạy riêng biệt mà không có bảng điều khiển nên sự kiện Ctrl + C không cần phải tắt và bật lại.

CtrlCSender.java - Dựa trên Nemo1024KindDragon's câu trả lời.

Với một ID quy trình đã biết, ứng dụng tự tin này sẽ đính kèm bảng điều khiển của quy trình được nhắm mục tiêu và tạo Sự kiện CTRL + C trên đó.

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

Ứng dụng chính - Chạy CtrlCSender như một quy trình giải quyết riêng

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

hmm, nếu tôi chạy điều này với quy trình powershell thì quy trình vẫn tồn tại. Mặt khác, thật thú vị, việc chạy trong quá trình trên JVM thực sự làm hỏng máy ảo! Bạn có biết tại sao quy trình powershell không đáp ứng với kỹ thuật này không?
Groostav


1

Một giải pháp mà tôi đã tìm thấy từ đây khá đơn giản nếu bạn có sẵn python 3.x trong dòng lệnh của mình. Đầu tiên, lưu một tệp (ctrl_c.py) với nội dung:

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)

Sau đó gọi:

python ctrl_c.py 12345

Nếu điều đó không hiệu quả, tôi khuyên bạn nên thử dự án windows-kill: https://github.com/alirdn/windows-kill


0

Một người bạn của tôi đã đề xuất một cách hoàn toàn khác để giải quyết vấn đề và nó đã hiệu quả với tôi. Sử dụng một vbscript như dưới đây. Nó khởi động và ứng dụng, để nó chạy trong 7 giây và đóng nó bằng ctrl + c .

'Ví dụ về VBScript

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

WshShell.Run "notepad.exe"

WshShell.AppActivate "notepad"

WScript.Sleep 7000

WshShell.SendKeys "^C"

Điều này hoạt động nếu ứng dụng có một cửa sổ mà bạn có thể AppActive (đưa lên nền trước).
rogerdpack

0

Tôi thấy tất cả điều này quá phức tạp và sử dụng SendKeys để gửi CTRL- Ctổ hợp phím đến cửa sổ dòng lệnh (tức là cửa sổ cmd.exe) như một giải pháp thay thế.


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 có thể được gửi đến chương trình bằng cách sử dụng windows-kill , theo cú pháp windows-kill -SIGINT PID, nơi PIDcó thể lấy được bằng pslist của Microsoft .

Về việc bắt SIGINTs, nếu chương trình của bạn bằng Python thì bạn có thể thực hiện xử lý / bắt SIGINT như trong giải pháp này .


-1

Dựa trên id quy trình, chúng tôi có thể gửi tín hiệu cần xử lý để kết thúc một cách mạnh mẽ hoặc duyên dáng hoặc bất kỳ tín hiệu nào khác.

Liệt kê tất cả quá trình:

C:\>tasklist

Để giết quá trình:

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

Chi tiết:

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


Chắc chắn điều này sẽ gửi người ký tên?
teknopaul

Taskkill không gửi CTRL-C. Kiểm tra tín hiệu Windows.
Josi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.