全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3550
推到 Plurk!
推到 Facebook!

強制讓自己的程式快速關閉,且關得乾淨

答題得分者是:aftcast
salo0610
高階會員


發表:42
回覆:120
積分:107
註冊:2003-02-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-08-14 13:16:39 IP:202.39.xxx.xxx 未訂閱

各位先進您們好:

引用:
問:怎麼才能關掉一個用任務管理器關不了的進程?我前段時間發現我的機子裏多了一個進程,只要開機就在,我用任務管理器卻怎麼關也關不了
答1:殺進程很容易,隨便找個工具都行。比如IceSword。關鍵是找到這個進程的啟動方式,不然下次重啟它又出來了。順便教大家一招狠的。其實用Windows自帶的工具就能殺大部分進程:
c:\>ntsd -c q -p PID

但我想在我的程式內有這樣的功能,不知要怎麼寫,我要強制讓自己的程式快速關閉,且關得乾淨。
我用下面的寫法:
HANDLE HandleProcess = OpenProcess(PROCESS_ALL_ACCESS , true , GetCurrentProcessId());
TerminateProcess( HandleProcess,0 );
但這樣寫法並沒有把這程式相關的Process也關閉,不知各位先進是否有其它的方法?? 謝謝您們!!


PS:程式是用socket與裝置連線,用執行緒在處理,一個與裝置的連線可能有三四個執行緒在運作,也就是說二個連線( 2*3=6 )就有六個執行緒,但連線的裝置一多時,在關閉程式的速度會很慢(正常的程序關閉),所以想嚐試用較快的方式且又清得乾淨的方法。

aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-08-21 22:13:22 IP:61.229.xxx.xxx 未訂閱

你好,

我寫了一隻模擬 ntsd -c q 功能的console程式,經過測式後可以殺多數殺不掉的程序。但若要應用在一般的程式上,真的需要做許多壓力測式來了解所有的資源是否都清的很乾淨。即使是使用ntsd也是一樣的道理。必竟這不是正規的terminate process的方式…至少未save的data是一定會lost的。我目前沒有大量的thread測式環境,還請若有機會test,可以把結果分享一下:

程式的原理很簡單,是利用debug 的api把process attach上來,然後用一個debug自然的機制…即debugger程式離開時,被debug的process也會被terminate。至於這個自然的機制是如何處理…目前我也還不很清楚。

由上面的原理來看,我們需要先編一個獨立的exe檔來attach process,然後結束自己…我用c的語法寫(非cpp)

#include
#include
#include

BOOL tokenUp(void); //提昇權限至debug模式
void tokenRestore(void); //回復原來的權限

DWORD main(int argc, char* argv[])
{
DWORD dwId, dwError;

if (argc != 2)
{
fprintf(stderr,"Usage: %s ProcessId\n", argv[0]);
return 1;
}

dwId = _atoi64(argv[1]);

if(!DebugActiveProcess(dwId))
{
dwError = GetLastError();
if(dwError != ERROR_ACCESS_DENIED)
{
printf("Error Num = %u",dwError);
return dwError;
}

if(tokenUp())
{
// try to attach again
if(!DebugActiveProcess(dwId))
{
dwError = GetLastError();
printf("Error Num = %u",dwError);
return dwError;
}

tokenRestore();
return 0;
}

dwError = GetLastError();
printf("Error Num = %u",dwError);
return dwError;
}

return 0;

}
//---------------------------------------------------------------------------

static TOKEN_PRIVILEGES Priv, PrivOld;
static DWORD cbPriv = sizeof(PrivOld);
static DWORD dwError;
static HANDLE hToken;

BOOL tokenUp(void)
{
// get current thread token
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
FALSE, &hToken))
{
if (GetLastError() != ERROR_NO_TOKEN)
return FALSE;

// revert to the process token, if not impersonating
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
&hToken))
return FALSE;
}


// _ASSERTE(ANYSIZE_ARRAY > 0);

Priv.PrivilegeCount = 1;
Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME,
&Priv.Privileges[0].Luid);

// try to enable the privilege
if (!AdjustTokenPrivileges(hToken, FALSE, &Priv, sizeof(Priv),
&PrivOld, &cbPriv))
{
dwError = GetLastError();
CloseHandle(hToken);
return SetLastError(dwError), FALSE;
}

if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
// the SE_DEBUG_NAME privilege is not in the caller's token
CloseHandle(hToken);
return SetLastError(ERROR_ACCESS_DENIED), FALSE;
}
return TRUE;
}

void tokenRestore(void)
{
// restore original privilege state
AdjustTokenPrivileges(hToken, FALSE, &PrivOld, sizeof(PrivOld),
NULL, NULL);
CloseHandle(hToken);
}

這個console程式可以單獨使用,我compile為killp.exe ,就可以在dos box下執行 killp 1234 (假設pid是1234)。

若要應用在你的form ap上,則需要使用create process的api來執行它…如下:

STARTUPINFO si;
PROCESS_INFORMATION pi;
String cmd;

cmd = "killp " Edit1->Text;

LPTSTR szCmdline=cmd.c_str();

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );

// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
szCmdline, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
ShowMessage(String().sprintf("CreateProcess failed (%d).\n", GetLastError()));
return;
}

// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );

// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );

蕭沖 qs.xiao@gmail.com


===================引 用 文 章===================

各位先進您們好:

引用:
問:怎麼才能關掉一個用任務管理器關不了的進程?我前段時間發現我的機子裏多了一個進程,只要開機就在,我用任務管理器卻怎麼關也關不了
答1:殺進程很容易,隨便找個工具都行。比如IceSword。關鍵是找到這個進程的啟動方式,不然下次重啟它又出來了。順便教大家一招狠的。其實用Windows自帶的工具就能殺大部分進程:
c:\>ntsd -c q -p PID

但我想在我的程式內有這樣的功能,不知要怎麼寫,我要強制讓自己的程式快速關閉,且關得乾淨。

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
系統時間:2024-04-27 23:55:33
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!