自作アプリからCreateOleObjectでエクセルを操作しているのですが、
エクセルの閉じるボタンで終了するとバックグラウンド
(タスクマネージャーのプロセス)にエクセルの残骸が
残ってしまいます。
閉じるボタンでエクセルを終了しても残骸が残らないように
するにはどのようにすれば良いのでしょうか?
・・ですが
https://www.petitmonte.com/bbs/answers?question_id=2577
強引にプロセス終了しちゃう、というのは?
いきあたりばったりさんありがとうございます。
参考にして色々試してみます。
んじゃ、こっちは?
https://www.petitmonte.com/bbs/answers?question_id=1808
> SKJP 2004/07/05(月) 13:21:08
> myWorkSheet := unAssigned;
> myWorkBook := unAssigned;
> myExcel.Quit;
> myExcel := unAssigned;
>
> にて全てが解放され、プロセスも完全に消滅しました。
ofzさんへ
MainFormのCloseでunAssignedとQuitはしているのですが、
MainFormのClose前だとやはり・・・。
自アプリでCreateしたExcelのみを監視して
該当Excelが閉じられた時にそのプロセスのみを
強制終了させる方法などはないんでしょうか?
色々聞いてばかりでスミマセン。
> 自アプリでCreateしたExcelのみを監視して
起動した、プロセスのプロセスIDを取得することができるかどうかですよね。
起動する前に、プロセス一覧Aを得ておいて
起動後にプロセス一覧Bを得て、
その差分の中から、Excel.exeをみつけだしておき
・・・
っていっても、Excelの閉じるボタンが押された事を知ることはできないのか。
自アプリから操作するExcelは非表示にしてしまうとか
自アプリからの操作が完了したら、上記のプロセスIDを取得しておいて
それを強制終了するとか、
そういう感じでしょうか。
Fusaさんの言う通り今は
>自アプリから操作するExcelは非表示にしてしまうとか
にて対応してます。
自アプリで作成したExcelデータ(Excelは非表示)を
一旦ファイルとして出力した後に
unAssignedとQuitといった風にしていますが、
ファイルとして吐き出さずに自アプリで作成したExcelのシートに
手を加えたりしたいんですよ。
でも何か大変な事になりそうですね。
お考えとは思いますが
テンポラリとしてファイル保存して、処理終了してから
再度、ユーザーの為にテンポラリファイルを
エクセルで開いてみてはいかがでしょうか?
だめなのかな?
>テンポラリとしてファイル保存して、処理終了してから
>再度、ユーザーの為にテンポラリファイルを
>エクセルで開いてみてはいかがでしょうか?
おお!なるほど、この手が有りましたね!
スミマセンがテンポラリとしてファイル保存した後
どの様にしてエクセルで開けば良いでしょうか?
Fusaさん何から何まで聞いてばかりでスミマセン。
//--------------------------
// CBTをHOOKする為のDLL
//--------------------------
library CBTHook;
uses
Windows,Classes,SysUtils,Messages;
{$R *.RES}
var
HCBTHook: Integer;
WM_WINDOWDESTROY : UINT;
function CBTProc(nCode,Wparam,Lparam :Integer) :Integer; stdcall;
var
List : TStringList;
I : Integer;
HProcess: Integer;
begin
if nCode < 0 then
begin
Result := CallNextHookEx (0,nCode,WParam,LParam);
end
else
begin
if nCode = HSHELL_WINDOWDESTROYED then
begin
PostMessage(HWND_BROADCAST ,WM_WINDOWDESTROY ,WParam,LParam);
Beep;
end;
end;
end;
//HOOK開始
procedure SetCBTHook;stdcall;
begin
HCBTHook := SetWindowsHookEx(WH_SHELL, @CBTProc,hInstance,0);
end;
//HOOK解除
function UnHookCBTHook:Boolean;stdcall;
begin
UnhookWindowsHookEx(HCBTHook);
end;
exports
SetCBTHook,UnHookCBTHook;
begin
WM_WINDOWDESTROY := RegisterWindowMessage('CBTWindowDestroy');
end.
//----------------
// 本体プログラム
//----------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComObj, StdCtrls, ProcessServiceUnit;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
public
procedure ApplicationMessage(var Message: TMSG; var Handled: Boolean);
end;
var
Form1: TForm1;
CBTModuleHandle: HModule;
WM_WINDOWDESTROY: UINT;
SaveWinProc: TWndMethod;
Excel: Variant;
WorkBook: Variant;
WorkSheet: Variant;
ExcelWindowHandle : HWND;
procedure SetCBTHook;stdcall;external 'CBTHook.dll' name 'SetCBTHook';
procedure UnHookCBTHook;stdcall; external 'CBTHook.dll' name 'UnHookCBTHook';
implementation
{$R *.dfm}
procedure TForm1.ApplicationMessage(var Message: TMSG; var Handled: Boolean);
var
List: TStringList;
I : Integer;
begin
if Message.message = WM_WINDOWDESTROY then
begin
if Message.WParam = ExcelWindowHandle then
begin
List:=TStringList.Create;
GetProcessList(List);
I := Integer(List.Objects[List.IndexOf('EXCEL.EXE')]);
if I<>-1 then ProcessTerminate(I);
List.Free;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SaveCaption : String;
begin
if OpenDialog1.Execute = True then
begin
Excel := CreateOleObject('Excel.Application');
SaveCaption := Excel.Caption;
ExcelWindowHandle := FindWindow(nil,PChar(SaveCaption));
Excel.Caption := SaveCaption;
WorkBook :=Excel.WorkBooks.Open(FileName := OpenDialog1.FileName , readOnly := False);
WorkSheet := WorkBook.WorkSheets[1];
Excel.Visible:= True;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnHookCBTHook;
try
WorkBook.close;
WorkBook:=unAssigned;
WorkSheet:=unAssigned;
except
end;
try
Excel.Quit;
Excel:=unAssigned;
except
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := ApplicationMessage;
WM_WINDOWDESTROY := RegisterWindowMessage('CBTWindowDestroy');
SetCBTHook;
end;
end.
DLL のほうの BEEP は消しておいて
あと本体の
CBTModuleHandle: HModule;
SaveWinProc: TWndMethod;
も消しといて
ProcessServiceUnit は
http://khe00221.image.coocan.jp/index.php?FrontPage%2FUnit%2FProcessServiveUnit.pas
>SaveCaption := Excel.Caption;
ExcelWindowHandle := FindWindow(nil,PChar(SaveCaption));
>Excel.Caption := SaveCaption;
ここも必要ないな・・・
function CBTProc(nCode,Wparam,Lparam :Integer) :Integer; stdcall;
>var
>List : TStringList;
>I : Integer;
>HProcess: Integer;
これも必要ない
WH_CBTじゃなくて WH_SHELL だった
KHE00221さん有難うございます。
試してみます。
結果は追って報告します。
ツイート | ![]() |