デスクトップ以外の他のアプリの窓を全て閉じるには?

[戻る]
持田 2001/05/08(火) 11:51:52
ExitWinだとwin2000などでは、ログインのダイアログボックスが表示されてしまいます
ダイアログボックスを表示せずに 他のアプリを全て終了させるか
特定のユーザーIDで自動的に再ログインしたいのですが 教えてください

目的はある人がインターネットやゲームを使用して複数の窓を開いたまま一定時間放置すると
次の人のために元のホームページを表示しておきたいのです
(店頭のデモ機のように)

Bun 2001/05/08(火) 13:22:00
> 他のアプリを全て終了させるか

うまくいくかは解りませんが・・・
EnumWindows()で画面上のトップレベルウィンドウのハンドルを次々に取得して
終了させたいWindows(ハンドル)に対してのみ、SendMessage(WM_CLOSE)して
あげてはいかがでしょうか?

持田 2001/05/14(月) 02:15:24
遅れてすいません

基本的にMFCしか使えないのでウインドウハンドルとやらが
でてくるとお手上げです
ヘルプを見て試行錯誤しましたがどうもうまくいきません

もう少しヒントを下さい

持田 2001/05/14(月) 02:25:58
遅れてすいません

基本的にMFCしか使えないのでウインドウハンドルとやらが
でてくるとお手上げです
ヘルプを見て試行錯誤しましたがどうもうまくいきません

もう少しヒントを下さい

Bun 2001/05/14(月) 08:12:18
どうも質問の内容をきちんと理解できていないようです。
もう少し詳しく説明して頂けますか?

> ExitWinだとwin2000などでは、ログインのダイアログボックスが表示されてしまいます

知らないのですが、ExitWinって何でしょうか?

「現在デスクトップ上に存在する自分以外のWindowsをすべて終了させる。」(だけの)
方法で良いでしょうか? うまくいくかはわかりませんが(^^;

持田 2001/05/14(月) 21:58:17
省略してすみません
ExitWindowsEx(EWX_FORCE,EWX_FORCE);
ExitWindowsEx(EWX_REBOOT,EWX_REBOOT);
などを試しましたが

デスクトップも閉じてしまう(?)ようで
ログオフ->ログインパスワードを求められてしまいます

ようするに自身も含めて全てのアプリを強制終了させたいのです
よろしくお願いします

Bun 2001/05/15(火) 22:06:52
結構たいへんです。この問題は。(泣き;

ちなみに、開発の環境はなんでしょうか?
Wind98ですか? 95ですか? それともNTでしょうか?

たしか、MFCで作成でしたね。

ダイアログベースでしょうか?
あと、MS IMEの問題とかもあるようです。使ってますか?
もーあっしの手には負えません。

もーちょっと調べてみます。
やりかたは別として、細かいところがわからなくて
よそでいろいろ教わってきました。

基本方針としては(勝手に私が決めたのですが・・・)
EnumWindows()という関数で起動中のトップレベルウィンドウの
ハンドルを次々に取得し、デスクトップの場合はWM_CLOSEせずに
それ以外のアプリの場合にはWM_CLOSEさせるということを実現
しようとしています。

細かいことがあれこれとあるようで、調査中です。
(注意:必ずうまくいくという保障はないです)

持田 2001/05/15(火) 23:22:17
どうも、お手数かけます

CALLBACK 関数というのが理解できなくててこづりましたが
なんとか作ってみました

が、シャットダウンダイアログが出て来ます。
デスクトップかどうかどうやって判断しますか


BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    if(hwnd==NULL)    return FALSE;  //これは不要かも?
    SendMessage(hwnd,WM_CLOSE,lParam,lParam);
    return TRUE;

};


...

EnumWindows(EnumWindowsProc,32);  //32は適当?

Bun 2001/05/16(水) 01:01:08
夜Bunです。

// ソースをのせますが、問題はたくさんありそうです。
// 一応終了ダイアログは出なくなりました。
// 実験はVC6を使わないで、EXEで試した方が良いかも知れません。(危ないので)
// また、データなどをきちんと保存している状態で試験してください。
// (どっかがおかしくなったりしそうな・・・ 汗)
// あと、タスクトレイの表示が消えたりしますね。 <---仕様にはない(勘弁)

// VC6, MFC, ダイアログベースで作成

// ボタンを押した場合に終了処理をする場合
void CCloseDlg::OnButton1() 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    ::EnumWindows(::EnumWndProc, 0);    // ハンドルを取得する

}

// グローバル関数なので
// 普通これはcppファイルの先頭あたりに記述する。
BOOL CALLBACK EnumWndProc(HWND, LPARAM);    // プロトタイプ宣言

// こちらもcppファイル内に記述する
BOOL CALLBACK EnumWndProc(HWND hWnd, LPARAM lParam)
{
    
    // Windowsの終了ダイアログを出すハンドルの取得
    HWND hwndTaskBar = ::FindWindow("Shell_TrayWnd", "");

    DWORD dwExplorerPID, dwAnotherPID;

    // 終了ダイアログを出すトップウィンドウはデスクトップやタスクバーがある
    // これらは同じプロセスIDなのでプロセスIDで判定する

    // ハンドルからプロセスIDを取得
    ::GetWindowThreadProcessId(hwndTaskBar, &dwExplorerPID);
    ::GetWindowThreadProcessId(hWnd, &dwAnotherPID);

    if (dwExplorerPID == dwAnotherPID) // IDがデスクトップ、タスクバーの場合は
    {
        ; // 終了ダイアログを出さないようにWM_CLOSEしない
    }
    else
    {
        ::PostMessage(hWnd, WM_CLOSE, 0, 0); // 終了させる
    }
    return TRUE;

}

持田 2001/05/16(水) 23:10:05
こちらの環境で試してみましたが、どうも不安定です

閉じてはいけない窓まで閉じてしまったのかも・・

逆転の発想で指定した exeファイルのみ閉じる(実行されていれば)
というのはどうか? とふと思いつきました。

hWndからその実行ファイル名を知る事はできるのでしょうか

ku 2001/05/17(木) 16:02:14
exeで判定できるかどうかは知りませんが
ウィンドウハンドルから実行ファイルのフルパスを得る方法はこんな感じです。

HINSTANCE hInst = (HINSTANCE)GetWindowLong(ウィンドウハンドル, GWL_HINSTANCE);
char szPath[MAX_PATH + 1];
GetModuleFileName(hInst, szPath, sizeof(szPath));

Bun 2001/05/17(木) 21:42:46
持田様、お疲れさまです。もう一息っす。がんばってください。

私がたてた方針では、隠れているウィンドウ(例えばIME等)があった場合には
それらも終了してしまいますよね。
良くないとは思いますが、これは最初の質問の意図からははずれていまいと思います。
ですから、終了させたくないアプリは全て調査しなくてはいけないと思うのです。

ku様
はじめまして、Bunと申します。
いつも参考にさせて頂いております。

> exeで判定できるかどうかは知りませんが

exeで判定しても同じような結果になると思うのですが、いかがでしょうか?

私はこう考えています。
終了させてはいけないすべてのトップレベルウィンドウを理解する。
そして、これらのウィンドウ以外に対してPostMessage(WM_CLOSE)する。

終了させてはいけないすべてのウィンドウを理解するにはどうすれば良いのでしょうか?

方針が決まれば、あとは力仕事を持田様ががんばるってことで結果が出るような気がします。
何かヒントがあれば、ご意見をお待ちしております。
よろしくお願いします。

Bun 2001/05/20(日) 08:53:26
「こうすれば良いのでは?」という考えだけ述べさせて頂きます。

動作が不安定になる原因は、終わらせてはいけないプログラムに対して
PostMessage(WM_CLOSE)していることだと思います。
ですから、終わらせてはいけないプログラムを見つけて、EnumWndProc()内で
そのプログラムに対してはPostMessage(WM_CLOSE)しないようにすれば良いと
思います。

もともと、Windowsの終了ダイアログが出なければ良いという話でしたが
そうではなく、その他にも終了してはいけないプログラムがあるということですね。

ですから、FindWindow()で終了してはいけないプログラムのハンドルを全て取得して
このEnumWndProcルーチン内のhWndがそれらのどれかに等しい場合には、WM_CLOSEをPostしなければ
良いわけです。(実際にはプロセスIDで判定しますけど)

下記のようにGetClassName()でhWndからクラス名が取得できます。
こんな感じで適当にブレークポイントをもうけて、クラス名を確認しながら、終了してはいけない
プログラム( = クラス名)をあらかじめ調べておきます。
そして下記のように終了してはいけないプログラムの数だけ判定をすれば良いと思います。

#一番たいへんなのは、(ハングアップしながら)終了してはいけないプログラムを探すこと
#だと思います。(T_T;
#私には、このくらいしか思いつきません。
#がんばってください。

BOOL CALLBACK EnumWndProc(HWND hWnd, LPARAM lParam)
{

    DWORD dwExplorerPID[100], dwAnotherPID;

    // Windowsの終了ダイアログを出すハンドルの取得
    HWND hWndTask = ::FindWindow("Shell_TrayWnd", "");
    // ハンドルからプロセスIDを取得
    ::GetWindowThreadProcessId(hWndTask, &dwExplorerPID[0]);

    HWND hWndTask = ::FindWindow("終了してはいけないクラス名", "");
    // ハンドルからプロセスIDを取得
    ::GetWindowThreadProcessId(hWndTask, &dwExplorerPID[1]);

    .    // 必要なだけPIDを取得する
    .
    .
    .

    // 終了ダイアログを出すトップウィンドウはデスクトップやタスクバーがある
    // これらは同じプロセスIDなのでプロセスIDで判定する

    ::GetWindowThreadProcessId(hWnd, &dwAnotherPID);

    char buff[256];
    ::GetClassName(hWnd, buff, 255);

    if (dwExplorerPID[0] == dwAnotherPID)
    {
        ;
    }
    else if (dwExplorerPID[1] == dwAnotherPID)
    {
        ;
    }
    else if (dwExplorerPID[n] == dwAnotherPID)
    {
        ;    // 必要な数だけ比較する
    }
    else
    {
        ::PostMessage(hWnd, WM_CLOSE, 0, 0);
    }
    return TRUE;

}

古いスレッドには追加発言できません。