質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.62%

  • C

    3558questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3324questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    215questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

(WINAPI)タスク常駐アプリのアイコン-visual studioでデバッグ中は表示されるが、exeファイルでは非表示

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 413

mercurian-teto

score 42

windowsAPIでタスク常駐するアプリを作成したのですが、
visual studioでデバッグして実行しているときには
常駐アプリが表示されるタスクトレイにアイコンが表示されていました。
しかし、

エクスプローラーでビルドして出来上がったexeファイルのものを実行すると
タスクバーにアイコンが表示されませんでした。

メッセージボックスのアイコンは両方正常に表示されます。

なぜこのような現象が起こるのかわからないのですが、
出来上がった実行ファイルでも同様にタスクトレイにアイコンが表示されるようにするにはどうすればいいですか。

下のコードが実際に実行したコードです。

試したこと

このサイトにある通りコードを追加したりしました。

実行環境

windows 10 pro 
visual studio 2017

コード

#include <Windows.h>
#include <tchar.h>
#include "resource.h"
#include <stdarg.h>
#include <stdbool.h>
#include <Shlwapi.h>
#include <locale.h>



#define WM_TASKTRAY (WM_USER+1)
#define ID_TASKTRAY 0
#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))


void SetShutdownPriority();



HWND    g_hWnd;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    static UINT s_uTaskbarRestart;
    SetShutdownPriority();

    switch (msg)
    {
    /*case WM_CREATE:
    {
        s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
        return 0;

    }break;*/

    case WM_TASKTRAY:
        if (wParam == ID_TASKTRAY)
        {
            switch (lParam) {


                break;
            case WM_LBUTTONUP:

                int iRetYesNo;



                iRetYesNo = MessageBox(NULL, _T("RAguardを終了しますか"), _T("RAguard"), MB_YESNO | MB_ICONQUESTION);
                if (iRetYesNo == IDYES) {

                    setlocale(LC_ALL, "Japanese");

                    //メモ帳のウィンドウを探す
                    HWND hWnd = FindWindow
                    (_T("WindowsForms10.Window.8.app.0.141b42a_r6_ad1"),
                        _T("パソコンねむねむPro"));
                    if (hWnd != NULL)
                    {
                        MessageBox(NULL, _T("ぱそこんねむねむが起動中です"),
                            _T("RAguard"), MB_OK | MB_ICONWARNING);




                    }


                    else
                    {
                        MessageBox(NULL, _T("処理が完了しました"), _T("RAguard"), MB_OK);
                        ::PostQuitMessage(0);                               //!< WM_QUITを送る
                        return ::DefWindowProc(hWnd, msg, wParam, lParam);



                    }
                }










                if (iRetYesNo == IDNO) {

                    return -2;
                }
            }

        }
        break;


    case WM_QUERYENDSESSION:

        ShutdownBlockReasonCreate(hWnd, L"パソコンねむねむを終了させるか、RAGuardを終了してください");

        // Prevent shutdown. Return FALSE as a return value for WM_QUERYENDSESSION.
        // If your window is not a dialog, you can simply use `return FALSE`.
        // シャットダウンを抑制するために FALSE を返します。
        // 通常のウィンドウなら `return FALSE` で構いません。

        return FALSE;

    case WM_ENDSESSION:


        // Do nothing.
        break;

    case WM_DESTROY:                                       //!< ウインドウを閉じる
        ::PostQuitMessage(0);                               //!< WM_QUITを送る
        return ::DefWindowProc(hWnd, msg, wParam, lParam);
    default:
        /*if (msg == s_uTaskbarRestart)
        {
            s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
            return 0;
        }*/
        return ::DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

BOOL Init(HINSTANCE hInstance)
{
    /*HANDLE hMSP;
    hMSP = CreateMutex(NULL, TRUE, _T("MultiplexStartingPreventionTest"));
     すでに起動しているか判定 
    if (GetLastError() == ERROR_ALREADY_EXISTS) {


        ReleaseMutex(hMSP);
        CloseHandle(hMSP);
        return FALSE;
    }*/
    // ウインドウ生成
    WNDCLASS                wc;                                       //!< ウインドウクラス
                                                                      // ウインドウクラスの登録
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = static_cast<WNDPROC>(WndProc);    //!< メッセージを受け取るウインドウ関数
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);                                   //!< アイコン登録
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);    //!< カーソル登録
    wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
    wc.lpszMenuName = NULL;                        //!< メニューの登録
    wc.lpszClassName = L"パソコンねむねむPro";

    // ウインドウクラスの登録
    if (!::RegisterClass(&wc)) return EXIT_FAILURE;

    // ウインドウを作成
    g_hWnd = ::CreateWindow(L"パソコンねむねむPro",                     //!< クラス名
        L"パソコンねむねむPro",                                            //!< タイトル名
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU, //!< スタイル
        0,                                                    //!< X座標
        0,                                                    //!< Y座標
        100,                                                //!< 横幅
        100,                                                //!< 高さ
        NULL,                                          //!< 親ウインドウのハンドル
        NULL,                                          //!< メニューハンドル
        hInstance,                                   //!< インスタンスハンドル
        NULL);                                        //!< lParam

                                                      // ウインドウの作成
    if (!g_hWnd) return EXIT_FAILURE;
    // ウインドウの表示状態の設定
    ::ShowWindow(g_hWnd, SW_HIDE);
    // ウインドウの更新
    ::UpdateWindow(g_hWnd);


    NOTIFYICONDATA nif;
    // タスクトレイに登録
    nif.cbSize = sizeof(NOTIFYICONDATA);
    /*nif.hIcon =  LoadIcon(NULL, IDI_APPLICATION);*/
    nif.hIcon = (HICON)LoadImage(0, TEXT("shutdown.ico"),
    IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
    nif.hWnd = g_hWnd;
    nif.uCallbackMessage = WM_TASKTRAY;
    nif.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nif.uID = ID_TASKTRAY;
    ::wcscpy_s(nif.szTip, 128, L"RAguard");

    Shell_NotifyIcon(NIM_ADD, &nif);

    return EXIT_SUCCESS;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;

    if (Init(hInstance) == EXIT_FAILURE) return EXIT_FAILURE;

    while (::GetMessage(&msg, NULL, 0, 0))
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
    return EXIT_SUCCESS;
}


void SetShutdownPriority()
{
    int i;
    EXECUTION_STATE state;

    DWORD priorityLevels[5] = { 0x4FF, 0x4F0, 0x3FF, 0x3F0, 0x300 };
    for (i = 0; i < 5; i++)
        if (SetProcessShutdownParameters(priorityLevels[i], 0))
            break;

    // ついでにプロセスをスタンバイや画面オフから守る
    state = ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED;
    SetThreadExecutionState(state);
}

編集したところ

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = static_cast<WNDPROC>(WndProc);    //!< メッセージを受け取るウインドウ関数
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, iconid);;                                   //!< アイコン登録
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);    //!< カーソル登録
    wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
    wc.lpszMenuName = NULL;                        //!< メニューの登録
    wc.lpszClassName = L"パソコンねむねむPro";
    NOTIFYICONDATA nif;
    // タスクトレイに登録
    nif.cbSize = sizeof(NOTIFYICONDATA);
    nif.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SMALL));



    nif.hWnd = g_hWnd;
    nif.uCallbackMessage = WM_TASKTRAY;
    nif.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nif.uID = ID_TASKTRAY;
    ::wcscpy_s(nif.szTip, 128, L"RAguard");

    Shell_NotifyIcon(NIM_ADD, &nif);

    return EXIT_SUCCESS;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

    nif.hIcon = (HICON)LoadImage(0, TEXT("shutdown.ico"),
    IMAGE_ICON, 0, 0, LR_LOADFROMFILE);

これちゃんと取得できてますか?
具体的には、NULLが返ってきてないか調べてみてはいかがでしょうか。

なんとなく予想としてはカレントディレクトリからshutdown.icoを探そうとして失敗している予感がします。
実行ファイルの場合カレントディレクトリは想定外の場所になることもあるので
(ショートカットファイルを作成したり、D&Dとか)
必要ならばGetModuleFileName+PathRemoveFileSpec<filesystem>等を使って実行ファイルのあるディレクトリを取得してカレントディレクトリにする
などの措置が必要になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/28 17:28

    パスでの設定方法も試してみます。ありがとうございました。

    キャンセル

checkベストアンサー

+1

asmさんの回答の通り、エクスプローラーから起動したことでカレントディレクトリーが変わり、アイコンファイル(shutdown.ico)のロードに失敗していることが原因でしょう。

アイコンファイルはソースファイルと同じ場所(プロジェクトを作ったフォルダー)に置かれていると思いますが、Visual Studioから起動すればそこがカレントフォルダーになるので正しくロードできます。一方、エクスプローラーから起動すると、EXEファイルの場所がカレントフォルダーになります。そこにアイコンファイルがなければ当然ロードに失敗します。ロードに失敗すればアイコンは表示されません。

パス操作でアイコンファイルを正しくロードできるようにするのも良いですが、よりスマートな解決策としては、アイコンイメージをリソースにしてEXEファイルに埋め込むことです。そうすればパスを気にする必要はありませんし、配布の際もEXEファイル1個で済みます。
Windowsアプリでは、アイコンイメージを(アイコンに限らずGUI関連のビットマップイメージ等も)リソースで持つことはごく一般的に行われています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/28 17:28

    ありがとうございました。

    キャンセル

0

リソースをexeファイルに埋め込む方針にしました。

とりあえず、

visual studio 新規作成→プロジェクト→windowsデスクトップウィザード

windowsデスクトップ プロジェクトでは

プリコンパイル済みヘッダー(P)
セキュリティ関連ライフサイクル(SDL)チェック(C)
にチェックを入れました。

エクスプローラーに移動して
デフォルトで作成されてある

プログラム名.ico
small.ico


設定したいアイコン画像で上書きして、

アイコンのロード先を変更するように追記した通りにコードを修正したら、

タスクバーに表示されるアイコンや実行ファイルのアイコンが正常に表示されるようになりました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3558questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3324questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    215questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • トップ
  • C++に関する質問
  • (WINAPI)タスク常駐アプリのアイコン-visual studioでデバッグ中は表示されるが、exeファイルでは非表示