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

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

新規登録して質問してみよう
ただいま回答率
85.39%
C

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

Win32 API

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

C++

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

Q&A

解決済

4回答

25494閲覧

LNK2019 未解決の外部シンボル ~が関数~で参照されました。

mercurian-teto

総合スコア75

C

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

Win32 API

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

C++

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

0グッド

0クリップ

投稿2018/04/19 09:37

編集2018/04/20 11:57

レジストリを確認することで起動しているか否かを確認できる常駐プログラムが
起動している間、シャットダウンを抑止する常駐プログラムを作成しようと思っています。
コードは一番下に記載しております。

#環境
windows10 pro

Visual Studio2017

#やってみたこと
コンパイルしたところ

//エラー画面 LNK2019 未解決の外部シンボル "unsigned long __cdecl RegestryCheck(struct HKEY__ *,wchar_t const *,wchar_t const *,unsigned long *,void *,unsigned long *)" (?RegestryCheck@@YAKPAUHKEY__@@PB_W1PAKPAX2@Z) が 関数 "bool __cdecl GetValue(void)" (?GetValue@@YA_NXZ) で参照されました

というエラーが発生しました。

レジストリ参照についてはこちらのサイトを参照しました。
シャットダウン抑止についてはこちらを参照しました。
関数に関しては
プロトタイプ宣言もしていますし、組み込み関数をincludeで呼び出して言ると思うのですが、
ほかにどこか間違っているのでしょか。

文字セットはunicodeです。

回答お願いします。

#プログラミングコード

//shutdownkillguard.cpp #include <Windows.h> #include <tchar.h> #include "resource.h" #include <stdarg.h> #include <stdbool.h> #define WM_TASKTRAY (WM_USER+1) #define ID_TASKTRAY 0 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) void SetupShutdownBlock(bool noStandby, bool noScreenSaver); bool GetValue(); HWND g_hWnd; LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { 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) { bool checkpasonemu = GetValue(); if (checkpasonemu = false) { MessageBox(NULL, _T("処理が完了しました"), _T("RAguard"), MB_OK); return WM_DESTROY; } else { MessageBox(NULL, _T("ぱそこんねむねむが起動中です"), _T("RAguard"), MB_OK | MB_ICONWARNING); } } else { return -2; // -2を返す. } } } break; case WM_INITDIALOG: // Adjust process info to block shutdown. // スタンバイ等を抑制するためにプロセスの情報をあれこれ変更 SetupShutdownBlock(true, true); // Vista or later: You can display the reason of block (optional) // Vista 以降: シャットダウンできない理由を表示できます ShutdownBlockReasonCreate(hWnd, TEXT("ぱそこんねむねむの監視中です;)")); return (INT_PTR)TRUE; case WM_QUERYENDSESSION: // 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 (INT_PTR)TRUE; case WM_ENDSESSION: // Do nothing. break; case WM_DESTROY: //!< ウインドウを閉じる ::PostQuitMessage(0); //!< WM_QUITを送る return ::DefWindowProc(hWnd, msg, wParam, lParam); default: return ::DefWindowProc(hWnd, msg, wParam, lParam); } return ::DefWindowProc(hWnd, msg, wParam, lParam); } BOOL Init(HINSTANCE hInstance) { // ウインドウ生成 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 = NULL; //!< アイコン登録 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); //!< カーソル登録 wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)); wc.lpszMenuName = NULL; //!< メニューの登録 wc.lpszClassName = L"常駐"; // ウインドウクラスの登録 if (!::RegisterClass(&wc)) return EXIT_FAILURE; // ウインドウを作成 g_hWnd = ::CreateWindow(L"常駐", //!< クラス名 L"常駐", //!< タイトル名 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 = (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 SetupShutdownBlock(bool noStandby, bool noScreenSaver) { // Get OS version // OS のバージョンを取得 OSVERSIONINFO osVersion; osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osVersion); // Set shutdown order (highest priority) // シャットダウン時の処理順序を最高にする DWORD priorityLevels[5] = { 0x4FF, 0x4F0, 0x3FF, 0x3F0, 0x300 }; for (int i = 0; i < ARRAY_LENGTH(priorityLevels); i++) { if (SetProcessShutdownParameters(priorityLevels[i], 0) != FALSE) { break; } } if (noScreenSaver) { // Windows 7 or later? if (osVersion.dwMajorVersion == 6 && osVersion.dwMinorVersion >= 1) { // Cast a magic spell, I'm not sure why it is needed. // なんだろうこれ、おまじない BOOL screenSaveActive; SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &screenSaveActive, 0); SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, screenSaveActive, NULL, SPIF_SENDWININICHANGE); } } // Protect process from standby or screensaver. // プロセスをスタンバイや画面オフから守るように命じる EXECUTION_STATE state = ES_CONTINUOUS | (noStandby ? ES_SYSTEM_REQUIRED : 0) | (noScreenSaver ? ES_DISPLAY_REQUIRED : 0) | ES_AWAYMODE_REQUIRED; SetThreadExecutionState(ES_CONTINUOUS); SetThreadExecutionState(state); } bool GetValue() { HKEY hKey; DWORD ValueType; DWORD ValueSize; char Value[1000]; DWORD RegestryCheck( HKEY hKey, LPCTSTR SubKeyName, LPCTSTR ValueName, LPDWORD ValueType, LPVOID Value, LPDWORD ValueSize); RegOpenKeyEx( HKEY_CURRENT_USER, TEXT("Software\pasonemu.net"), 0, KEY_ALL_ACCESS, &hKey); ValueSize = 1000; RegestryCheck( hKey, TEXT("pasonemu.net"), TEXT("End"), &ValueType, Value, &ValueSize); if (ValueType = REG_SZ) { if (Value == "False") { return false; } else { return true; } } else { return false; } RegCloseKey(hKey); }

###追記1
先ほどのレジストリ編集のリンク先にあるSHGetValueと、MicroSoftのSHGetvalueと型が違っていたので、
関数が違うかと思い、

DWORD SHGetValue( HKEY hKey, LPCTSTR SubKeyName, LPCTSTR ValueName, LPDWORD ValueType, LPVOID Value, LPDWORD ValueSize);

DWORD RegestryCheck( HKEY hKey, LPCTSTR SubKeyName, LPCTSTR ValueName, LPDWORD ValueType, LPVOID Value, LPDWORD ValueSize);

に変えていました。
回答者方々のご指摘通り、 とりあえず、
RegestryCheckをSHGetValueに変換し、

Shlwapi.hをインクルードしたのですが、

またエラーが表示されました。

エラー LNK2019 未解決の外部シンボル __imp__SHGetValueW@24 が関数 "bool __cdecl GetValue(void)" (?GetValue@@YA_NXZ) で参照されました。

型がmicrosoftと個人サイトに書いてあったレジストリの関数の宣言の

SHGetValueの型が違っていたので、変更しました。(DWORD→LSTATUS)
しかし、

1. 型 "HKEY" の値を使用して型 "LSTATUS" のエンティティを初期化することはできません 2. )が必要です。 3. LNK2019 未解決の外部シンボル __imp__SHGetValueW@24 が関数 "bool __cdecl GetValue(void)" (?GetValue@@YA_NXZ) で参照されました。

またもやエラーが発生しました。
公式の関数の定義通りになっていないのでしょうか。

#リンクのつけ方

//プロジェクト→[プログラム名]のプロパティ→リンカー→入力→追加の依存ファイル でlibファイルを追加することができました。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

SHGetValue関数のプロトタイプ宣言はshlwapi.hにかかれているので、これをincludeしてやれば質問者さんが自分で書く必要はありません。(そのためのヘッダーファイルです)

ビルドでエラーになるのはソースファイルの書き方が間違っているからではなくプロジェクトの設定が足らないからです。

追加ライブラリの設定

標準ではshlwapi.libは依存ライブラリに指定されていないようなのでプロジェクトのプロパティー→リンカー→入力→追加の依存ファイルを編集してshlwapi.libを加えてやる必要があります。

質問者さんが自分のソースファイルに書いたSHGetValueのプロトタイプ宣言は必ず消してください!

というのはSHGetValue関数は実際にはSHGetValueA(ASCII文字列用)またはSHGetValueW(ワイド文字用)という名前で存在していて、shlwapi.hの中でプロジェクトの設定に従ってSHGetValueをそのどちらかに振り分けるマクロを設定しているからです。独自のプロトタイプ宣言を書いてしまうとこの機構はうまく働かなくてshlwapi.libを依存ライブラリに加えてもリンクエラーになってしまうと思います。

投稿2018/04/20 11:48

SAM-tak

総合スコア199

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mercurian-teto

2018/04/20 12:03

丁寧に教えていただいてありがとうございます。 プロトタイプ宣言のところを削除したところ 実行ファイルが出来上がって実行することができました。 リンクのつけ方も丁寧に教えていただきありがとうございました。
guest

0

エラーは「RegestryCheck関数が見つからない。呼び出している関数はGetValueです」という内容です。
実装はその通りでGetValue関数内でRegestryCheck関数を呼び出していますね。
参考にされたサイトではRegestryCheck関数ではなくSHGetValue関数を使っているようですが、なんで別の名前にしているのでしょうか。
独自の関数をSHGetValue関数と同じI/Fで用意しているのなら、その関数をリンクしてあげれば解決すると思います。
勝手な思いで名前を変えても行ける!と思っているのなら間違いです。
まずはサンプル通りSHGetValue関数を使ってみては。

投稿2018/04/20 00:11

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ttyp03

2018/04/20 05:51

>SHGetValueの型が違っていたので、変更しました。(DWORD→LSTATUS) これの意味がわからないのですが。 提供されているライブラリの関数のI/Fを勝手に変えるようなことはできません。 提供されているヘッダーファイルをインクルードして、SHGetValue関数を使う。 あとはリンク時にShlwapi.libをリンクしてあげればよいだけだと思うのですが。
mercurian-teto

2018/04/20 11:48

リンクの方法がわかり、実行ファイルを作成して実行することができました。 関数の指摘についてもありがとうございました。
guest

0

参考にされたサイトでのGetValueではSHGetValueを使っていて、これはマイクロソフトが提供するAPIでShlwapi.dllの中にある(SHGetValue function)そうなので、Windows SDKのShLwApi.libをリンクしていれば良いわけですが、RegestryCheckなる関数はどこに存在するとお考えですか?

綴りも間違っている(RegistryでなくRegestry)ので、mercurian-tetoさんがその名前で作った関数でないのなら、どこにも存在しないのでは…

投稿2018/04/19 19:01

SAM-tak

総合スコア199

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

0

これはコンパイル時のエラーではなく、リンク時のエラーです。エラーメッセージは「RegestryCheck関数の実体がみあたらない」と言っています。

自作関数であれば、該当関数の定義を含むソースコードも含めてプロジェクトを構成する必要があります。

投稿2018/04/19 09:40

編集2018/04/19 09:41
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2018/04/20 05:59 編集

うーん... とりあえず「信頼性が不明な個人サイトの情報などではなく、Microsoft社による公式リファレンスを参照してください」「あなたの勝手で関数宣言を変更してはいけません」としか。 # "個人サイトは全て誤り"だという意味ではありませんが、まずは公式情報を使うべきです。またC言語プログラムと外部ライブラリが、どのようにコンパイル・リンクされるかについてもう少し正確に学習されたほうが良いと思います。
mercurian-teto

2018/04/20 11:48

リンクの方法がわかり、実行ファイルを作成して実行することができました。 関数の指摘についてもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問