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


キュー太  2008-02-13 14:06:00  No: 29801  IP: 192.*.*.*

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

編集 削除
いきあたりばったり  2008-02-13 22:40:47  No: 29802  IP: 192.*.*.*

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

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

編集 削除
キュー太  2008-02-14 22:39:04  No: 29803  IP: 192.*.*.*

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

編集 削除
ofZ  2008-02-15 08:17:52  No: 29804  IP: 192.*.*.*

んじゃ、こっちは?
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 10:17:02  No: 29805  IP: 192.*.*.*

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

編集 削除
Fusa  2008-02-15 10:35:06  No: 29806  IP: 192.*.*.*

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

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

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

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

編集 削除
キュー太  2008-02-15 16:26:25  No: 29807  IP: 192.*.*.*

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

編集 削除
Fusa  2008-02-15 17:54:39  No: 29808  IP: 192.*.*.*

お考えとは思いますが

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

だめなのかな?

編集 削除
キュー太  2008-02-15 18:15:32  No: 29809  IP: 192.*.*.*

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

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

編集 削除
KHE00221  2008-02-15 18:38:29  No: 29810  IP: 192.*.*.*

//--------------------------
// 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-15 18:39:11  No: 29811  IP: 192.*.*.*

//----------------
// 本体プログラム
//----------------
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-15 18:41:33  No: 29812  IP: 192.*.*.*

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

編集 削除
KHE00221  2008-02-15 18:44:05  No: 29813  IP: 192.*.*.*

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

編集 削除
KHE00221  2008-02-15 18:46:10  No: 29814  IP: 192.*.*.*

ProcessServiceUnit は

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

編集 削除
KHE00221  2008-02-15 18:48:38  No: 29815  IP: 192.*.*.*

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

ここも必要ないな・・・

編集 削除
KHE00221  2008-02-15 18:50:45  No: 29816  IP: 192.*.*.*

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

これも必要ない

編集 削除
KHE00221  2008-02-15 19:08:43  No: 29817  IP: 192.*.*.*

WH_CBTじゃなくて WH_SHELL だった

編集 削除
キュー太  2008-02-17 09:19:29  No: 29818  IP: 192.*.*.*

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

編集 削除