2012-04-14 56 views
11

Tôi hy vọng bài đăng này không phải là bản sao trùng lặp. Hãy để tôi giải thích:Tạm dừng/tiếp tục quy trình như PsSuspend thực hiện

Tôi đã xem bài đăng tương tự How to pause/resume any external process under Windows? nhưng với tùy chọn C++/Python và chưa có câu trả lời được chấp nhận kể từ thời điểm đăng bài.


Câu hỏi của tôi:

Tôi quan tâm đến một thực thể trong Delphi các chức năng được cung cấp bởi PsSuspend bởi Mark Russinovich của của Windows Sysinternals.

Quotes:

PsSuspend giúp bạn tạm ngưng quá trình trên địa phương hoặc một hệ thống từ xa, đó là mong muốn trong trường hợp một quá trình tốn nhiều tài nguyên (ví dụ mạng, CPU hay đĩa) mà bạn muốn để cho phép các quy trình khác nhau sử dụng. Thay vì giết quá trình đang tiêu thụ tài nguyên, hãy tạm ngưng cấp phép cho phép bạn tiếp tục hoạt động tại một số thời điểm sau này .

Cảm ơn bạn.


Edit:

Một thực hiện từng phần sẽ làm. Khả năng từ xa có thể được giảm xuống.

+0

Bạn có muốn mô phỏng toàn bộ chức năng không? Quá trình từ xa quá? –

+1

bây giờ đây thực sự là một câu hỏi hay (x3) – ComputerSaysNo

+0

@David Heffernan: Không, hãy thả khả năng từ xa. – menjaraz

Trả lời

10

Bạn có thể thử sử dụng mã sau đây. Nó sử dụng các hàm không có giấy tờ NtSuspendProcessNtResumeProcess. Tôi đã thử nó trên Windows 7 64-bit từ ứng dụng 32-bit được xây dựng trong Delphi 2009 và nó hoạt động cho tôi. Lưu ý rằng các chức năng này không có giấy tờ, do đó có thể được gỡ bỏ khỏi các phiên bản sau của Windows.

Cập nhật

Các SuspendProcessResumeProcess giấy gói từ mã sau đây hiện là chức năng và trả về True nếu thành công, False khác.

type 
    NTSTATUS = LongInt; 
    TProcFunction = function(ProcHandle: THandle): NTSTATUS; stdcall; 

const 
    STATUS_SUCCESS = $00000000; 
    PROCESS_SUSPEND_RESUME = $0800; 

function SuspendProcess(const PID: DWORD): Boolean; 
var 
    LibHandle: THandle; 
    ProcHandle: THandle; 
    NtSuspendProcess: TProcFunction; 
begin 
    Result := False; 
    LibHandle := SafeLoadLibrary('ntdll.dll'); 
    if LibHandle <> 0 then 
    try 
    @NtSuspendProcess := GetProcAddress(LibHandle, 'NtSuspendProcess'); 
    if @NtSuspendProcess <> nil then 
    begin 
     ProcHandle := OpenProcess(PROCESS_SUSPEND_RESUME, False, PID); 
     if ProcHandle <> 0 then 
     try 
     Result := NtSuspendProcess(ProcHandle) = STATUS_SUCCESS; 
     finally 
     CloseHandle(ProcHandle); 
     end; 
    end; 
    finally 
    FreeLibrary(LibHandle); 
    end; 
end; 

function ResumeProcess(const PID: DWORD): Boolean; 
var 
    LibHandle: THandle; 
    ProcHandle: THandle; 
    NtResumeProcess: TProcFunction; 
begin 
    Result := False; 
    LibHandle := SafeLoadLibrary('ntdll.dll'); 
    if LibHandle <> 0 then 
    try 
    @NtResumeProcess := GetProcAddress(LibHandle, 'NtResumeProcess'); 
    if @NtResumeProcess <> nil then 
    begin 
     ProcHandle := OpenProcess(PROCESS_SUSPEND_RESUME, False, PID); 
     if ProcHandle <> 0 then 
     try 
     Result := NtResumeProcess(ProcHandle) = STATUS_SUCCESS; 
     finally 
     CloseHandle(ProcHandle); 
     end; 
    end; 
    finally 
    FreeLibrary(LibHandle); 
    end; 
end; 
+0

Tôi bắt đầu nghĩ rằng chúng không hoạt động nhưng các thủ tục từ quan điểm của Delphi vì chúng trở về luôn Sai ngay cả khi quá trình đông lạnh. – TLama

+4

Đó là niềm vui của các chức năng không có giấy tờ. Dù sao, 'OpenProcess' trả về một quá trình xử lý và không phải là một xử lý mô-đun, FWIW. –

+0

@ David, bắt tốt, cảm ơn! Menjaraz, thú vị về chức năng 'NtSuspendProcess' là hành vi của nó. Nó đóng băng quá trình, nhưng các cửa sổ vẫn nhận được thông báo của windows. Khi bạn giải phóng quy trình, chúng sẽ được xử lý. – TLama

5

Không có cuộc gọi API SuspendProcess API trong Windows. Vì vậy, những gì bạn cần làm là:

  1. Liệt kê tất cả các chủ đề trong quy trình. Xem RRUZ's answer để biết mã mẫu.
  2. Gọi SuspendThread cho từng chủ đề này.
  3. Để thực hiện phần tiếp tục của chương trình, hãy gọi ResumeThread cho từng chuỗi.
+0

Điều này có vẻ hợp lý để mô phỏng chức năng. Tôi nghi ngờ API không có giấy tờ dựa trên việc sử dụng PsSuspend: 'pssuspend [-] [-r] [\\ máy tính [-u tên người dùng] [-p mật khẩu]] '. Có cách nào để xác định rằng nó không sử dụng api như vậy cho rằng nó đã được viết bởi một chuyên gia trong MS chính nó? – menjaraz

+2

Mark đã tham gia MS một thời gian sau khi viết PsSuspend. Tất cả cùng nó có thể rất tốt sử dụng các API không có giấy tờ. Ông cũng viết Windows Internals trước khi tham gia MS để bên trong hoặc bên ngoài làm cho sự khác biệt nhỏ. Tôi nghĩ rằng walker phụ thuộc trong chế độ hồ sơ sẽ cho bạn biết những gì các API được sử dụng. –

+0

@menjaraz: Nếu nó đã từng tồn tại, bạn sẽ biết. Đây không phải là thời trung cổ ... –

1

Tôi chỉ tìm thấy các đoạn mã sau here (Tác giả: steve10120).

Tôi nghĩ rằng đó là những vật có giá trị và tôi không thể giúp đăng chúng cũng như một câu trả lời thay thế cho câu hỏi của riêng tôi. Process


Resume:

function ResumeProcess(ProcessID: DWORD): Boolean; 
var 
    Snapshot,cThr: DWORD; 
    ThrHandle: THandle; 
    Thread:TThreadEntry32; 
begin 
    Result := False; 
    cThr := GetCurrentThreadId; 
    Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
    if Snapshot <> INVALID_HANDLE_VALUE then 
    begin 
    Thread.dwSize := SizeOf(TThreadEntry32); 
    if Thread32First(Snapshot, Thread) then 
     repeat 
     if (Thread.th32ThreadID <> cThr) and (Thread.th32OwnerProcessID = ProcessID) then 
     begin 
     ThrHandle := OpenThread(THREAD_ALL_ACCESS, false, Thread.th32ThreadID); 
     if ThrHandle = 0 then Exit; 
     ResumeThread(ThrHandle); 
     CloseHandle(ThrHandle); 
     end; 
     until not Thread32Next(Snapshot, Thread); 
     Result := CloseHandle(Snapshot); 
    end; 
end; 

Đình chỉ Process:

function SuspendProcess(PID:DWORD):Boolean; 
var 
hSnap: THandle; 
THR32: THREADENTRY32; 
hOpen: THandle; 
begin 
    Result := FALSE; 
    hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
    if hSnap <> INVALID_HANDLE_VALUE then 
    begin 
    THR32.dwSize := SizeOf(THR32); 
    Thread32First(hSnap, THR32); 
    repeat 
     if THR32.th32OwnerProcessID = PID then 
     begin 
     hOpen := OpenThread($0002, FALSE, THR32.th32ThreadID); 
     if hOpen <> INVALID_HANDLE_VALUE then 
     begin 
      Result := TRUE; 
      SuspendThread(hOpen); 
      CloseHandle(hOpen); 
     end; 
     end; 
    until Thread32Next(hSnap, THR32) = FALSE; 
    CloseHandle(hSnap); 
    end; 
end; 

Tuyên bố từ chối trách nhiệm:

Tôi đã không kiểm tra tất cả. Hãy tận hưởng và đừng quên phản hồi.

+0

Xem bình luận từ Wombat. Đây không phải là chương trình tốt. – Lothar

4

Có điều kiện chủng tộc để thực hiện "tạm dừng tất cả chuỗi" - điều gì sẽ xảy ra nếu chương trình bạn đang cố tạm ngưng tạo một hoặc nhiều chủ đề giữa thời gian bạn tạo ảnh chụp nhanh và thời gian bạn ngừng hoàn tất?

Bạn có thể lặp lại, nhận được một ảnh chụp nhanh khác và tạm ngưng bất kỳ chuỗi không treo nào, chỉ thoát khi bạn không tìm thấy gì.

Chức năng không có giấy tờ tránh được sự cố này.

Các vấn đề liên quan