Gerenciando o sistema de arquivos

O Shell fornece várias maneiras de gerenciar sistemas de arquivos. O Shell fornece uma função , SHFileOperation, que permite que um aplicativo mova, copie, renomeie e exclua arquivos programaticamente. O Shell também dá suporte a alguns recursos adicionais de gerenciamento de arquivos.

  • Documentos HTML podem ser conectados a arquivos relacionados, como arquivos gráficos ou folhas de estilo. Quando o documento é movido ou copiado, os arquivos conectados também são movidos ou copiados automaticamente.
  • Para sistemas que estão disponíveis para mais de um usuário, os arquivos podem ser gerenciados por usuário. Os usuários têm acesso fácil aos arquivos de dados, mas não aos arquivos pertencentes a outros usuários.
  • Se os arquivos de documento forem adicionados ou modificados, eles poderão ser adicionados à lista de documentos recentes do Shell. Quando o usuário clica no comando Documentos no menu Iniciar, uma lista de links para os documentos é exibida.

Este documento discute como essas tecnologias de gerenciamento de arquivos funcionam. Em seguida, descreve como usar o Shell para mover, copiar, renomear e excluir arquivos e como gerenciar objetos na Lixeira.

gerenciamento de arquivos Per-User

O Shell do Windows 2000 permite que os arquivos sejam associados a um usuário específico para que os arquivos permaneçam ocultos de outros usuários. Em termos do sistema de arquivos, os arquivos são armazenados na pasta de perfil do usuário, normalmente C:\Documents and Settings\Username\ em sistemas Windows 2000. Esse recurso permite que muitas pessoas usem o mesmo computador, mantendo a privacidade de seus arquivos de outros usuários. Diferentes usuários podem ter programas diferentes disponíveis. Ele também fornece uma maneira simples para administradores e aplicativos armazenarem itens como arquivos de inicialização (.ini) ou link (.lnk). Assim, os aplicativos podem preservar um estado diferente para cada usuário e recuperar facilmente esse estado específico quando necessário. Também há uma pasta de perfil para armazenar informações comuns a todos os usuários.

Como é inconveniente determinar qual usuário está conectado e onde seus arquivos estão localizados, as pastas padrão por usuário são pastas especiais e são identificadas por um CSIDL. Por exemplo, o CSIDL para a pasta Arquivos de Programas por usuário é CSIDL_PROGRAMS. Se o aplicativo chamar SHGetFolderLocation ou SHGetFolderPath com um dos CSIDLs por usuário, a função retornará o ponteiro para uma lista de identificadores de item (PIDL) ou o caminho apropriado para o usuário conectado no momento. Se o aplicativo precisar recuperar o caminho ou o PIDL da pasta de perfil, seu CSIDL será CSIDL_PROFILE.

Meus Documentos e Minhas Pastas de Imagens

Um dos ícones padrão encontrados na área de trabalho é Meus Documentos. Quando você abre essa pasta, ela contém os arquivos de documento do usuário atual. A instância da área de trabalho de Meus Documentos é uma pasta virtual — um alias para o local do sistema de arquivos usado para armazenar fisicamente os documentos do usuário — localizada imediatamente abaixo da área de trabalho na hierarquia do namespace.

A finalidade das pastas Meus Documentos e Minhas Imagens é fornecer uma maneira simples e segura de os usuários acessarem seus arquivos de documentos e imagens em um sistema que possa ter vários usuários. Cada usuário recebe pastas separadas do sistema de arquivos para seus arquivos. Por exemplo, o local da pasta de documentos de um usuário no sistema de arquivos normalmente é algo como C:\Documents and Settings\username\My Documents. Não é necessário que os usuários saibam nada sobre o local físico de suas pastas do sistema de arquivos. Eles simplesmente acessam seus arquivos por meio do ícone Meus Documentos.

Observação

Meus Documentos permitem que um usuário acesse seus próprios arquivos, mas não os de qualquer outro usuário. Se vários indivíduos usarem o mesmo computador, um administrador poderá bloquear os usuários da parte do sistema de arquivos em que os arquivos reais são armazenados. Assim, os usuários poderão trabalhar em seus próprios documentos por meio da pasta Meus Documentos, mas não em documentos que pertençam a outros usuários.

 

Geralmente, não há necessidade de um aplicativo saber qual usuário está conectado ou onde está localizado a pasta Meus Documentos do usuário no sistema de arquivos. Em vez disso, seu aplicativo pode recuperar o PIDL do ícone da área de trabalho Meus Documentos chamando o método IShellFolder::P arseDisplayName da área de trabalho. O nome de análise usado para identificar a pasta Meus Documentos não é um caminho de arquivo, mas sim ::{450d8fba-ad25-11d0-98a8-0800361b1103}. A expressão entre colchetes é a forma de texto do GUID Meus Documentos. Por exemplo, para recuperar o PIDL de Meus Documentos, seu aplicativo deve usar essa chamada para IShellFolder::P arseDisplayName.

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

Depois que o aplicativo tiver o PIDL Meus Documentos, ele poderá manipular a pasta da mesma forma que faria com uma pasta normal do sistema de arquivos, enumerando itens, analisando, associando e executando quaisquer outras operações de pasta válidas. O Shell mapeia automaticamente as alterações em Meus Documentos ou suas subpastas para as pastas apropriadas do sistema de arquivos.

Se o aplicativo precisar de acesso à pasta do sistema de arquivos real que contém os documentos do usuário atual, passe CSIDL_PERSONAL para SHGetFolderLocation. A função retorna o PIDL da pasta do sistema de arquivos exibida na pasta Meus Documentos do usuário atual.

Arquivos Conectados

Os documentos HTML geralmente têm vários arquivos gráficos associados, um arquivo de folha de estilos, vários arquivos JScript da Microsoft (compatíveis com a especificação de linguagem ECMA 262 ) e assim por diante. Ao mover ou copiar o documento HTML primário, você também geralmente deseja mover ou copiar seus arquivos associados para evitar a quebra de links. Infelizmente, não houve nenhuma maneira fácil até agora de determinar quais arquivos estão relacionados a qualquer documento HTML específico além de analisar seu conteúdo. Para aliviar esse problema, o Windows 2000 fornece uma maneira simples de conectar um documento HTML primário ao grupo de arquivos associados. Se a conexão de arquivo estiver habilitada, quando o documento for movido ou copiado, todos os arquivos conectados o acompanharão.

Para criar um grupo de arquivos conectados, o documento primário deve ter uma extensão de nome de arquivo .htm ou .html. Crie uma subpasta da pasta pai do documento primário. O nome da subpasta deve ser o nome do documento primário, menos a extensão .htm ou .html, seguido por uma das extensões listadas abaixo. As extensões mais usadas são ".files" ou "_files". Por exemplo, se o documento primário for nomeado MyDoc.htm, nomear a subpasta "MyDoc_files" definirá a subpasta como o contêiner para os arquivos conectados do documento. Se o documento primário for movido ou copiado, a subpasta e seus arquivos também serão movidos ou copiados.

Para alguns idiomas, é possível usar um equivalente localizado de "_files" para criar uma subpasta para arquivos conectados. A tabela a seguir lista as cadeias de caracteres válidas que podem ser acrescentadas a um nome de documento para criar uma subpasta de arquivos conectados. Observe que algumas dessas cadeias de caracteres têm '-' como seu primeiro caractere em vez de '_' ou '.'.

"_archivos"

"_arquivos"

"_bestanden"

"_bylos"

"-Dateien"

"_datoteke"

"_dosyalar"

"_elemei"

"_failid"

"_fails"

"_fajlovi"

"_ficheiros"

"_fichiers"

"-filer"

".files"

"_files"

"_file"

"_fitxers"

"_fitxategiak"

"_pliki"

"_soubory"

"_tiedostot"

 

Observação

Esse recurso é sensível ao caso da extensão. Por exemplo, para o exemplo acima, uma subpasta chamada "MyDoc_Files" não será conectada a MyDoc.htm.

 

Se a conexão de arquivo está habilitada ou desabilitada é controlada por um valor REG_DWORD , NoFileFolderConnection, da chave do Registro a seguir.

HKEY_CURRENT_USER
   Software
      Microsoft
         Windows
            CurrentVersion
               Explorer

Normalmente, esse valor não é definido e a conexão de arquivo está habilitada. Se necessário, você pode desabilitar a conexão de arquivo adicionando esse valor à chave e definindo-a como 1. Para habilitar a conexão de arquivo novamente, defina NoFileFolderConnection como zero.

Observação

A conexão de arquivo normalmente deve ser habilitada porque outros aplicativos podem depender dela. Desabilite a conexão de arquivo somente se for absolutamente necessário.

 

Movendo, copiando, renomeando e excluindo arquivos

O namespace não é estático e os aplicativos geralmente precisam gerenciar o sistema de arquivos executando uma das operações a seguir.

  • Copiando um objeto para outra pasta.
  • Movendo um objeto para outra pasta.
  • Excluindo um objeto .
  • Renomeando um objeto .

Todas essas operações são executadas com SHFileOperation. Essa função usa um ou mais arquivos de origem e produz arquivos de destino correspondentes. No caso da operação de exclusão, o sistema tenta colocar os arquivos excluídos na Lixeira.

Também é possível mover arquivos usando a funcionalidade de arrastar e soltar .

Para usar a função, você deve preencher os membros de uma estrutura SHFILEOPSTRUCT e passá-la para SHFileOperation. Os principais membros da estrutura são pFrom e pTo.

O membro pFrom é uma cadeia de caracteres terminada em nulo duplo que contém um ou mais nomes de arquivo de origem. Esses nomes podem ser caminhos totalmente qualificados ou curingas padrão dos DOS, como *.*. Embora esse membro seja declarado como uma cadeia de caracteres terminada em nulo, ele é usado como um buffer para conter vários nomes de arquivo. Cada nome de arquivo deve ser encerrado pelo caractere NULL único usual. Um caractere NULL adicional deve ser acrescentado ao final do nome final para indicar o fim do pFrom.

O membro pTo é uma cadeia de caracteres terminada em nulo duplo, assim como pFrom. O membro pTo contém os nomes de um ou mais nomes de destino totalmente qualificados. Eles são empacotados em pTo da mesma forma que são para pFrom. Se pTo contiver vários nomes, você também deverá definir o sinalizador FOF_MULTIDESTFILES no membro fFlags . O uso de pTo depende da operação, conforme descrito aqui.

  • Para operações de cópia e movimentação, se todos os arquivos estiverem indo para um único diretório, pTo conterá o nome do diretório totalmente qualificado. Se os arquivos estiverem indo para destinos diferentes, pTo também poderá conter um diretório totalmente qualificado ou um nome de arquivo para cada arquivo de origem. Se um diretório não existir, o sistema o criará.
  • Para operações de renomeação, pTo contém um caminho totalmente qualificado para cada arquivo de origem no pFrom.
  • Para operações de exclusão, pTo não é usado.

Notificando o shell

Notifique o Shell da alteração depois de usar SHFileOperation para mover, copiar, renomear ou excluir arquivos ou depois de executar qualquer outra ação que afete o namespace. As ações que devem ser acompanhadas pela notificação incluem o seguinte:

  • Adicionar ou excluir arquivos ou pastas.
  • Mover, copiar ou renomear arquivos ou pastas.
  • Alterando uma associação de arquivo.
  • Alterando atributos de arquivo.
  • Adicionar ou remover unidades ou mídia de armazenamento.
  • Criar ou desabilitar uma pasta compartilhada.
  • Alterando a lista de imagens do sistema.

Um aplicativo notifica o Shell chamando SHChangeNotify com os detalhes do que mudou. Em seguida, o Shell pode atualizar sua imagem do namespace para refletir com precisão seu novo estado.

Exemplo simples de gerenciamento de arquivos com SHFileOperation

O aplicativo de console de exemplo a seguir ilustra o uso de SHFileOperation para copiar arquivos de um diretório para outro. Os diretórios de origem e destino, C:\My_Docs e C:\My_Docs2, são codificados no aplicativo para simplificar.

#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;
}

O aplicativo primeiro recupera um ponteiro para a interface IShellFolder da área de trabalho. Em seguida, ele recupera o PIDL do diretório de origem passando seu caminho totalmente qualificado para IShellFolder::P arseDisplayName. Observe que IShellFolder::P arseDisplayName requer que o caminho do diretório seja uma cadeia de caracteres Unicode. Em seguida, o aplicativo se associa ao diretório de origem e usa sua interface IShellFolder para recuperar a interface IEnumIDList de um objeto enumerador.

Como cada arquivo no diretório de origem é enumerado, IShellFolder::GetDisplayNameOf é usado para recuperar seu nome. O sinalizador SHGDN_FORPARSING é definido, o que faz com que IShellFolder::GetDisplayNameOf retorne o caminho totalmente qualificado do arquivo. Os caminhos de arquivo, incluindo os caracteres NULL de terminação, são concatenados em uma única matriz, szSourceFiles. Um segundo caractere NULL é acrescentado ao caminho final para encerrar a matriz corretamente.

Depois que a enumeração for concluída, o aplicativo atribuirá valores a uma estrutura SHFILEOPSTRUCT . Observe que a matriz atribuída a pTo para especificar o destino também deve ser encerrada por um NULL duplo. Nesse caso, ele é simplesmente incluído na cadeia de caracteres atribuída ao pTo. Como esse é um aplicativo de console, os sinalizadores FOF_SILENT, FOF_NOCONFIRMATION e FOF_NOCONFIRMMKDIR são definidos para suprimir as caixas de diálogo que possam aparecer. Depois que SHFileOperation retorna, SHChangeNotify é chamado para notificar o Shell da alteração. Em seguida, o aplicativo executa a limpeza usual e retorna.

Adicionar arquivos à lista de documentos recentes do Shell

O Shell mantém uma lista de documentos adicionados ou modificados recentemente para cada usuário. O usuário pode exibir uma lista de links para esses arquivos clicando em Documentos no menu Iniciar. Assim como acontece com Meus Documentos, cada usuário tem um diretório do sistema de arquivos para manter os links reais. Para recuperar o PIDL do diretório Recente do usuário atual, seu aplicativo pode chamar SHGetFolderLocation com CSIDL_RECENT ou chamar SHGetFolderPath para recuperar seu caminho.

Seu aplicativo pode enumerar o conteúdo da pasta Recente usando as técnicas discutidas anteriormente neste documento. No entanto, um aplicativo não deve modificar o conteúdo da pasta como se fosse uma pasta normal do sistema de arquivos. Se isso acontecer, a lista de documentos recentes do Shell não será atualizada corretamente e as alterações não serão refletidas no menu Iniciar. Em vez disso, para adicionar um link de documento à pasta Recente de um usuário, seu aplicativo pode chamar SHAddToRecentDocs. O Shell adicionará um link à pasta do sistema de arquivos apropriada, bem como atualizará sua lista de documentos recentes e o menu Iniciar. Você também pode usar essa função para limpar a pasta.