純規の暇人趣味ブログ

首を突っ込んで足を洗う

[VC++]exeに内包したリソースを読み込む

      HimaJyun

もはや驚く事でもなかろうかと思われますが、exe(PE)ファイルにはデータを内包する事が可能です。

基本的には、リソースとして埋め込むか、データとして引っ付けるかのどちらかです。

今回は埋め込む方のデータ内包、取り出しをご紹介しようと思います。

データ on exe

exeにデータが埋め込まれているシーン、普通に見掛けるかと思います。

そうです、アイコンなどがそれです。

この様に、exeに何かが内包されているのは特段珍しい現象でもありません、覚えておくとどこかで役に立つかもです。

環境

とりあえず今回は以下の環境を前提として説明します。

  • C++
  • VisualStudio 2015 Community

VisualStudioはExpress版だとリソースエディタが使えないので要注意、ライセンス的に問題がないならCommunity版を使う(か、Pro版を買う)事を推奨。

実際にやってみる

今回は文字列を読み込んでMessageBoxに表示させる事を目的としてやってみようと思います。

とりあえず新規プロジェクトを作成しました、main.cppの中身は空です。
exe-embedded-resource-001

埋め込む

埋め込む際はコードなど殆ど気にせずに出来ます。

まずは、VisualStudioから「リソースファイル」のフォルダ(フィルタ)を右クリック->追加->リソースと進みましょう。
exe-embedded-resource-002

resource.h、(プロジェクト名).rcファイルが作成されると同時に、追加したいリソースの種類を選ぶように促されます。
exe-embedded-resource-003

今回はただの文字列なので「String Table」を選択しました。

以下の画像の通り、キャプションの所に文字列を書き込んでみました。
exe-embedded-resource-004

メニューにあった通り、画像やアイコンを入れる事も出来ます。(「インポート」からそれ以外の種類のバイナリを無理やり入れる事も可能ではありますが、あんまり良い方法ではないかと……)

読み込む

入れるのは簡単、じゃあ出すのは?

こっちも簡単、リソースの種類に合わせて以下の様な関数が用意されています。(以下は良く使うであろうと言う妄想からの例、実際はあと何種類かある)

今回はString Tableでしたので、「LoadString」を使用します。

ちょっと雑ですが、具体的には以下の様な感じ。

#include <Windows.h>
#include "resource.h"

int WINAPI WinMain(_In_ HINSTANCE hInstance
				   , _In_opt_ HINSTANCE hPrevInstance
				   , _In_ LPSTR lpCmdLine
				   , _In_ int nCmdShow) {
	TCHAR str1[64];
	TCHAR str2[64];

	// std:stringで(文字列(配列)サイズを指定せずに)読み込む方法求
	LoadString(hInstance, IDS_STRING101, str1, sizeof(str1));
	LoadString(hInstance, IDS_STRING102, str2, sizeof(str2));

	MessageBox(NULL, str1, str2, MB_OK);
	return S_OK;
}

これを実行すると、以下の様に表示されます。
exe-embedded-resource-005

先ほど追加したリソースが読み込まれて表示されている事が分かるかと思います。

LoadStringで指定している「IDS_STRING101」は「resource.h」に書かれてありますので、自分が希望しているリソースファイルの番号と一致するものを使用しましょう。

今回は確認しやすい文字列で試したのでリソースファイルに入れる旨味は薄いですが、主にアイコン画像をLoadIconする事が多いかと思われます。

ちなみに

……書いてみたら予想以上に中身が薄い

ので、もう少し何か書きましょうか……

この方法、当然ながらアイコンとかの小さな部品を入れる事が目的です。(だと思います)

ただ単にexe内にデータを押し込んだと言うだけで、圧縮や暗号化などは施されないので、例えば7-Zipとかを使ってexeの中身が覗けさえすれば、入れてあるリソースファイルを取り出す事は容易です。(そして、置き換える事も可能です。)

そのため、例えば、「ゲームを作るから」と言ってここにキャラ設定やステータス値を押し込んだりしてしまうと、意図せず、裏キャラなどの存在がバレてしまう。(ちなみに、同じ方法でリソースを埋め込んでいるのかは分からないが、東方紅魔郷をテキストエディタとかで開くと没キャラ(?)の「冴月 麟」なる者の存在が確認できる。)
exe-embedded-resource-006

そう言う意味で、あえて裏キャラや裏ストーリーの出し方を仕込むと言うのも面白いかも知れない、それに気付いてもらえるかどうかは別として(「○○面で××を行うと???」みたいなテキストをぶち込んでおくとか)

また、入れれば入れた分だけexeファイルの大きさがデカくなるのは当然の事です、更新の配布などが手間になるだけなので、必要な物だけを入れるようにしましょう。

 - プログラミング