ディレクトリ操作

ディレクトリフォルダはここでは同じものと考えて構いません。

ディレクトリの作成

CreateDirectory関数

ディレクトリの作成はCreateDirectory関数を使用します。

BOOL CreateDirectoryW(
 LPCWSTR lpPathName,
 LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
新しいディレクトリlpPathNameを作成する。
成功した場合は0以外を、失敗した場合は0を返す。

lpPathNameは新しいディレクトリのパス(場所+名前)です。

lpSecurityAttributesはセキュリティ記述子を設定するSECURITY_ATTRIBUTES構造体のポインタです。
セキュリティ記述子とはファイルの所有者やアクセス権者を設定するものです。
NULLを指定すると既定のセキュリティ記述子を使用します。
(ややこしいので説明は省きます)

この関数は存在しないディレクトリ下にディレクトリを作ることはできません。
例えばディレクトリ「C:\abc\」が存在しない場合、関数の引数に「C:\abc\def\」を指定して一気に階層構造を作成することはできません。
この場合、ディレクトリ「def」を作る前にディレクトリ「abc」を作成する必要があります。

CreateDirectoryEx関数

ディレクトリの作成はCreateDirectoryEx関数を使用することもできます。

BOOL CreateDirectoryExW(
 LPCWSTR lpTemplateDirectory,
 LPCWSTR lpNewDirectory,
 LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
ディレクトリlpTemplateDirectoryの属性を元にして新しいディレクトリlpPathNameを作成する。
成功した場合は0以外を、失敗した場合は0を返す。

第一引数lpTemplateDirectoryに、既存の別のディレクトリを指定するようになっています。
このディレクトリの属性を適用して新しいディレクトリ(lpNewDirectory)を作成します。
それ以外はCreateDirectory関数と同じです。

SHCreateDirectoryEx関数

ディレクトリはSHCreateDirectoryEx関数で作成することもできます。
この関数の使用にはshlobj_core.hをインクルードする必要があります。
また、Windows XP SP2以降で使用可能です。

int SHCreateDirectoryExW(
 HWND hwnd,
 LPCWSTR pszPath,
 const SECURITY_ATTRIBUTES *psa
);
新しいディレクトリpszPathを作成する。
成功した場合は0以外を、失敗した場合は0を返す。

第一引数hwndは親ウィンドウハンドルです。
この関数がエラーダイアログを表示する時、このウィンドウを親として表示します。
(エラー時に常にダイアログが表示されるわけではありません)
NULLを指定するとダイアログは表示されません。

第二引数pszPathは作成するディレクトリのパスです。
このパスは絶対パス(完全修飾パス)である必要があります。
(ドライブ名から指定する)
階層構造を指定する時、途中に存在しないディレクトリが存在する場合は同時に作成されます。
また、区切り文字にスラッシュは使用できません。

第三引数psaはセキュリティ記述子の指定です。
必要なければNULLを指定します。

ディレクトリの削除

ディレクトリの削除はRemoveDirectory関数を使用します。

BOOL RemoveDirectoryW(
 LPCWSTR lpPathName
);
ディレクトリlpPathNameを削除する。
成功した場合は0以外を、失敗した場合は0を返す。

lpPathNameにディレクトリのパス文字列を指定します。

この関数はディレクトリが空の場合のみ成功します。
また、ごみ箱には移動しないので注意が必要です。

空ではないディレクトリを削除する

RemoveDirectory関数は中身が空ではないディレクトリは削除できません。
これを削除するには主に

  • 中身をすべて削除してからディテクトリを削除する
  • SHFileOperation関数を使用する

の二通りがあります。
SHFileOperation関数は上記リンクを参照してください。
中身をすべて削除してからディレクトリを削除するサンプルは空ではないディレクトリを削除するの項を参照してください。

ディレクトリの移動、名前変更、コピー

ディレクトリを移動や名前を変更するにはMoveFile関数を使用します。
ただしMoveFile関数は同じボリューム(ドライブ)上でのディレクトリ移動は可能ですが、別ボリュームへの移動はできません。

別ボリュームへのディレクトリの移動やコピーはSHFileOperation関数で可能です。
その他、自分で実装する方法もあります。
そのサンプルはディレクトリをコピーするの項を参照してください。

ディレクトリの存在確認

ディレクトリの存在確認はPathFileExists関数PathIsDirectory関数を使用します。
詳しくはリンク先ページを参照してください。

空のディレクトリの判定

ディレクトリが空か否かを判定するにはPathIsDirectoryEmpty関数が使用できます。

BOOL PathIsDirectoryEmptyW(
 LPCWSTR pszPath
);
パス文字列pszPathが空のディレクトリの場合はTRUEを返す。
ディレクトリが空でない場合、存在しない場合、およびディレクトリでない場合はFALSEを返す。

特定のディレクトリ

GetCurrentDirectory関数

プログラムにはカレントディレクトリという概念があります。
(current=現在の)
これは「現在操作対象になっているディレクトリ」を意味するもので、何も設定しなければ実行ファイルが保存されている場所がカレントディレクトリとなります。
「作業フォルダ」とも呼ばれ、プログラムからファイルやディレクトリの場所を相対パスで指定する場合の起点となるディレクトリです。

カレントディレクトリはGetCurrentDirectory関数で取得できます。

DWORD GetCurrentDirectory(
 DWORD nBufferLength,
 LPTSTR lpBuffer
);
カレントディレクトリを文字列バッファlpBufferにnBufferLength文字分格納する。
戻り値は取得した文字数
(NULL文字は含まない)

nBufferLengthは次に指定するバッファ(文字列配列)のサイズを指定します。
lpBufferは取得した文字列を受け取るバッファです。

バッファサイズはパス文字列(ファイルやディレクトリの場所を示す文字列)を格納できるだけの十分なサイズをあらかじめ確保しておく必要があります。
Windowsで使用されるパス名の最大の長さはMAX_PATHという定数で定義されているので、これを使用するのが一般的です。
これは末尾のNULL文字も含めた長さです。

SetCurrentDirectory関数

カレントディレクトリの変更はSetCurrentDirectory関数を使用します。

BOOL SetCurrentDirectory(
 LPCTSTR lpPathName
);
カレントディレクトリを文字列lpPathNameに設定する。
成功した場合は0以外を、失敗した場合は0を返す。

指定する文字列の最後の文字は区切り文字(\記号)を指定します。
区切り文字を指定しなかった場合、自動で区切り文字が追加されます。
文字列の末尾にはNULL文字が付加されますから、最後が区切り文字の場合の文字列の最大の長さは「MAX_PATH - 1」、区切り文字ではない場合は「MAX_PATH - 2」までとなります。

パスの指定は絶対パス、相対パスのどちらでも可能です。
相対パスの場合は..\でひとつ上のディレクトリ、.\で同じ階層のディレクトリを表します。
(これらの記号を指定しない場合は同じ階層のディレクトリを表します)

区切り文字は「\」(円記号またはバックスラッシュ)のほか、「/」(スラッシュ)を指定することもできます。


#include <windows.h>

//ウィンドウの生成等は省略

#define IDC_STATIC -1
#define IDC_EDIT1 100
#define IDC_EDIT2 101
#define IDC_BUTTON1 102
#define IDC_STATIC1 103
#define ID_TIMER1 1

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	WCHAR buf[MAX_PATH];

	switch (message)
	{
	case WM_CREATE:
		GetCurrentDirectory(MAX_PATH, buf);

		CreateWindow(
			L"STATIC", L"カレントディレクトリ",
			WS_CHILD | WS_VISIBLE,
			10, 10, 480, 24,
			hWnd, (HMENU)IDC_STATIC, hInst, NULL);

		CreateWindowEx(
			WS_EX_CLIENTEDGE,
			L"EDIT", buf,
			WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | ES_READONLY,
			10, 35, 480, 24,
			hWnd, (HMENU)IDC_EDIT1, hInst, NULL);

		CreateWindow(
			L"STATIC", L"新しいカレントディレクトリ",
			WS_CHILD | WS_VISIBLE,
			10, 70, 480, 24,
			hWnd, (HMENU)IDC_STATIC, hInst, NULL);
		CreateWindowEx(
			WS_EX_CLIENTEDGE,
			L"EDIT", buf,
			WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_BORDER,
			10, 95, 480, 24,
			hWnd, (HMENU)IDC_EDIT2, hInst, NULL);

		CreateWindow(
			L"BUTTON", L"設定",
			WS_CHILD | WS_VISIBLE,
			10, 120, 60, 24,
			hWnd, (HMENU)IDC_BUTTON1, hInst, NULL);
		CreateWindow(
			L"STATIC", NULL,
			WS_CHILD | WS_VISIBLE,
			70, 120, 420, 24,
			hWnd, (HMENU)IDC_STATIC1, hInst, NULL);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDC_BUTTON1:
			GetDlgItemText(hWnd, IDC_EDIT2, buf, MAX_PATH);
			if (SetCurrentDirectory(buf)) {
				GetCurrentDirectory(MAX_PATH, buf);
				SetDlgItemText(hWnd, IDC_EDIT1, buf);
				SetDlgItemText(hWnd, IDC_STATIC1, L"カレントディレクトリを変更しました。");
				SetTimer(hWnd, ID_TIMER1, 5000, NULL);
			}
			else {
				SetDlgItemText(hWnd, IDC_STATIC1, L"カレントディレクトリの変更に失敗しました。");
				SetTimer(hWnd, ID_TIMER1, 5000, NULL);
			}
			break;
		}
		break;

	case WM_TIMER:
		SetDlgItemText(hWnd, IDC_STATIC1, L"");
		KillTimer(hWnd, ID_TIMER1);
		break;	

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

カレントディレクトリの取得と設定
ウィンドウ生成時にカレントディレクトリを取得し、上部のエディットコントロール(読み取り専用)に表示します。
下部のエディットコントロールに適当なフォルダパスを入力し、「設定」ボタンを押下することで新しいカレントディレクトリを設定できます。
設定に失敗した場合はその旨のメッセージが表示されます。
(タイマーはメッセージを消去するために使用しています。)

GetSystemDirectory関数

GetSystemDirectory関数は、システムディレクトリを取得します。

UINT GetSystemDirectoryW(
 LPWSTR lpBuffer,
 UINT uSize
);
バッファlpBufferにシステムディレクトリのパスを取得する。
成功した場合は0以外を、失敗した場合は0を返す。

lpBufferはパス文字列を受け取るバッファ、uSizeはバッファサイズ(文字数)の指定です。

システムディレクトリはシステムの動作に重要なファイルが格納されているので不用意に操作すべきではありません。
(管理者以外は書き込み権限はありません)

GetWindowsDirectory関数

GetWindowsDirectory関数は、Windowsディレクトリを取得します。

UINT GetWindowsDirectoryW(
 LPWSTR lpBuffer,
 UINT uSize
);
バッファlpBufferにWindowsディレクトリのパスを取得する。
成功した場合は0以外を、失敗した場合は0を返す。

使い方はGetSystemDirectory関数と同じです。
こちらも重要なファイル群が格納されているので普通は操作することはありません。