【VC++】デスクトップの情報を HTML に書き出す



ブラウザでダウンロード
【Windows Shell プログラミング】
VBScript バージョンとほぼ同じ情報を取得します
※ 属性は面倒なので処理しませんでしたが、info tip の取得方法は解りませんでした

とにかく、Shell を C++ で処理すると面倒でやってられないです。
ですが、デスクトップに関してだけ言えばメリットがあるので整理しました。

通常、COM 経由で使用すると簡単なので Framework では 
COM をインポートして利用します。
( C++ からも、COM でアクセスしたほうが簡単かもしれません。)
// *********************************************************
// 【Windows Shell プログラミング】
// デスクトップの情報を HTML に書き出す
//
// ※ このアプリそのままでは役に立たないので、
// ※ サンプルとしてファイル名は desktop_info.htm で固定
// *********************************************************

#define _WIN32_WINNT 0x0500
#include <tchar.h>
#include "lightbox\lightbox.h"

#pragma comment( lib, "lightbox\\lightbox.lib" )
#pragma comment( lib, "shlwapi.lib" )
#pragma comment( lib, "wininet.lib" )


// *********************************************************
// Windows アプリケーションとしてのエントリポイント
// Link.exe で /SUBSYSTEM:WINDOWS がデフォルトで
// 指定される事になります
// *********************************************************
int APIENTRY _tWinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine,
	int nCmdShow
)
{

	_bstr_t Html;
	// *********************************************************
	// HTML ヘッダ部分
	// 
	// ↓JavaScript で取得したもの
	// http://winofsql.jp/php/cnvtext/frame.htm
	// *********************************************************
	Html="";
	Html+="<HTML><HEAD><TITLE>ProcessList</TITLE> \n";
	Html+="<META http-equiv=\"Content-Type\" content=\"text/html; charset=shift_jis\"> \n";
	Html+="<STYLE type=\"text/css\">* { font-size:12px;}</STYLE> \n";
	Html+="</HEAD><BODY> \n";
	Html+="<TABLE> \n";
	Html+="<TR> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap></TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>名称</TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>サイズ</TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>タイプ</TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>更新日</TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>属性</TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>パス</TH> \n";
	Html+="<TH style='background-color:gray;color:white' nowrap>8.3ファイル名</TH> \n";
	Html+="</TR> \n";

	// *********************************************************
	// Shell 関係の変数
	// *********************************************************
	HRESULT			hr;
	LPSHELLFOLDER	pDesktop;
	LPITEMIDLIST	pidlItem;
	LPENUMIDLIST	pEnum;
	DWORD			dwRetrieved;
	STRRET			str;	// STRRET 構造体
	char			szName[MAX_PATH];
 
	_bstr_t			Target("");
	_bstr_t			strCss("");
 
	// *********************************************************
	// デスクトップフォルダの取得
	// *********************************************************
	hr = SHGetDesktopFolder( &pDesktop );
	if( FAILED( hr ) ) {
		return 0;
	}

	// *********************************************************
	// 一覧の取得
	// *********************************************************
	hr = pDesktop->EnumObjects(
				NULL,
				SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
				&pEnum
			);
	if( FAILED( hr ) ) {
		pDesktop->Release();
		return 0;
	}

	// *********************************************************
	// ループ準備
	// *********************************************************
	int cnt;
	FILE *fp;
	fp = fopen( "desktop_info.htm", "wt" );
	fprintf( fp, "%s\n", (LPTSTR)Html );

	// *********************************************************
	// 一覧ループ
	// *********************************************************
	cnt = 1;
	while( 1 ) {

		strCss = "";
		if ( cnt % 2 == 1 ) {
			strCss = "style='background-color:#D0D0D0;'";
		}

		// *********************************************************
		// アイテム の取得
		// *********************************************************
		hr = pEnum->Next( 1, &pidlItem, &dwRetrieved );
		if( FAILED( hr ) ) {
			break;
		}
		if ( dwRetrieved == 0 ) {
			break;
		}
 
		fprintf( fp, "%s\n", "<TR>" );
		fprintf( fp, "<TD nowrap %s >%d</TD>\n", (LPTSTR)strCss, cnt );

		// *********************************************************
		// アイテムの名称を取得
		// *********************************************************
		hr = pDesktop->GetDisplayNameOf( pidlItem, SHGDN_NORMAL, &str );
		if( FAILED( hr ) ) {
			continue;
		}
		// Unicode
		if ( str.uType == STRRET_WSTR ) {
			Target = str.pOleStr;
			lstrcpy( szName, (LPTSTR)Target );
		}
		// ASCII
		if ( str.uType == STRRET_CSTR ) {
			lstrcpy( szName, str.cStr );
		}
		// たぶん無いので無視
		if ( str.uType == STRRET_OFFSET ) {
			fprintf( fp, "<td>skip</td>\n" );
			fprintf( fp, "%s\n", "</TR>" );
			continue;
		}
		fprintf( fp, "<TD nowrap %s >%s</TD>\n", (LPTSTR)strCss, szName );


		HRESULT hFile;
		// *********************************************************
		// アイテムのファイルシステム情報
		// *********************************************************
		WIN32_FIND_DATA wfd;
		hFile = SHGetDataFromIDList( 
				pDesktop,
				pidlItem,
				SHGDFIL_FINDDATA,
				&wfd,
				sizeof( WIN32_FIND_DATA )
		);
		if ( hFile != NOERROR ) {
			// ファイルシステムでは無いアイテム
			fprintf( fp, "<TD nowrap %s >&nbsp;</TD>\n", (LPTSTR)strCss );
		}
		else {
			// デスクトップなので、サイズは nFileSizeLow のみを使用
			fprintf( fp, "<TD nowrap %s >%d</TD>\n", (LPTSTR)strCss, wfd.nFileSizeLow );
		}

		// *********************************************************
		// アイテムの タイプ名
		// *********************************************************
		SHFILEINFO sfi;
		SHGetFileInfo(
			(LPCSTR)pidlItem,
			0,
			&sfi,
			sizeof( SHFILEINFO ),
			SHGFI_PIDL | SHGFI_TYPENAME
		);
		fprintf( fp, "<TD nowrap %s >%s</TD>\n", (LPTSTR)strCss, sfi.szTypeName );


		// *********************************************************
		// アイテムの タイムスタンプ
		// *********************************************************
		if ( hFile != NOERROR ) {
			// ファイルシステムでは無いアイテム
			fprintf( fp, "<TD nowrap %s >&nbsp;</TD>\n", (LPTSTR)strCss );
		}
		else {
			FILETIME ft;
			SYSTEMTIME st;
			FileTimeToLocalFileTime( &(wfd.ftLastWriteTime), &ft );
			FileTimeToSystemTime( &ft, &st );
			fprintf( fp,
				"<TD nowrap %s >%02d-%02d-%02d %02d:%02d:%02d</TD>\n",
				(LPTSTR)strCss,
				st.wYear,
				st.wMonth,
				st.wDay,
				st.wHour,
				st.wMinute,
				st.wSecond
			);
		}

		// *********************************************************
		// 属性は面倒なので省略
		// *********************************************************
		fprintf( fp, "<TD nowrap %s >&nbsp;</TD>\n", (LPTSTR)strCss );

		// *********************************************************
		// アイテムのパスを取得
		// *********************************************************
		hr = pDesktop->GetDisplayNameOf( pidlItem, SHGDN_FORPARSING, &str );
		if( FAILED( hr ) ) {
			continue;
		}
		// Unicode
		if ( str.uType == STRRET_WSTR ) {
			Target = str.pOleStr;
			lstrcpy( szName, (LPTSTR)Target );
		}
		// ASCII
		if ( str.uType == STRRET_CSTR ) {
			lstrcpy( szName, str.cStr );
		}
		// たぶん無いので無視
		if ( str.uType == STRRET_OFFSET ) {
			fprintf( fp, "<td>skip</td>\n" );
			fprintf( fp, "%s\n", "</TR>" );
			continue;
		}
		fprintf( fp, "<TD nowrap %s >%s</TD>\n", (LPTSTR)strCss, szName );

		// *********************************************************
		// infoTip は解らないので、短いファイル名
		// *********************************************************
		if ( hFile != NOERROR ) {
			// ファイルシステムでは無いアイテム
			fprintf( fp, "<TD nowrap %s >&nbsp;</TD>\n", (LPTSTR)strCss );
		}
		else {
			fprintf( fp, "<TD nowrap %s >%s</TD>\n",
				(LPTSTR)strCss, wfd.cAlternateFileName );
		}


		fprintf( fp, "%s\n", "</TR>" );

		cnt++;
 
	}

	fprintf( fp, "%s\n", "</TABLE></BODY></HTML>" );

	fclose( fp );


	// 取得したものは解放
	pEnum->Release();
	pDesktop->Release();

	LboxTool Tool;

	Tool.Execute(
		"RunDLL32.EXE shell32.dll,ShellExec_RunDLL desktop_info.htm",
		NULL
	);

	return 0;
}



/*
↓For EnumObject
typedef enum tagSHCONTF {
    SHCONTF_FOLDERS,
    SHCONTF_NONFOLDERS,
    SHCONTF_INCLUDEHIDDEN,
    SHCONTF_INIT_ON_FIRST_NEXT,
    SHCONTF_NETPRINTERSRCH,
    SHCONTF_SHAREABLE,
    SHCONTF_STORAGE,
    SHCONTF_FASTITEMS,
    SHCONTF_FLATLIST,
    SHCONTF_ENABLE_ASYNC
} SHCONT;

↓For GetDisplayNameOf
typedef enum tagSHGDN {
    SHGDN_NORMAL,
    SHGDN_INFOLDER,
    SHGDN_FOREDITING,
    SHGDN_FORADDRESSBAR,
    SHGDN_FORPARSING
} SHGNO;


*/