Управление файловой системой

Оболочка предоставляет несколько способов управления файловой системой. Оболочка предоставляет функцию SHFileOperation, которая позволяет приложению перемещать, копировать, переименовывать и удалять файлы программными средствами. Оболочка также поддерживает некоторые дополнительные возможности управления файлами.

  • HTML-документы можно подключить к связанным файлам, таким как графические файлы или таблицы стилей. При перемещении или копировании документа подключенные файлы также автоматически перемещаются или копируются.
  • Для систем, доступных для нескольких пользователей, управление файлами можно осуществлять для каждого пользователя. Пользователи имеют простой доступ к файлам данных, но не к файлам, принадлежащим другим пользователям.
  • Если файлы документов добавляются или изменяются, их можно добавить в список последних документов оболочки. Когда пользователь щелкает команду Документы в меню Пуск, появляется список ссылок на документы.

В этом документе рассматривается принцип работы этих технологий управления файлами. Затем в ней показано, как с помощью оболочки перемещать, копировать, переименовывать и удалять файлы, а также управлять объектами в корзине.

Управление файлами Per-User

Оболочка Windows 2000 позволяет связывать файлы с определенным пользователем, чтобы файлы оставались скрытыми от других пользователей. Что касается файловой системы, файлы хранятся в папке профиля пользователя, обычно C:\Documents and Settings\Username\ в системах Windows 2000. Эта функция позволяет многим пользователям использовать один и тот же компьютер, сохраняя при этом конфиденциальность своих файлов от других пользователей. У разных пользователей могут быть разные программы. Она также предоставляет администраторам и приложениям простой способ хранения файлов инициализации (.ini) или ссылок (LNK). Таким образом, приложения могут сохранять разные состояния для каждого пользователя и легко восстанавливать это конкретное состояние при необходимости. Существует также папка профиля для хранения сведений, общих для всех пользователей.

Так как определить, какой пользователь вошел в систему и где находятся его файлы, неудобно, стандартные папки для каждого пользователя являются специальными папками и определяются CSIDL. Например, CSIDL для папки Program Files для каждого пользователя CSIDL_PROGRAMS. Если приложение вызывает SHGetFolderLocation или SHGetFolderPath с одним из CSIDL для каждого пользователя, функция возвращает указатель на список идентификаторов элементов (PIDL) или путь, соответствующий текущему пользователю, вошедшего в систему. Если приложению необходимо получить путь или PIDL папки профиля, его CSIDL CSIDL_PROFILE.

Папки "Мои документы" и "Мои рисунки"

Один из стандартных значков на рабочем столе — "Мои документы". При открытии этой папки она содержит файлы документов текущего пользователя. Экземпляр рабочего стола "Мои документы" — это виртуальная папка( псевдоним расположения файловой системы, используемого для физического хранения документов пользователя), расположенная непосредственно под рабочим столом в иерархии пространства имен.

Цель папок "Мои документы" и "Мои рисунки" — предоставить пользователям простой и безопасный способ доступа к файлам документов и изображений в системе, которая может иметь нескольких пользователей. Каждому пользователю назначаются отдельные папки файловой системы для его файлов. Например, папка документов пользователя в файловой системе обычно имеет вид C:\Documents and Settings\username\My Documents. Пользователям не нужно ничего знать о физическом расположении папок файловой системы. Они просто получают доступ к своим файлам с помощью значка "Мои документы".

Примечание

Мои документы позволяют пользователю получать доступ к своим файлам, но не к файлам других пользователей. Если несколько пользователей используют один и тот же компьютер, администратор может заблокировать пользователей в той части файловой системы, где хранятся фактические файлы. Таким образом, пользователи смогут работать с собственными документами через папку "Мои документы", но не с документами, принадлежащими другим пользователям.

 

Обычно приложению не нужно знать, какой пользователь вошел в систему или где находится папка "Мои документы" этого пользователя в файловой системе. Вместо этого приложение может получить PIDL значка "Мои документы" на рабочем столе, вызвав метод IShellFolder::P arseDisplayName рабочего стола. Имя синтаксического анализа, используемое для идентификации папки "Мои документы", — это не путь к файлу, а :::450d8fba-ad25-11d0-98a8-0800361b1103}. Выражение в квадратных скобках — это текстовая форма 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. Эта функция принимает один или несколько исходных файлов и создает соответствующие целевые файлы. В случае операции удаления система пытается поместить удаленные файлы в корзину.

Можно также перемещать файлы с помощью функции перетаскивания .

Чтобы использовать функцию, необходимо заполнить элементы структуры SHFILEOPSTRUCT и передать их в SHFileOperation. Ключевыми элементами структуры являются pFrom и pTo.

Элемент pFrom — это строка с двойным завершением NULL, которая содержит одно или несколько имен исходных файлов. Это могут быть полные пути или стандартные подстановочные знаки DOS, такие как *.*. Хотя этот элемент объявлен как строка, завершающаяся нулевым значением, он используется в качестве буфера для хранения нескольких имен файлов. Каждое имя файла должно заканчиваться обычным символом NULL . Чтобы указать конец pFrom, в конце конечного имени необходимо добавить дополнительный символ NULL.

Элемент pTo — это строка с двойным нулем, как и pFrom. Элемент pTo содержит имена одного или нескольких полных имен назначения. Они упаковываются в pTo так же, как и для pFrom. Если pTo содержит несколько имен, необходимо также установить флаг FOF_MULTIDESTFILES в элементе fFlags . Использование pTo зависит от операции, как описано здесь.

  • Если для операций копирования и перемещения все файлы находятся в одном каталоге, pTo содержит полное имя каталога. Если файлы находятся в разных местах назначения, pTo также может содержать один полный каталог или имя файла для каждого исходного файла. Если каталог не существует, система создает его.
  • Для операций переименования pTo содержит один полный путь к каждому исходному файлу в pFrom.
  • Для операций удаления 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 рабочего стола. Затем он получает PIDL исходного каталога, передавая его полный путь в IShellFolder::P arseDisplayName. Обратите внимание, что IShellFolder::P arseDisplayName требует, чтобы путь к каталогу был строкой Юникода. Затем приложение привязывается к исходному каталогу и использует его интерфейс IShellFolder для получения интерфейса IEnumIDList объекта перечислителя.

При перечислении каждого файла в исходном каталоге для получения его имени используется IShellFolder::GetDisplayNameOf . Установлен флаг SHGDN_FORPARSING, в результате чего IShellFolder::GetDisplayNameOf возвращает полный путь к файлу. Пути к файлам, включая завершающие символы NULL , объединяются в один массив szSourceFiles. Второй символ NULL добавляется к последнему пути для правильного завершения массива.

После завершения перечисления приложение присваивает значения структуре SHFILEOPSTRUCT . Обратите внимание, что массив, назначенный pTo для указания назначения, также должен заканчиваться двойным значением NULL. В этом случае он просто включается в строку, назначенную pTo. Так как это консольное приложение, флаги FOF_SILENT, FOF_NOCONFIRMATION и FOF_NOCONFIRMMKDIR настроены для подавления всех диалоговых окон, которые могут отображаться. После возврата SHFileOperation вызывается SHChangeNotify , чтобы уведомить оболочку об изменении. Затем приложение выполняет обычную очистку и возвращает .

Добавление файлов в список последних документов оболочки

Оболочка хранит список недавно добавленных или измененных документов для каждого пользователя. Пользователь может отобразить список ссылок на эти файлы, щелкнув Документы в меню Пуск. Как и в случае с "Мои документы", у каждого пользователя есть каталог файловой системы для хранения фактических ссылок. Чтобы получить PIDL каталога Recent текущего пользователя, приложение может вызвать SHGetFolderLocation с CSIDL_RECENT или метод SHGetFolderPath , чтобы получить путь к нему.

Приложение может перечислить содержимое папки Recent с помощью методов, описанных ранее в этом документе. Однако приложение не должно изменять содержимое папки так, как если бы это была обычная папка файловой системы. В этом случае список последних документов оболочки не будет обновлен должным образом, и изменения не будут отражены в меню "Пуск". Вместо этого, чтобы добавить ссылку на документ в папку Recent пользователя, приложение может вызвать SHAddToRecentDocs. Оболочка добавит ссылку на соответствующую папку файловой системы, а также обновит список последних документов и меню "Пуск". Эту функцию также можно использовать для очистки папки.