自作アプリ以外からExcelを閉じた時の残骸を無くすには?


キュー太  2008-02-13 23:06:00  No: 29801

自作アプリからCreateOleObjectでエクセルを操作しているのですが、
エクセルの閉じるボタンで終了するとバックグラウンド
(タスクマネージャーのプロセス)にエクセルの残骸が
残ってしまいます。
閉じるボタンでエクセルを終了しても残骸が残らないように
するにはどのようにすれば良いのでしょうか?


いきあたりばったり  2008-02-14 07:40:47  No: 29802

・・ですが
https://www.petitmonte.com/bbs/answers?question_id=2577

強引にプロセス終了しちゃう、というのは?


キュー太  2008-02-15 07:39:04  No: 29803

いきあたりばったりさんありがとうございます。
参考にして色々試してみます。


ofZ  2008-02-15 17:17:52  No: 29804

んじゃ、こっちは?
https://www.petitmonte.com/bbs/answers?question_id=1808

> SKJP 2004/07/05(月) 13:21:08
>  myWorkSheet := unAssigned;
>  myWorkBook := unAssigned;
>  myExcel.Quit;
>  myExcel := unAssigned;

> にて全てが解放され、プロセスも完全に消滅しました。


キュー太  2008-02-15 19:17:02  No: 29805

ofzさんへ
MainFormのCloseでunAssignedとQuitはしているのですが、
MainFormのClose前だとやはり・・・。
自アプリでCreateしたExcelのみを監視して
該当Excelが閉じられた時にそのプロセスのみを
強制終了させる方法などはないんでしょうか?
色々聞いてばかりでスミマセン。


Fusa  2008-02-15 19:35:06  No: 29806

> 自アプリでCreateしたExcelのみを監視して

起動した、プロセスのプロセスIDを取得することができるかどうかですよね。
起動する前に、プロセス一覧Aを得ておいて
起動後にプロセス一覧Bを得て、
その差分の中から、Excel.exeをみつけだしておき
・・・
っていっても、Excelの閉じるボタンが押された事を知ることはできないのか。

自アプリから操作するExcelは非表示にしてしまうとか
自アプリからの操作が完了したら、上記のプロセスIDを取得しておいて
それを強制終了するとか、

そういう感じでしょうか。


キュー太  2008-02-16 01:26:25  No: 29807

Fusaさんの言う通り今は
>自アプリから操作するExcelは非表示にしてしまうとか
にて対応してます。
自アプリで作成したExcelデータ(Excelは非表示)を
一旦ファイルとして出力した後に
unAssignedとQuitといった風にしていますが、
ファイルとして吐き出さずに自アプリで作成したExcelのシートに
手を加えたりしたいんですよ。
でも何か大変な事になりそうですね。


Fusa  2008-02-16 02:54:39  No: 29808

お考えとは思いますが

テンポラリとしてファイル保存して、処理終了してから
再度、ユーザーの為にテンポラリファイルを
エクセルで開いてみてはいかがでしょうか?

だめなのかな?


キュー太  2008-02-16 03:15:32  No: 29809

>テンポラリとしてファイル保存して、処理終了してから
>再度、ユーザーの為にテンポラリファイルを
>エクセルで開いてみてはいかがでしょうか?

おお!なるほど、この手が有りましたね!
スミマセンがテンポラリとしてファイル保存した後
どの様にしてエクセルで開けば良いでしょうか?
Fusaさん何から何まで聞いてばかりでスミマセン。


KHE00221  2008-02-16 03:38:29  No: 29810

//--------------------------
// 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.


KHE00221  2008-02-16 03:39:11  No: 29811

//----------------
// 本体プログラム
//----------------
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.


KHE00221  2008-02-16 03:41:33  No: 29812

DLL のほうの BEEP は消しておいて


KHE00221  2008-02-16 03:44:05  No: 29813

あと本体の
CBTModuleHandle: HModule;
SaveWinProc: TWndMethod;
も消しといて


KHE00221  2008-02-16 03:46:10  No: 29814

ProcessServiceUnit は

http://khe00221.image.coocan.jp/index.php?FrontPage%2FUnit%2FProcessServiveUnit.pas


KHE00221  2008-02-16 03:48:38  No: 29815

>SaveCaption := Excel.Caption;
ExcelWindowHandle := FindWindow(nil,PChar(SaveCaption));
>Excel.Caption := SaveCaption;

ここも必要ないな・・・


KHE00221  2008-02-16 03:50:45  No: 29816

function CBTProc(nCode,Wparam,Lparam :Integer) :Integer; stdcall;
>var
>List : TStringList;
>I : Integer;
>HProcess: Integer;

これも必要ない


KHE00221  2008-02-16 04:08:43  No: 29817

WH_CBTじゃなくて WH_SHELL だった


キュー太  2008-02-17 18:19:29  No: 29818

KHE00221さん有難うございます。
試してみます。
結果は追って報告します。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加