ファイル システムの管理

シェルには、ファイル システムを管理するためのさまざまな方法が用意されています。 シェルには、アプリケーションがプログラムでファイルの移動、コピー、名前変更、削除を行える SHFileOperation 関数が用意されています。 シェルでは、いくつかの追加のファイル管理機能もサポートされています。

  • HTML ドキュメントは、グラフィックス ファイルやスタイル シートなどの関連ファイルに 接続 できます。 ドキュメントを移動またはコピーすると、接続されているファイルも自動的に移動またはコピーされます。
  • 複数のユーザーが使用できるシステムの場合、ファイルはユーザーごとに管理できます。 ユーザーはデータ ファイルに簡単にアクセスできますが、他のユーザーに属するファイルにはアクセスできません。
  • ドキュメント ファイルが追加または変更された場合は、シェルの最近のドキュメントの一覧に追加できます。 ユーザーが [スタート] メニューの [ ドキュメント ] コマンドをクリックすると、ドキュメントへのリンクの一覧が表示されます。

このドキュメントでは、これらのファイル管理テクノロジのしくみについて説明します。 次に、シェルを使用してファイルを移動、コピー、名前変更、削除する方法と、ごみ箱内のオブジェクトを管理する方法について説明します。

Per-User ファイル管理

Windows 2000 シェルを使用すると、ファイルを特定のユーザーに関連付け、ファイルを他のユーザーから非表示にできます。 ファイル システムに関しては、ファイルはユーザーのプロファイル フォルダー (通常は Windows 2000 システムの C:\Documents and Settings\Username\ ) の下に格納されます。 この機能を使用すると、多くのユーザーが同じコンピューターを使用しながら、他のユーザーからのファイルのプライバシーを維持できます。 異なるユーザーは、異なるプログラムを使用できます。 また、管理者やアプリケーションが初期化 (.ini) ファイルやリンク (.lnk) ファイルなどを格納するための簡単な方法も提供します。 そのため、アプリケーションはユーザーごとに異なる状態を保持し、必要に応じてその特定の状態を簡単に回復できます。 すべてのユーザーに共通する情報を格納するためのプロファイル フォルダーもあります。

ログインしているユーザーとそのファイルの場所を判断するのは不便であるため、標準のユーザーごとのフォルダーは特別なフォルダーであり、 CSIDL によって識別されます。 たとえば、ユーザーごとの Program Files フォルダーの CSIDL がCSIDL_PROGRAMS。 アプリケーションで SHGetFolderLocation または SHGetFolderPath をユーザーごとの CSIDLs のいずれかを使用して呼び出す場合、この関数は、現在ログインしているユーザーに適した項目識別子リスト (PIDL) またはパスへのポインターを返します。 アプリケーションでプロファイル フォルダーのパスまたは PIDL を取得する必要がある場合、その CSIDL は CSIDL_PROFILE

マイ ドキュメントとマイ ピクチャ フォルダー

デスクトップに表示される標準的なアイコンの 1 つは 、[マイ ドキュメント] です。 このフォルダーを開くと、現在のユーザーのドキュメント ファイルが含まれます。 マイ ドキュメントのデスクトップ インスタンスは、仮想フォルダーです。これは、ユーザーのドキュメントを物理的に格納するために使用されるファイル システムの場所のエイリアスであり、名前空間階層のデスクトップのすぐ下にあります。

[マイ ドキュメント] フォルダーと [マイ ピクチャ] フォルダーの目的は、ユーザーが複数のユーザーがいる可能性があるシステム上のドキュメントファイルや画像ファイルに簡単かつ安全にアクセスできるようにすることです。 各ユーザーには、自分のファイルに個別のファイル システム フォルダーが割り当てられます。 たとえば、ファイル システム内のユーザーのドキュメント フォルダーの場所は、通常、C:\Documents と Settings\username\My Documents のようなものです。 ユーザーは、ファイル システム フォルダーの物理的な場所について何も知る必要はありません。 [マイ ドキュメント] アイコンを使用してファイルにアクセスするだけです。

注意

マイ ドキュメントを使用すると、ユーザーは自分のファイルにアクセスできますが、他のユーザーのファイルにはアクセスできません。 複数の個人が同じコンピューターを使用している場合、管理者は、実際のファイルが格納されているファイル システムの一部からユーザーをロックアウトできます。 したがって、ユーザーはマイ ドキュメント フォルダーを使用して自分のドキュメントを操作できますが、他のユーザーに属するドキュメントでは作業できません。

 

通常、どのユーザーがログインしているか、ファイル システム内のユーザーの [マイ ドキュメント] フォルダーがどこにあるかをアプリケーションで知る必要はありません。 代わりに、アプリケーションは、デスクトップの IShellFolder::P arseDisplayName メソッドを呼び出すことによって、マイ ドキュメント デスクトップ アイコンの PIDL を取得できます。 マイ ドキュメント フォルダーを識別するために使用される解析名は、ファイル パスではなく、::{450d8fba-ad25-11d0-98a8-0800361b1103} です。 角かっこで囲まれた式は、My Documents GUID のテキスト 形式です。 たとえば、マイ ドキュメントの PIDL を取得するには、アプリケーションで IShellFolder::P arseDisplayName へのこの呼び出しを使用する必要があります。

hr = psfDeskTop->ParseDisplayName(NULL, 
                                  NULL, 
                                  L"::{450d8fba-ad25-11d0-98a8-0800361b1103}", 
                                  &chEaten, 
                                  &pidlDocFiles, 
                                  NULL);

アプリケーションがマイ ドキュメント PIDL を取得すると、通常のファイル システム フォルダーと同様にフォルダーを処理できます。つまり、項目の列挙、解析、バインド、その他の有効なフォルダー操作の実行が可能になります。 シェルは、マイ ドキュメントまたはそのサブフォルダーの変更を適切なファイル システム フォルダーに自動的にマップします。

アプリケーションが現在のユーザーのドキュメントを含む実際のファイル システム フォルダーにアクセスする必要がある場合は、 CSIDL_PERSONALを SHGetFolderLocation に渡します。 関数は、現在のユーザーの [マイ ドキュメント] フォルダーに表示されているファイル システム フォルダーの PIDL を返します。

接続されているファイル

HTML ドキュメントには、多くの場合、関連するグラフィックス ファイル、スタイル シート ファイル、いくつかの Microsoft JScript (ECMA 262 言語仕様と互換性があります) ファイルなどが含まれます。 プライマリ HTML ドキュメントを移動またはコピーする場合は、通常、リンクが壊れないように、関連付けられているファイルを移動またはコピーします。 残念ながら、これまでは、コンテンツを分析する以外に、特定の HTML ドキュメントに関連するファイルを特定する簡単な方法はありませんでした。 この問題を軽減するために、Windows 2000 では、プライマリ HTML ドキュメントを関連付けられているファイルのグループに 簡単に接続 できます。 ファイル接続が有効になっている場合、ドキュメントが移動またはコピーされると、接続されているすべてのファイルが一緒に移動されます。

接続されたファイルのグループを作成するには、プライマリ ドキュメントに.htmまたは.htmlファイル名拡張子が必要です。 プライマリ ドキュメントの親フォルダーのサブフォルダーを作成します。 サブフォルダーの名前は、プライマリ ドキュメントの名前から、.htmまたは.html拡張子を差し引いた後に、次に示す拡張機能のいずれかを引いた名前にする必要があります。 最も一般的に使用される拡張子は、".files" または "_files" です。 たとえば、プライマリ ドキュメントに MyDoc.htm という名前が付けられている場合、サブフォルダーに "MyDoc_files" という名前を付けると、サブフォルダーがドキュメントの接続ファイルのコンテナーとして定義されます。 プライマリ ドキュメントを移動またはコピーすると、サブフォルダーとそのファイルも移動またはコピーされます。

一部の言語では、ローカライズされた同等の "_files" を使用して、接続されたファイルのサブフォルダーを作成できます。 次の表は、接続されたファイル サブフォルダーを作成するためにドキュメント名に追加できる有効な文字列の一覧です。 これらの文字列の中には、'_' や '.' ではなく、最初の文字として '-' を持つものもあります。

"_archivos"

"_arquivos"

"_bestanden"

"_bylos"

"-Dateien"

"_datoteke"

"_dosyalar"

"_elemei"

"_failid"

"_fails"

"_fajlovi"

"_ficheiros"

"_fichiers"

"-filer"

".files"

"_files"

"_file"

"_fitxers"

"_fitxategiak"

"_pliki"

"_soubory"

"_tiedostot"

 

注意

この機能は、拡張機能の大文字と小文字が区別されます。 たとえば、上記の例では、"MyDoc_Files" という名前のサブフォルダーはMyDoc.htmに接続されません。

 

ファイル接続が有効か無効かは、次のレジストリ キーの REG_DWORD 値 NoFileFolderConnection によって制御されます。

HKEY_CURRENT_USER
   Software
      Microsoft
         Windows
            CurrentVersion
               Explorer

通常、この値は定義されておらず、ファイル接続が有効になっています。 必要に応じて、キーにこの値を追加して 1 に設定することで、ファイル接続を無効にすることができます。 ファイル接続を再度有効にするには、NoFileFolderConnection を 0 に設定します。

注意

他のアプリケーションがそれに依存する可能性があるため、通常はファイル接続を有効にする必要があります。 絶対に必要な場合にのみ、ファイル接続を無効にします。

 

ファイルの移動、コピー、名前変更、削除

名前空間は静的ではなく、アプリケーションでは通常、次のいずれかの操作を実行してファイル システムを管理する必要があります。

  • オブジェクトを別のフォルダーにコピーする。
  • オブジェクトを別のフォルダーに移動する。
  • オブジェクトを削除しています。
  • オブジェクトの名前を変更します。

これらの操作はすべて SHFileOperation で実行されます。 この関数は、1 つ以上のソース ファイルを受け取り、対応する変換先ファイルを生成します。 削除操作の場合、システムは削除されたファイルをごみ箱に格納しようとします。

ドラッグ アンド ドロップ機能を使用してファイルを移動することもできます。

関数を使用するには、 SHFILEOPSTRUCT 構造体のメンバーを入力し、 SHFileOperation に渡す必要があります。 構造体の主要なメンバーは pFrompTo です

pFrom メンバーは、1 つ以上のソース ファイル名を含む null で終わる二重文字列です。 これらの名前には、完全修飾パスまたは *.* などの標準の DOS ワイルドカードを指定できます。 このメンバーは null で終わる文字列として宣言されていますが、複数のファイル名を保持するためのバッファーとして使用されます。 各ファイル名は、通常の 1 つの NULL 文字で終了する必要があります。 pFrom の末尾を示すには、最後の名前の末尾に追加の NULL 文字を追加する必要があります。

pTo メンバーは、pFrom と同様に、null で終わる二重文字列です。 pTo メンバーには、1 つ以上の完全修飾宛先名の名前が含まれています。 pFrom の場合と同じ方法で pTo にパックされますpTo に複数の名前が含まれている場合は、fFlags メンバーで FOF_MULTIDESTFILES フラグも設定する必要があります。 pTo の使用方法は、ここで説明する操作によって異なります。

  • コピー操作と移動操作では、すべてのファイルが 1 つのディレクトリに移動する場合、 pTo には完全修飾ディレクトリ名が含まれます。 ファイルが異なる宛先に移動する場合、 pTo には 、ソース ファイルごとに 1 つの完全修飾ディレクトリまたはファイル名を含めることもできます。 ディレクトリが存在しない場合は、システムによって作成されます。
  • 名前変更操作の場合、 pTo には pFrom 内のソース ファイルごとに 1 つの完全修飾パスが含まれます。
  • 削除操作の場合、 pTo は使用されません。

シェルへの通知

SHFileOperation を使用してファイルを移動、コピー、名前変更、または削除した後、または名前空間に影響を与えるその他のアクションを実行した後に、変更をシェルに通知します。 通知を伴う必要があるアクションは次のとおりです。

  • ファイルまたはフォルダーの追加または削除。
  • ファイルまたはフォルダーの移動、コピー、または名前変更。
  • ファイルの関連付けを変更する。
  • ファイル属性の変更。
  • ドライブまたはストレージ メディアの追加または削除。
  • 共有フォルダーの作成または無効化。
  • システム・イメージ・リストの変更。

アプリケーションは、変更された内容の詳細を SHChangeNotify を呼び出してシェルに通知します。 その後、シェルは名前空間のイメージを更新して、新しい状態を正確に反映できます。

SHFileOperation を使用したファイルの管理の簡単な例

次のサンプル コンソール アプリケーションは、 SHFileOperation を使用して、あるディレクトリから別のディレクトリにファイルをコピーする方法を示しています。 C:\My_Docs と C:\My_Docs2 のソース ディレクトリと変換先ディレクトリは、わかりやすくするためにアプリケーションにハードコーディングされています。

#include <shlobj.h>
#include <shlwapi.h>
#include <strsafe.h>

int main(void)
{
    IShellFolder *psfDeskTop = NULL;
    IShellFolder *psfDocFiles = NULL;
    LPITEMIDLIST pidlDocFiles = NULL;
    LPITEMIDLIST pidlItems = NULL;
    IEnumIDList *ppenum = NULL;
    SHFILEOPSTRUCT sfo;
    STRRET strDispName;
    TCHAR szParseName[MAX_PATH];
    TCHAR szSourceFiles[256];
    int i;
    int iBufPos = 0;
    ULONG chEaten;
    ULONG celtFetched;
    size_t ParseNameSize = 0;
    HRESULT hr;
    

    szSourceFiles[0] = '\0';
    hr = SHGetDesktopFolder(&psfDeskTop);

    hr = psfDeskTop->ParseDisplayName(NULL, NULL, L"c:\\My_Docs", 
         &chEaten, &pidlDocFiles, NULL);
    hr = psfDeskTop->BindToObject(pidlDocFiles, NULL, IID_IShellFolder, 
         (LPVOID *) &psfDocFiles);
    hr = psfDeskTop->Release();

    hr = psfDocFiles->EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 
         &ppenum);

    while( (hr = ppenum->Next(1,&pidlItems, &celtFetched)) == S_OK 
       && (celtFetched) == 1)
    {
        psfDocFiles->GetDisplayNameOf(pidlItems, SHGDN_FORPARSING, 
            &strDispName);
        StrRetToBuf(&strDispName, pidlItems, szParseName, MAX_PATH);
        
        hr = StringCchLength(szParseName, MAX_PATH, &ParseNameSize);
        
        if (SUCCEEDED(hr))
        {
            for(i=0; i<=ParseNameSize; i++)
            {
                szSourceFiles[iBufPos++] = szParseName[i];
            }
            CoTaskMemFree(pidlItems);
        }
    }
    ppenum->Release();
    
    szSourceFiles[iBufPos] = '\0';

    sfo.hwnd = NULL;
    sfo.wFunc = FO_COPY;
    sfo.pFrom = szSourceFiles;
    sfo.pTo = "c:\\My_Docs2\0";
    sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;

    hr = SHFileOperation(&sfo);
    
    SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH, (LPCVOID) "c:\\My_Docs2", 0);

    CoTaskMemFree(pidlDocFiles);
    psfDocFiles->Release();

    return 0;
}

アプリケーションは、最初にデスクトップの IShellFolder インターフェイスへのポインターを取得します。 その後、 IShellFolder::P arseDisplayName に完全修飾パスを渡すことによって、ソース ディレクトリの PIDL を取得します。 IShellFolder::P arseDisplayName には、ディレクトリのパスが Unicode 文字列である必要があることに注意してください。 その後、アプリケーションはソース ディレクトリにバインドし、その IShellFolder インターフェイスを使用して列挙子オブジェクトの IEnumIDList インターフェイスを取得します。

ソース ディレクトリ内の各ファイルが列挙されると、その名前を取得するために IShellFolder::GetDisplayNameOf が使用されます。 SHGDN_FORPARSING フラグが設定されているため、 IShellFolder::GetDisplayNameOf はファイルの完全修飾パスを返します。 終端 の NULL 文字を含むファイル パスは、単一の配列 szSourceFiles に連結されます。 配列を正しく終了するために、最後のパスに 2 番目の NULL 文字が追加されます。

列挙が完了すると、アプリケーションは SHFILEOPSTRUCT 構造体に値を割り当てます。 コピー先を指定するために pTo に割り当てられた配列も、二重 NULL で終了する必要があることに注意 してください。 この場合、 pTo に割り当てられている文字列に含まれるだけです。 これはコンソール アプリケーションであるため、FOF_SILENT、FOF_NOCONFIRMATION、およびFOF_NOCONFIRMMKDIRフラグは、表示される可能性のあるダイアログ ボックスを抑制するように設定されます。 SHFileOperation が返されると、変更をシェルに通知するために SHChangeNotify が呼び出されます。 その後、アプリケーションは通常のクリーンアップを実行し、 を返します。

シェルの最近使用したドキュメントの一覧にファイルを追加する

シェルでは、ユーザーごとに最近追加または変更されたドキュメントの一覧が保持されます。 ユーザーは、[スタート] メニューの [ドキュメント] をクリックして、これらのファイルへのリンクの一覧を表示できます。 マイ ドキュメントと同様に、各ユーザーには、実際のリンクを保持するファイル システム ディレクトリがあります。 現在のユーザーの Recent ディレクトリの PIDL を取得するには、アプリケーションで CSIDL_RECENTを使用して SHGetFolderLocation を呼び出すか、 SHGetFolderPath を呼び出してパスを取得します。

アプリケーションでは、このドキュメントで前述した手法を使用して、Recent フォルダーの内容を列挙できます。 ただし、アプリケーションでは、通常のファイル システム フォルダーのようにフォルダーの内容を変更しないでください。 その場合、シェルの最近のドキュメントの一覧は正しく更新されず、変更は [スタート] メニューに反映されません。 代わりに、ユーザーの Recent フォルダーにドキュメント リンクを追加するために、アプリケーションで SHAddToRecentDocs を呼び出すことができます。 シェルは、適切なファイル システム フォルダーへのリンクを追加し、最近使用したドキュメントの一覧と [スタート] メニューを更新します。 この関数を使用して、フォルダーをクリアすることもできます。