デスクトップアイコン情報と64bitアプリケーション

※環境はWindows8.1 64bit + Visual Studio 2013 Professional + C/C++

諸事情でデスクトップ上のアイコン情報を取得しなければいけない機会がありました
テキトーにググってみるとLVM_GETITEMTEXTを送信すれば良いらしいので、さーっと組んでみると動かない…

LVM_GETITEMTEXT message (Windows)

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <windows.h>
#include <CommCtrl.h>

int main()
{
	HWND hWnd = FindWindow("Progman", "Program Manager");
	hWnd = FindWindowEx(hWnd, NULL, "SHELLDLL_DefView", NULL);
	hWnd = FindWindowEx(hWnd, NULL, "SysListView32", NULL);

	int iconCount = SendMessage(hWnd, LVM_GETITEMCOUNT, NULL, NULL);

	LVITEM lvi, *_lvi;
	char item[512];
	char *_item;
	unsigned long pid;
	HANDLE process;

	GetWindowThreadProcessId(hWnd, &pid);
	process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, pid);

	_lvi = (LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
	_item = (char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE);

	lvi.cchTextMax = 512;

	for (int i = 0; i<iconCount; i++)
	{
		lvi.iSubItem = 0;
		lvi.pszText = _item;
		WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
		SendMessage(hWnd, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);

		ReadProcessMemory(process, _item, item, 512, NULL);

		printf("[%d]    ->    %s\n", i, item);
	}

	VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
	VirtualFreeEx(process, _item, 0, MEM_RELEASE);

	return 0;
}

なんでだろうなーって思いながら32bitのWindows7で動かしてみると普通に動く…

8.1が問題なのか、64bitなのが問題なのか分からなかったので、取り敢えずVSの設定を変更して64bitアプリケーションとしてビルドすると動きました


Visual Studioで64bitアプリケーションをビルドするにはプロジェクトのプロパティを変更する必要があります

プロジェクトのプロパティから構成プロパティ→構成マネージャー→プラットフォーム→新規作成→新しいプラットフォームをx64に変更

f:id:kkrnt:20141212110035p:plain
f:id:kkrnt:20141212110044p:plain
f:id:kkrnt:20141212110051p:plain

これで64bitアプリケーションとしてビルドされます

よくよく調べてみると、色々気を付けなければいけないようです


ListView to CSVを作ってみよう番外編〜x64を考慮した場合 - ListView to CSVのヘルプ