如何關閉Processes的程序 |
答題得分者是:eaglewolf
|
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
再次請問各位!
如何取得工作管理員中我指定的某一個程序(例如EXCEL.EXE),可以透過程式將其關閉,之前我已搜尋過本站拜讀兩位前輩的資料,但測試結果都行不通 http://delphi.ktop.com.tw/board.php?cid=30&fid=67&tid=27841 http://delphi.ktop.com.tw/board.php?cid=30&fid=70&tid=70337 我需要這個功能的目的是因為,我要開啟一個EXCEL來讀入XLS資料,但有時候會發生一些狀況導致當機,結果造成剛才開啟的EXCEL.EXE殘留在Processes中,此時如果程式再重新執行一次,又開啟了一個EXCEL.EXE,如果多來幾次,系統資源就被吃光,所以我想偵測是否有前一次的EXCEL.EXE殘留,如果有則主動釋放,如下程式 但這會有個問題,如果程式很順利執行,msexcel可以取得Processes的ID,在程式完成後執行msexcel.quit可以順利釋放 EXCEL, 但如果程式中途出錯,程式無法正常結束關閉,當再次啟動程式時,msexcel是不存在的值,自然msexcel.quit就無法執行,目前我僅能透過FindProcWnd找到EXCEL.EXE 的程序名稱,但無法利用ExitProcess()來釋放 (我查了一些文獻,發現要釋放Processes,利用ExitProcesses是最乾淨的),所以要如何才能做到我想要的功能,謝謝! <textarea class="delphi" rows="10" cols="60" name="code"> try if U_VarDef.FindProcWnd('EXCEL.EXE') then begin msexcel.DisplayAlerts:= False; msexcel.Quit; end; except on E:Exception do begin Application.MessageBox(pChar(E.Message #13 #13 '1.請開啟工作管理員' #13 '2.檢查是否有『EXCEL.EXE』的程序存在' #13 '3.如果發現有請手動執行【結束處理程序】' #13 '4.再重新進行【資料匯入】作業...'),'系統訊息',MB_OK); exit; end; end; msexcel:= CreateOleObject('Excel.Application'); workbook := msexcel.WorkBooks.Open(eFile.Text); worksheet:= msexcel.WorkSheets[1]; </textarea> |
wameng
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
<textarea cols="60" rows="10" class="delphi" name="code">
Procedure KillTask(ProcName: string); procedure KillProcess(dwProcessId: DWORD);
var
ProcHandle: THandle;
begin
ProcHandle := OpenProcess(1, FALSE, dwProcessID);
try
if ProcHandle <> 0 then
begin
if TerminateProcess(ProcHandle, $FFFFFFFF) then
WaitForSingleObject(ProcHandle, INFINITE);
end;
finally
CloseHandle(ProcHandle);
end;
end; var
OK: Bool;
hPL: THandle;
ProcessStruct: TProcessEntry32;
begin
hPL := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
ProcessStruct.dwSize := SizeOf(TProcessEntry32);
OK := Process32First(hPL, ProcessStruct);
while OK do
begin
if UpperCase(ProcessStruct.szExeFile) = UpperCase(ProcName) then
begin
KillProcess(ProcessStruct.th32ProcessID);
end;
OK := Process32Next(hPL, ProcessStruct);
end;
CloseHandle(hPL);
end;
</textarea> 可以先嘗試用 PostQuitMessage 。
|
eaglewolf
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:4 回覆:268 積分:429 註冊:2006-07-06 發送簡訊給我 |
為何不使用GetActiveOLEObject?
<textarea class="delphi" rows="10" cols="60" name="code"> try msexcel := GetActiveOleObject('Excel.Application') except msexcel := CreateOleObject('Excel.Application'); end; </textarea>
------
先查HELP 再查GOOGLE 最後才發問 沒人有義務替你解答問題 在標題或文章中標明很急 並不會增加網友回答速度 Developing Tool: 1.Delphi 6 2.Visual Studio 2005 3.Visual Studio 2008 DBMS: MS-SQL |
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
感謝wameng版主再次的指教,另外eaglewolf所提出的方式,我測試後的確可以取得並關閉,我只要設定以下的做法,就可以搭配找到Process先關閉
感謝兩位指導,謝謝 <textarea class="delphi" rows="10" cols="60" name="code"> if FindProcWnd('EXCEL.EXE') then begin msexcel:= GetActiveOleObject('Excel.Application'); msexcel.DisplayAlerts:= False; msexcel.Quit; end; </textarea> |
Kingron
中階會員 ![]() ![]() ![]() 發表:1 回覆:51 積分:60 註冊:2005-09-14 發送簡訊給我 |
GetActiveOleObject的确是正确的解决之道,不过你的方法好奇怪哈。
如果有另外一个程序的档名也叫做Excel.exe,你的程序就挂了。 两个问题: 首先这样: const CSExcelClassName = 'Excel.Application'; try msexcel := GetActiveOleObject(CSExcelClassName); except try msexcel = CreateOleObject(CSExcelClassName ); except ShowMessage('Excel 可能没有正常安装!'); Exit; end; end; /// do something with msexcel.... 另外一个问题: 你的代码没有正常Quit,是你没有正确处理异常,你应该正确处理异常! try .... msexcel.... finally VarClear(excelbook); VarClear(excelsheet); .... and so on msexcel.Quit; // 这里 VarClear(msexcel); ////这里 end; ===================引 用 P.D. 文 章=================== 感謝wameng版主再次的指教,另外eaglewolf所提出的方式,我測試後的確可以取得並關閉,我只要設定以下的做法,就可以搭配找到Process先關閉 感謝兩位指導,謝謝 <textarea class="delphi" rows="10" cols="60" name="code">if FindProcWnd('EXCEL.EXE') then begin msexcel:= GetActiveOleObject('Excel.Application'); msexcel.DisplayAlerts:= False; msexcel.Quit; end; </textarea>
------
超级猛料:http://kingron.delphibbs.com |
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
感謝kingron的說明,讓我又學習到一個用法,否則我還真不知有varclear()的用法
不過這個varclear 與 quit 的關係如何,我看了一下說明不是很清楚,是不是與 form1.free 並未真正釋放該記憶區塊,所以都會以FreeandNil()或Form1:= nil再徹底消減該變數的道理相同呢? 但對於 worksheet, workbook 也要如此做,我就存在很大的好奇心了。 另外,對於excel.exe 未被正確處理異常,這有時實在很難控制,例如可能對方執行另一個程式也啟動excel, 或者直接呼叫excel ,或者在我的程式中啟動了excel, 但中途當機,這都不是 try ... except 可以捕捉的到然後再正常的釋放的情況,所以才會想搜尋Processes中是否有殘留的EXCEL.EXE 存在,而的確如果有很多個EXCEL.EXE存在時,GETATIVEOLDOBJECT()的確會產生一些問題,不過還好目前會用EXCEL.EXE 的基本上只有OFFICE,而且我們處理這段只是提供給使用者能減少一些手動釋放動作,如果真有問題,還是得請他們自行在工作管理員做處理。
編輯記錄
P.D. 重新編輯於 2007-07-15 00:38:25, 註解 無‧
|
Kingron
中階會員 ![]() ![]() ![]() 發表:1 回覆:51 積分:60 註冊:2005-09-14 發送簡訊給我 |
VarClear就是和 sheet := nil一样类似的效果,可以认为是对Variant的FreeAndNil。
至于为什么对WorkSheet和WorkBook等等也要类似处理,这是因为应用计数导致的。 Delphi本身对COM是隐式进行了AddRef和ReleaseRef的,不需要我们显示调用,但这里有一个前提就是你的顺序很重要! 例如以下的例子: 假设: Var App, Book, Sheet: OleVariant; // 这是创建和使用 App = Create Excel OLE Variant Object; Book = App.WorkBooks.Add; Sheet = Book.Sheets("Sheet1"); do something... 上面的代码会导致这些变量被顺序增加引用计数:Book这一行会隐式给App的Ref 1!其余类似 .// 以下是释放,应该严格遵守反向的顺序 VarClear(Sheet); --> 1 VarClear(Book); --> 2 App.Quit; --> 3 VarClear(App); --> 4 上面的代码中,如果 2和1交换,就可能出现一个不好的现象: Book的计数被-1,但实际上,Book的子对象被引用了,也就是那个Sheet没有释放,从而导致Sheet在内存中还是真正存在的,但对程序代码来说,Book已经被释放掉了! 同样的道理,如果3方在1的前面,就出现问题了! App.Quit会试图去Quit Excel,此时App变量是Free掉了,我们不能再使用,但是因为Shee和Book还在,OLE为了保证安全,在内存中还是需要维持Excel进程的,因此Quit并没有真正生效!这也就是很多时候Quit不正常的原因:在某些时候,OLE调用出错,结果某些局部的OLE变量,例如Sheet,Graph等没有正常释放,导致Quit不能正常退出Excel。 所有的错误都是可以抓住的,看你的编程习惯而已。如果偷懒,可以在调用的例程最外面添加一个try except end捕获异常即可。 如果在操作的时候,最好是Disable Excel的ScreenUpdating = False; Interactiv = False,禁止用户操作和更新界面,以保证安全和提高效率,即使中途Crash,也可以用try except 抓取得,实际上是个体力活,但可以保证代码质量。 很多病毒使用EXCEL的进程名哈~ 当然,Kill Excel 进程的做法也是可取的,但可能会导致用户丢失数据 ===================引 用 P.D. 文 章=================== 感謝kingron的說明,讓我又學習到一個用法,否則我還真不知有varclear()的用法 不過這個varclear 與 quit 的關係如何,我看了一下說明不是很清楚,是不是與 form1.free 並未真正釋放該記憶區塊,所以都會以FreeandNil()或Form1:= nil再徹底消減該變數的道理相同呢? 但對於 worksheet, workbook 也要如此做,我就存在很大的好奇心了。 另外,對於excel.exe 未被正確處理異常,這有時實在很難控制,例如可能對方執行另一個程式也啟動excel, 或者直接呼叫excel ,或者在我的程式中啟動了excel, 但中途當機,這都不是 try ... except 可以捕捉的到然後再正常的釋放的情況,所以才會想搜尋Processes中是否有殘留的EXCEL.EXE 存在,而的確如果有很多個EXCEL.EXE存在時,GETATIVEOLDOBJECT()的確會產生一些問題,不過還好目前會用EXCEL.EXE 的基本上只有OFFICE,而且我們處理這段只是提供給使用者能減少一些手動釋放動作,如果真有問題,還是得請他們自行在工作管理員做處理。
------
超级猛料:http://kingron.delphibbs.com |
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |