ディレクトリ操作
ディレクトリとフォルダはここでは同じものと考えて構いません。
ディレクトリの作成
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
関数と同じです。
こちらも重要なファイル群が格納されているので普通は操作することはありません。