はじめまして。
Delphi6 Personalで初めてアプリを作りました。
常駐型のアプリなのですが、
Windowsの再起動や終了を行うと「アプリケーションが応答していません」の
メッセージ(強制終了するかどうか)が出ます。
これを回避する方法はあるのでしょうか?
(Delphiに関係の無い質問にも感じますが、宜しくお願いたします)
コードを見ないとわかりません。
なにかを待ってループしているところはありませんか?
早速の回答ありがとうございます。
ループのような処理は行っていないはずなのですが、
結果的にそのようなことになっているのか・・・。
ソースを見直して、主に気になったところは以下の内容です。
関係ありますでしょうか?
*.dprにてアプリケーションの二重起動防止を行っている処理があること。
※このようなソースです
Mutex := OpenMutex(MUTEX_ALL_ACCESS, False, MutexName);
if Mutex <> 0 then
begin
Handle := FindWindow(ClassName, WindowName);
SetForegroundWindow(Handle);
Exit;
end;
CreateMutex(nil, False, MutexName);
ホットキーでアプリを起動するために
ホットキー用のコンポーネント(※)を使用してキー押下時の処理があること。
※TGlobalHotkey 作者:たかみちえ
タスクトレイにてバルーンチップを一定時間表示するために
タイマーコンポーネントを使用している処理があること。
※これは常にEnabledをtrueにしてはいません
バルーンチップを一定時間表示したいときだけtrueにします
タスクトレイにアイコンを表示するコンポーネントを使っていたときに、
OSの終了時に反応してくれなくなる現象に遭遇したことがあります。
対応策は・・・わかりません(笑)
確実な再現性がなく、対処不能だった気がする。
解決策ではありませんが、そういうこともあったとだけ報告しておきます。
わたしの経験では、メッセージを受け取りたいけどウィンドウは表示したくない
というような場合には、よく AllocateHWnd() を使いますけど、このときの
Method: TWndMethod で DefWindowProc を呼び出してない場合は、ウィンドウズ終了に
応答しません。たかみちえさんの TGlobalHotkey は大丈夫です。あとは
ふむふむさんご指摘の「タスクトレイにアイコンを表示するコンポーネント」が
あやしいかもしれません。
以下を追加するとどうなりますか?
Windowsの終了を検知するルーチンですが・・・
private
procedure WMQueryEndSession(var Msg: TMessage); message WM_QUERYENDSESSION;
procedure TForm1.WMQueryEndSession(var Msg: TMessage);
begin
Msg.Result := 1;
end;
deldel さん
TForm は DefWindowProc で WM_QUERYENDSESSION に応答してるから大丈夫
なのでは? AllocateHWnd のように自前でウィンドウ関数を書くときには
注意が必要ですけど。
う〜ん、追加したらどうなるかなぁと思ったものですから・・・
解決の糸口が見えるかもしれませんしねぇ。
あと、こういった「何が悪いのかさっぱり」という状況では、
かなり面倒ですが、ある程度まとまったコードやコンポーネントを
削除して実行してみてエラーが出るかどうかを、出なくなるまで
繰り返すと、何が悪いのかがわかってくる場合もあります。
ま、最後の手段っぽいですけど^^;
ふむふむふむの助 さん、
anone さん、
deldel さん 本当にありがとうございます。
明確な原因が特定できそうにない質問で申し訳ないです。
みなさんの意見していただいたことを参考に試してみたいと思います。
1.タスクトレイにアイコンを表示するコンポーネントの調査(anone さん指摘)
2.Windowsの終了を検知するルーチン追加(deldel さん指摘)
3.ある程度まとまったコードやコンポーネントを削除して実行してみる(deldel さん指摘)
********************
いったん、これらの点をおいておきまして、
調べているうちに怪しそうなものを再度あげてみます。
アプリが終了するときに、
本当に終了するかの確認処理があるのを忘れていました。
これはどうなのでしょうか?
//”メインメニューの終了”によるアプリの終了
procedure TMainForm.MainMenuFileExitClick(Sender: TObject);
begin
//終了
Close;
end;
//”タスクトレイ ポップアップメニューの終了”によるアプリの終了
procedure TMainForm.TrayIconPopupMenuExitClick(Sender: TObject);
begin
//終了
Close;
end;
//いきなりアプリの終了をさせないために、確認を行っている
//(ここにくるのは、”メインメニューの終了”、
// ”タスクトレイ ポップアップメニューの終了”、
// ”Alt + F4 での終了”のはず)
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
//確認メッセージボックスの回答
AnswerWord: Word;
begin
AnswerWord := MessageDlg('本当に終了しますか?', mtConfirmation, [mbOK, mbCancel], 0);
if (AnswerWord <> mrOk) then
begin
CanClose := false;
end;
end;
********************
(これは上記にも関連し、質問の最初あたりに訂正・記述しておくべきことでした)
現時点で確認している動作です。
※詳細に確認できていないところもあり、異なるかもしれません
通常の再起動
アプリ自体の”終了するか確認”が出る。
(終了しないを選択するとWindows”すぐに終了”のメッセージが出る)
通常の終了
何も出ない。
他アプリによる再起動(ドライバインストール時など)
Windows”アプリケーションが応答していません”のメッセージ(強制終了するかどうか)が出る。
> これらの点をおいておきまして
これらの点が重要なんであって、普通に終了するときとは意味が違います。
>> これらの点をおいておきまして
>
>これらの点が重要なんであって、普通に終了するときとは意味が違います。
誤解させてしまったようです。すみませんでした。
”一旦”とひとこと付け加えたほうが良かったのかもしれません。
もちろん、指摘していただいたところは確認を行います。
2回目の投稿後に、前記の終了時の処理を行っているのを思い出し、
気になっていたものですから・・・。
すみませんでした(>_<)
ツイート | ![]() |