概要

サーバーの交換やドライブ構成が変わった場合のショートカットの変更は面倒です。特に大量のパソコンがサーバーに接続されていると面倒です。
本プログラムは、定されたフォルダーに含まれる複数のショートカットのリンク先を変換します。変換パターンは2種類設定できます。
下図は、E:\tempに含まれるショートカットのリンク先がC:\であるものをD:\に変換する例です。

テスト環境

コンパイラ

Visual C++ 2008/2013 Express 32/64bit UNICODE

実行環境

Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)
Windows 7 Enterprise Service Pack 1 64bit

プログラムソースの概要

shortcutchg.cpp

WinMain

 CoInitialize APIによりCOMを初期化します。
 ショートカットリンク先の変換ルールの初期設定をshortcutchg.iniから読み取るためにGetModuleFileName APIにより本プログラムのパスを取得します。
PathFindFileName APIによりファイル名を取り出し、フォルダー名のみを有効にします。
ダイアログボックスを呼び出します。
 CoUninitialize APIによりCOMを解放します。

DlgProc

WM_INITDIALOG
各コントロールのウィンドウハンドルを取得します。
shortcutchg.iniファイルより、初期ルールを呼び出します。
GetDesktopPath関数によりディスクトップのフォルダーを取得し、初期値とします。
WM_COMMAND
IDC_REF_BUTTON
参照ボタンをクリックすると呼び出されます。
GetDir関数によりフォルダ選択のコモンダイアログを表示し、フォルダ名を取得し、エディットボックスに設定します。
IDC_CHG_BUTTON
変換ボタンをクリックすると呼び出されます。
ショートカットを扱うための準備のため、IShellLink,IPersistFileの初期化を行う必要があります。
ここではshort_cut_initという関数を作成して呼び出しています。
エディットボックスからフォルダー名を取得します。
LVM_DELETEALLITEMSメッセージによりリストビューを初期化します。
変換ルールを読み込み配列にセットします。
get_dir_list関数により指定されたフォルダーにふくまれるショートカット(*.lnk)ファイルを検索し、リンク先の読み込み及び変更を行います。
ショートカットで使用したオブジェクトをshort_cut_exit関数で開放します。
IDCANCEL
キャンセルボタンをクリックした場合に呼び出されます。
EndDialog APIによりダイアロブボックスを終了させます。
short_cut_init
CoCreateInstance関数によりIShellLinkオブジェクトを作成します。 QueryInterface関数によりIPersistFileインターフェースの作成します。 複数のショートカットを扱う場合でも同時に1個しか扱わない場合は準備は1回で結構です。(STAでCOMを初期化しているのでスレッド単位で必要)
short_cut_exit
CoCreateInstance関数によりIShellLinkオブジェクトを作成します。 QueryInterface関数によりIPersistFileインターフェースの作成します。  複数のショートカットを扱う場合でも同時に1個しか扱わない場合は準備は1回で結構です。(STAでCOMを初期化しているのでスレッド単位で必要)
chg
get_dir_list関数から呼び出されます。
IPersistFileのメンバであるLoadにショートカットのファイル名を指定して呼び出すとショートカットが呼び出されます。
IShellLinkのメンバであるGetPathを呼び出すとリンク先が取得できます。
変換ルールをチェックして該当する場合、リンク先の文字列を変更します。
IPersistFileのメンバであるSaveでショートカットのファイル名を指定することによりショートカットが作成されます。
ListViewHeader
リストビューのヘッダーを初期化します。
get_dir_list
指定されたフォルダーからショートカットを検索し、見つかったショートカットに対してchg関数を呼び出します。
フォルダーが見つかった場合は、自分自身を呼び出してサブフォルダーを検索します。
GetDir
SHBrowseForFolderによりフォルダー名を取得するプログラム(32/64bit)を参照してください。
trim
_fgettsで取得された文字列から改行や復帰コードを除去します。
GetDesktopPath
ディスクトップのフォルダーを取得します。
第2引数を指定すると、マイドキュメントやお気に入り、スタートメニューを取得できます。

ソースコード

shortcutchg.cpp

//	指定されたフォルダーの複数のショートカットからリンク先を取得して表示後、変更する。
//	本プログラムと同じフォルダーにshortcutchg.iniファイルがある場合は、初期フォルダーと初期ルールを読み込む
//	Visual C++ 2008/2013 Express (UNICODE 32/64bit)

#include <windows.h>
#include <shobjidl.h>
#include <shlguid.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <stdio.h>
#include <tchar.h>
#include <commctrl.h>
#include "resource.h"

#pragma comment(lib,"shlwapi.lib")

int list_item_max=0;	//	検索されたショートカット数
int chg_short_cut=0;	//	変更されたショートカット数

IShellLink		*m_pShellLink=NULL;	
IPersistFile	*m_pPersistFile=NULL;

#define REPLACE_MAX 2	//	変換ルール個数

TCHAR src_str[REPLACE_MAX][MAX_PATH];	//	検索文字列
TCHAR dtc_str[REPLACE_MAX][MAX_PATH];	//	置換文字列

TCHAR exe_pass[MAX_PATH];	//	実行ファイルのパス
TCHAR* exe_name=0;	//	実行ファイルの名前

//	ダイアログボックスプロシージャー
LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

// ショートカット関連のオブジェクト等の初期化
bool short_cut_init(IShellLink** m_pShellLink,IPersistFile** m_pPersistFile);

// ショートカット関連のオブジェクト等の解放
void short_cut_exit(IShellLink* m_pShellLink,IPersistFile* m_pPersistFile);

//	ファイル名よりショートカットの取得及び変更
TCHAR* chg(TCHAR* file_pass,TCHAR* pass,int sz,TCHAR* chg,int chg_sz);

//	リストビューヘッダーの初期化
void ListViewHeader(HWND hList);

//	フォルダーに含まれるショートカットをサブフォルダーも含めて検索する
int get_dir_list(HWND hList,HWND hStatus,TCHAR* pass,TCHAR* card);

//	ディレクトリ名を取得するダイアログを表示する
bool GetDir(HWND hWnd, TCHAR* def_dir,TCHAR* path);

//	特殊フォルダーを取得
void GetDesktopPath(TCHAR* path,int csidl=CSIDL_DESKTOPDIRECTORY);

//	不要な改行を削除
void trim(TCHAR* str);

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,LPSTR lpsCmdLine, int nCmdShow){

	if( FAILED( CoInitialize(NULL) )){	//	COMの初期化 STA(シングルスレッドアパートメント)
		MessageBox(0,_TEXT("COMの初期化に失敗しました"),_TEXT("エラー"),MB_OK);
		return -1;
	}

	GetModuleFileName(NULL,::exe_pass, sizeof(::exe_pass)/sizeof(TCHAR));	//	本プログラムのパスを取得
	::exe_name=PathFindFileName(::exe_pass);	//	ファイル名の位置を取得
	*(::exe_name)=_T('\0');
//	ダイアログボックスの表示
	DialogBox(hCurInst, TEXT("DLG1"), 0, (DLGPROC)DlgProc);

	CoUninitialize();	//	COMの解放
	return (int)0;
}


//	ダイアログボックスプロシージャー

LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
	static HWND hEdit_dir;
	static HWND hList;
	static HWND hStatus;

	static TCHAR dir[MAX_PATH*40];		//	選択されたフォルダー名
	static TCHAR def_dir[MAX_PATH];	//	初期フォルダー

	static HCURSOR wait_icon=0;
	static HCURSOR org_icon=0;

	switch (msg) {
		case WM_INITDIALOG:{
			wait_icon=LoadCursor(NULL,IDC_WAIT);	//	処理中アイコンの取得
			hEdit_dir=GetDlgItem(hDlg,IDC_DIR_EDIT);
			hList=GetDlgItem(hDlg,IDC_LISTVIEW);
			hStatus=GetDlgItem(hDlg,IDC_STATUS_LABEL);
			ListViewHeader(hList);
			TCHAR fname[MAX_PATH];
			TCHAR buf[MAX_PATH];
			_stprintf_s(fname,sizeof(fname)/sizeof(TCHAR),_TEXT("%sshortcutchg.ini"),::exe_pass);
			FILE* fp;
			if( _tfopen_s(&fp,fname,_TEXT("r"))==0 ){	//	設定ファイルを読み込む
				if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
					trim(buf);
					SetWindowText(GetDlgItem(hDlg,IDC_SRC_EDIT1) , buf);
					if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
						trim(buf);
						SetWindowText(GetDlgItem(hDlg,IDC_DTC_EDIT1) , buf);
						if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
							trim(buf);
							SetWindowText(GetDlgItem(hDlg,IDC_SRC_EDIT1+1) , buf);
							if(_fgetts(buf,sizeof(buf)/sizeof(TCHAR),fp)){
								trim(buf);
								SetWindowText(GetDlgItem(hDlg,IDC_DTC_EDIT1+1) , buf);
							}
						}
					}
				}
				fclose(fp);
			}
			TCHAR desktop[MAX_PATH];
			GetDesktopPath(desktop);
			SetWindowText(hEdit_dir,desktop);	//	エディットボックスの中身をディスクトップにする

			return TRUE;
		}
		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDC_REF_BUTTON:	//	参照ボタンをクリックした場合
					_tcscpy_s(def_dir,sizeof(def_dir)/sizeof(TCHAR),_TEXT("C:\\"));
					if(GetDir(hDlg,def_dir,dir)==TRUE){
						SetWindowText(hEdit_dir,dir);
					}
					break;
				case IDC_CHG_BUTTON:{	//	変換ボタンをクリックした場合
					SetCursor(wait_icon);
					if(short_cut_init(&m_pShellLink,&m_pPersistFile)==false){
						MessageBox(0,_TEXT("com error"),_TEXT("エラー"),MB_OK);
						EndDialog(hDlg,TRUE);
					}
					GetWindowText(hEdit_dir,dir,sizeof(dir)/sizeof(TCHAR));
					SendMessage(hList,LVM_DELETEALLITEMS,0,0); // リストビュー全アイテム消去
//	変換ルールの読み込み
					for(int n=0;n<REPLACE_MAX;n++){
						HWND hSrc=GetDlgItem(hDlg,IDC_SRC_EDIT1+n);
						HWND hDtc=GetDlgItem(hDlg,IDC_DTC_EDIT1+n);
						GetWindowText(hSrc,::src_str[n],MAX_PATH);
						GetWindowText(hDtc,::dtc_str[n],MAX_PATH);
					}
					::src_str[REPLACE_MAX][0]=0;
					::dtc_str[REPLACE_MAX][0]=0;
					::list_item_max=0;	//	ショートカット数のリセット
					::chg_short_cut=0;	//	変更されたショートカット数のリセット
//	ショートカットの検索・表示・変更
					get_dir_list(hList,hStatus,dir,_TEXT("*.lnk"));

					short_cut_exit(m_pShellLink,m_pPersistFile);

					TCHAR buf[MAX_PATH+256];
					_stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("結果: ショートカット %d個,変換ショートカット %d個"),::list_item_max,::chg_short_cut);
					SetWindowText(hStatus,buf);

					SetCursor(org_icon);
					break;
				}
				case IDCANCEL:	//	キャンセルボタンをクリックした場合
					EndDialog(hDlg,TRUE);
					return TRUE;
				default:
					return FALSE;
			}
			default:
				return FALSE;
	}
	return TRUE;
}


// ショートカット関連のオブジェクト等の初期化

bool short_cut_init(IShellLink** m_pShellLink,IPersistFile** m_pPersistFile){
	if(CoCreateInstance( CLSID_ShellLink , NULL , CLSCTX_INPROC_SERVER ,IID_IShellLink ,(LPVOID *)m_pShellLink)==S_OK){
		if((*m_pShellLink)->QueryInterface( IID_IPersistFile, (LPVOID *)m_pPersistFile )==S_OK){
			return true;
		}
		(*m_pShellLink)->Release();
		*m_pShellLink=0;
		*m_pPersistFile=0;
		return false;
	}
	*m_pShellLink=0;
	*m_pPersistFile=0;
	return false;
}

// ショートカット関連のオブジェクト等の解放

void short_cut_exit(IShellLink* m_pShellLink,IPersistFile* m_pPersistFile){
	m_pPersistFile->Release();
	m_pShellLink->Release();
}

//	ファイル名よりショートカットの取得及び変更

TCHAR* chg(TCHAR* file_pass,TCHAR* pass,int sz,TCHAR* chg,int chg_sz){
	if(m_pPersistFile->Load( file_pass, STGM_READ | STGM_SHARE_DENY_WRITE)==S_OK){
		m_pShellLink->GetPath(pass,sz,NULL,SLGP_UNCPRIORITY);	// UNCパス名を取得
		chg[0]=_T('\0');
		for(int n=0;n<REPLACE_MAX;n++){
			TCHAR* find=::src_str[n];
			TCHAR* replace=::dtc_str[n];
			int len=(int)_tcslen(find);
			if(len==0)
				break;
			if(_tcsncmp(pass,find,len)==0){
				_tcscpy_s(chg,chg_sz,replace);
				_tcscat_s(chg,chg_sz,pass+len);
				m_pShellLink->SetPath(chg);	//	リンク先の設定
				m_pPersistFile->Save(file_pass,TRUE);	//	ショートカットを保存する
				::chg_short_cut++;	//	変更されたショートカット数のカウントアップ
				break;
			}
		}
	}
	return pass;
}

//	リストビューヘッダーの初期化

void ListViewHeader(HWND hList){
	LV_COLUMN lvcol;
	lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	lvcol.fmt = LVCFMT_LEFT;
	lvcol.cx = 192;
	lvcol.pszText = _TEXT("ショートカット名");
	lvcol.iSubItem = 0;
	ListView_InsertColumn(hList, 0, &lvcol);

	lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM ;
	lvcol.fmt =  LVCFMT_LEFT;
	lvcol.cx = 192;
	lvcol.pszText = _TEXT("フルパス");
	lvcol.iSubItem = 1;
	ListView_InsertColumn(hList, 1, &lvcol);

	lvcol.cx = 192;
	lvcol.pszText = _TEXT("リンク先変換前");
	lvcol.iSubItem = 2;
	ListView_InsertColumn(hList, 2, &lvcol);

	lvcol.cx = 192;
	lvcol.pszText = _TEXT("リンク先変換後");
	lvcol.iSubItem = 3;
	ListView_InsertColumn(hList, 3, &lvcol);
}

//	フォルダーに含まれるショートカットをサブフォルダーも含めて検索する

int get_dir_list(HWND hList,HWND hStatus,TCHAR* pass,TCHAR* card){
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind;
	TCHAR find_pass[MAX_PATH];
	TCHAR find_top_pass[MAX_PATH];
	TCHAR sub_pass[MAX_PATH];
	TCHAR make_pass[MAX_PATH];
	static TCHAR buf[MAX_PATH+256];

	_stprintf_s(buf,sizeof(buf)/sizeof(TCHAR),_TEXT("検索中:%s"),pass);
	SetWindowText(hStatus,buf);

	int num=0;	//	見つかったファイル数
	int l=(int)_tcslen(pass);
	int c=pass[l-1];	//	パスの最後の文字
	_tcscpy_s(find_top_pass,sizeof(find_top_pass)/sizeof(TCHAR),pass);
	if(c!=_T('\\') && c!=_T(':')){
		find_top_pass[l]=_T('\\');
		find_top_pass[l+1]=_T('\0');
	}

	_stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s*.*"),find_top_pass);	//	サブディレクトリの検索
	hFind = FindFirstFile(find_pass, &FindFileData);
	if(hFind != INVALID_HANDLE_VALUE){
		do{
			if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)==0 && (FindFileData.dwFileAttributes &FILE_ATTRIBUTE_READONLY )==0 )
				if(_tcscmp(FindFileData.cFileName,_TEXT("..")) && _tcscmp(FindFileData.cFileName,_TEXT(".")) ){	//	親ディレクトリは無視する
					_stprintf_s(sub_pass,sizeof(sub_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,FindFileData.cFileName);				
					num+=get_dir_list(hList,hStatus,sub_pass,card);	//	サブディレクトリの中を検索
				}
		}while( FindNextFile(hFind,&FindFileData) );
	}
	FindClose(hFind);
	int pass_len=(int)_tcslen(find_top_pass)+1;
	_stprintf_s(find_pass,sizeof(find_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,card);	//	ファイルの検索
	hFind = FindFirstFile(find_pass, &FindFileData);
	if(hFind != INVALID_HANDLE_VALUE){
		do {
			if( (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0  && (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)==0 && (FindFileData.dwFileAttributes &FILE_ATTRIBUTE_READONLY )==0){
				++num;
				_stprintf_s(make_pass,sizeof(make_pass)/sizeof(TCHAR),_TEXT("%s%s"),find_top_pass,FindFileData.cFileName);

				TCHAR full[MAX_PATH];
				TCHAR* file;
				GetFullPathName(make_pass,sizeof(full)/sizeof(TCHAR),full,&file);

				LV_ITEM item;
				item.mask = LVIF_TEXT  | LVIF_PARAM;
				item.pszText =file;
				item.iItem = ::list_item_max;
				item.iSubItem = 0;
				item.lParam = ::list_item_max;
				ListView_InsertItem(hList, &item);

				item.mask = LVIF_TEXT;
				item.pszText =full;
				item.iItem = ::list_item_max;
				item.iSubItem = 1;
				ListView_SetItem(hList, &item);

				TCHAR src_pass[MAX_PATH];
				TCHAR dtc_pass[MAX_PATH];
				chg(full,src_pass,sizeof(src_pass)/sizeof(TCHAR),dtc_pass,sizeof(dtc_pass)/sizeof(TCHAR));
				
				item.mask = LVIF_TEXT;
				item.pszText =src_pass;
				item.iItem = ::list_item_max;
				item.iSubItem = 2;
				ListView_SetItem(hList, &item);

				item.mask = LVIF_TEXT;
				item.pszText =dtc_pass;
				item.iItem = ::list_item_max;
				item.iSubItem = 3;
				ListView_SetItem(hList, &item);

				::list_item_max++;

			}
		}while( FindNextFile(hFind,&FindFileData) );
		return num;
	}else
		return num;
}


//	ディレクトリ名を取得するダイアログを表示する
//	GetDir(親ウィンドウのハンドル,初期時選択フォルダー,選択されたフォルダー名);
//	trueが返された場合有効なフォルダー名が取得できた場合

int __stdcall BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);


bool GetDir(HWND hWnd, TCHAR* def_dir,TCHAR* path){
	BROWSEINFO bInfo;
	LPITEMIDLIST pIDList;

	memset(&bInfo,0,sizeof(bInfo));
	bInfo.hwndOwner = hWnd; // ダイアログの親ウインドウのハンドル 
	bInfo.pidlRoot = NULL; // ルートフォルダをデスクトップフォルダとする 
	bInfo.pszDisplayName = path; //フォルダ名を受け取るバッファへのポインタ 
	bInfo.lpszTitle = TEXT("フォルダの選択"); // ツリービューの上部に表示される文字列 
	bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_VALIDATE | BIF_NEWDIALOGSTYLE; // 表示されるフォルダの種類を示すフラグ 
	bInfo.lpfn = BrowseCallbackProc; // BrowseCallbackProc関数のポインタ 
	bInfo.lParam = (LPARAM)def_dir;
	pIDList = SHBrowseForFolder(&bInfo);
	if (pIDList == NULL){
		path[0] = _TEXT('\0');
		return false; //何も選択されなかった場合 
	}
	else{
		if (!SHGetPathFromIDList(pIDList, path))
			return false;//変換に失敗 
		CoTaskMemFree(pIDList);// pIDListのメモリを開放 
		return true;
	}
}
//	上記ダイアログのコールバック関数

int __stdcall BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData){
	TCHAR dir[MAX_PATH];
	ITEMIDLIST *lpid;
	HWND hEdit;

	switch (uMsg){
	case BFFM_INITIALIZED:	//	ダイアログボックス初期化時
		SendMessage(hWnd, BFFM_SETSELECTION, (WPARAM)TRUE, lpData);	//	コモンダイアログの初期ディレクトリ
		break;
	case BFFM_VALIDATEFAILED:	//	無効なフォルダー名が入力された
		MessageBox(hWnd,(TCHAR*)lParam,_TEXT("無効なフォルダー名が入力されました"),MB_OK);
		hEdit=FindWindowEx(hWnd,NULL,_TEXT("EDIT"),NULL);	//	エディットボックスのハンドルを取得する
		SetWindowText(hEdit,_TEXT(""));
		return 1;	//	ダイアログボックスを閉じない
		break;
	case BFFM_IUNKNOWN:
		break;
	case BFFM_SELCHANGED:	//	選択フォルダーが変化した場合
		lpid=(ITEMIDLIST *)lParam;
		SHGetPathFromIDList(lpid,dir);
		hEdit=FindWindowEx(hWnd,NULL,_TEXT("EDIT"),NULL);	//	エディットボックスのハンドルを取得する
		SetWindowText(hEdit,dir);
		break;
	}
	return 0;
}

//	不要な改行を削除

void trim(TCHAR* str){
	TCHAR* p=str;
	while(*p){
		switch(*p){
			case _T('\n'):
			case _T('\r'):
				*p=_T('\0');
				return;
		}
		++p;
	}
}

//	特殊フォルダーを取得
//	csidl=CSIDL_DESKTOPDIRECTORY	ディスクトップ
//	csidl=CSIDL_PERSONAL	マイドキュメント
//	csidl=CSIDL_FAVORITES	お気に入り
//	csidl=CSIDL_STARTMENU	スタートメニュー

void GetDesktopPath(TCHAR* path,int csidl){
	LPITEMIDLIST pidl;
	HWND hWnd = NULL;
	IMalloc *pMalloc;
	SHGetMalloc( &pMalloc );
	if( SUCCEEDED(SHGetSpecialFolderLocation(hWnd,csidl,&pidl)) ){
		// パスに変換する
		SHGetPathFromIDList(pidl,path);
		// 取得したIDLを解放する (CoTaskMemFreeでも可)
		pMalloc->Free(pidl);
	}
	pMalloc->Release();
	return;
}

resource.h

#define	IDC_DIR_EDIT		100
#define	IDC_REF_BUTTON		110
#define	IDC_SRC_EDIT1		120
#define	IDC_DTC_EDIT1		130
#define	IDC_LISTVIEW		140
#define	IDC_CHG_BUTTON		150
#define	IDC_STATUS_LABEL	160

#define APL_NAME "ショートカットリンク先一括変換"
#define APL_NAME0 "ショートカットリンク先一括変換\0"
#define FILE_VERSION 1,0,0,0
#define VERSION_NUMBER 	"1, 0, 0,0"
#define VERSION_NUMBER0 "1, 0, 0,0\0"
#define COPYRIGHT "Copyright (C) 2014/08/27"
#define COPYRIGHT0 "Copyright (C) 2014/08/27"
#define DESCRIPTION  "キラー"
#define DESCRIPTION0  "キラー\0"
#define APL_VER	"ショートカットリンク先一括変換 Version  1, 0, 0,0"

resource.rc

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

IDI_ICON	ICON	DISCARDABLE	"org.ico"

DLG1 DIALOG DISCARDABLE 0, 0, 460, 387
EXSTYLE WS_EX_DLGMODALFRAME
STYLE WS_POPUP  | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | DS_SETFONT
CAPTION "ショートカットリンク先一括変換"
FONT 9, "MS 明朝"
{
 CONTROL "変換対象フォルダー", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 14, 103, 14

 CONTROL "C:\\", IDC_DIR_EDIT, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 14, 28, 378, 14
 CONTROL "参照", IDC_REF_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 399, 28, 47, 14

 CONTROL "リンク先変換ルール", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 56, 96, 14
 CONTROL "ルール1", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 14, 71, 48, 14

 CONTROL "", IDC_SRC_EDIT1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 62, 69, 173, 14
 CONTROL "→", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 250, 71, 16, 14
 CONTROL "", IDC_DTC_EDIT1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 273, 69, 173, 14

 CONTROL "ルール2", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 14, 93, 48, 14
 CONTROL "", IDC_SRC_EDIT1+1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 62, 91 173, 14
 CONTROL "→", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 250, 93, 16, 14
 CONTROL "", IDC_DTC_EDIT1+1, "EDIT", WS_CHILD | WS_DLGFRAME | WS_VISIBLE | ES_AUTOHSCROLL, 273, 91,173, 14

 CONTROL "変換結果", -1, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 119, 60, 14
 CONTROL "ListView110", IDC_LISTVIEW, "SYSLISTVIEW32", WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT, 14, 133, 432, 184
 
 CONTROL "", IDC_STATUS_LABEL, "STATIC", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 7, 331,439, 28

 CONTROL "変換", IDC_CHG_BUTTON, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 169, 359, 54, 18
 CONTROL "キャンセル", IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 237, 359, 54, 18

}

//--------------------
//  ヴァージョン情報
//--------------------

VS_VERSION_INFO VERSIONINFO
 FILEVERSION FILE_VERSION
 PRODUCTVERSION FILE_VERSION
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "Comments", APL_NAME0
            VALUE "CompanyName",DESCRIPTION0
            VALUE "FileDescription", APL_NAME0
            VALUE "FileVersion", VERSION_NUMBER0 
            VALUE "InternalName", "\0"
            VALUE "LegalCopyright", COPYRIGHT0
            VALUE "OriginalFilename", "shortcutchg.exe\0"
            VALUE "ProductName", APL_NAME0
            VALUE "ProductVersion",  VERSION_NUMBER0 
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation",0x0411, 0x03A4 
    END
END

実行ファイルとソースファイルのダウンロード