quarta-feira, 24 de junho de 2009

Como ler os detalhes de um arquivo?

Bom dia pessoal, tudo bem?
O Windows oferece um recurso que eu gosto bastante, que é a possibilidade de adicionar informações extras sobre um arquivo, como mostra a figura 01.



(figura 01)

Mas e se você quiser criar uma aplicação em C# para ler essas informações, o que deve fazer? Se você pensou no namespace System.IO (com eu), vai quebrar a cara. Pelo menos eu não consegui ver uma maneira de conseguir ler essas informações usando os recursos do BCL.

Depois de pesquisar sobre o assunto, eu tinha duas abordagens para resolver meu problema, usar o shell32.dll ou dsofile.dll (DLL disponível para download – “OLE File Property Reader”). Como o shell32.dll vem junto com o sistema operacional (meu palpite), resolvi utilizá-lo mesmo tendo uma interface menos agradável que o dsofile.dll.

Como inicialmente eu não sabia que o nome da DLL era Shell32.dll, somente sabia que deveria utilizar a classe “Shell.Application”, eu tinha que descobrir o local da DLL. Então fui dar aquela tradicional navegada no registro do Windows.
> “HKEY_Classes_Root” > “Shell.Application” > CLSID = (figura 02)



(figura 02)

> “HKEY_Classes_Root” > “CLSID” > “{13709620-C279-11CE-A49E-444553540000}” > InProcServer32 > default = “%SystemRoot%\system32\shell32.dll” (figura 03).



(figura 03)

Confirmado o caminho da DLL, adicionei uma referência COM ao meu projeto, chamada “Microsoft Shell Controls e Automation” (foi mais fácil buscar pelo path). Aí foi só codificar o código abaixo (simplificado, claro!).

1 string caminhoArquivo = @"E:\Temp\01 Rehab.mp3";

2 Shell32.Shell objS = new Shell32.ShellClass();

3 Shell32.Folder pasta = objS.NameSpace(Path.GetDirectoryName(caminhoArquivo));

4

5 if (pasta != null)

6 {

7 Shell32.FolderItem arquivo = pasta.ParseName(Path.GetFileName(caminhoArquivo));

8

9 // No Windows Vista 268 é o número total de propriedades existentes.

10 for (int i = 0; i < 268; i++)

11 {

12 if (pasta.GetDetailsOf(arquivo, i) != "")

13 listBox1.Items.Add(pasta.GetDetailsOf(null, i) + " = " +

14 pasta.GetDetailsOf(arquivo, i));

15 }

16 }


No início eu fiquei estudando as propriedades por posição, mas depois descobri que passando null para o “GetDetailsOf” o nome da propriedade é retornado, claro que leva em conta o idioma do seu sistema operacional.
Sinceramente eu esperava ver isso na BCL do .NET, mas realmente não encontrei. Se alguém souber de outra maneira, compartilhe.

Para não perder o costume deixo aqui uma pergunta.
E se você quisesse criar uma forma de ter, para diferentes tipos de arquivo, uma lista com as propriedades que irá recuperar e com um nome diferente do retornado pelo GetDetailsOf? Por exemplo: MP3 – propriedades 4, 5, 10, 14, 15 e 16, WMV – propriedades 4, 5, 100, 105, 120 e 130. Como você implementaria esse código? Uma solução é encher o seu código de IFs, mas não é nada elegante...

O PDF e o projeto com o código acima estão aqui.



Até um próximo post!

[]s
Luciano Caixeta Moreira - {Luti}
Chief Innovation Officer
Sr. Nimbus Serviços em Tecnologia Ltda
E-mail: luciano.moreira@srnimbus.com.br

Um comentário: