2009-06-24 9 views
6

Czy istnieje sposób zmiany ikony folderu Windows za pomocą skryptu Perla?Czy istnieje sposób zmiany ikony folderu Windows za pomocą skryptu Perla?

Moim zamiarem jest zmiana zwykłej ikony folderu "xxx_documents" na inną ikonę. Muszę uruchomić skrypt w taki sposób, aby dbał o cały dysk.

Dysk zawiera wiele folderów. Muszę wyszukać każdy folder o nazwie "dokumenty" (np. "Xxx_documents" lub po prostu "dokumenty") i zmienić jego ikonę na jedną z biblioteki "%SystemRoot%\system32\SHELL32.dll".

Czy to możliwe w Perlu? Dziękuję wszystkim, którzy mi w tym pomagają.

Odpowiedz

8

Na pewno można to zrobić za pomocą Perla. Windows kontroluje ikony katalogów za pomocą ukrytego pliku systemu Dekstop.ini w każdym folderze. Zawartość wygląda mniej więcej tak:

[.ShellClassInfo] 
IconFile=%SystemRoot%\system32\SHELL32.dll 
IconIndex=41 

W systemie Windows XP (i zakładam, że w innych systemach) ikona 41 jest drzewem. Windows wymaga tego pliku można jawnie ustawić jako system pliku do jego pracy, to znaczy musimy wykopać dół pod Win32API::File aby go utworzyć:

#!/usr/bin/perl 
use strict; 
use warnings; 

use Win32API::File qw(createFile WriteFile fileLastError CloseHandle); 

my $file = createFile(
     'Desktop.ini', 
     { 
      Access  => 'w',  # Write access 
      Attributes => 'hs',  # Hidden system file 
      Create  => 'tc',  # Truncate/create 
     } 
) or die "Can't create Desktop.ini - " . fileLastError(); 

WriteFile(
     $file, 
     "[.ShellClassInfo]\r\n" . 
     "IconFile=%SystemRoot%\\system32\\SHELL32.dll\r\n" . 
     "IconIndex=41\r\n", 
     0, [], [] 
) or die "Can't write Desktop.ini - " . fileLastError(); 

CloseHandle($file) or die "Can't close Desktop.ini - " . fileLastError(); 

Po uruchomieniu powyższy kod, należy ustawić ikonę bieżącego katalogu do drzewa. Może być konieczne odświeżenie spisu katalogów, zanim odkrywca podejmie zmianę.

Teraz, gdy mamy sposób na zmianę ikon, możemy teraz po prostu przejść przez cały dysk i zmienić każdy folder, który pasuje do naszego wzorca. Możemy to zrobić dość łatwo File::Find, lub jednego z jego alternatyw (np File::Find::Rule lub File::Next):

#!/usr/bin/perl 
use strict; 
use warnings; 
use File::Find qw(find); 
use Win32API::File qw(createFile WriteFile fileLastError CloseHandle); 

my $topdir = $ARGV[0] or die "Usage: $0 path\n"; 

find(\&changeIcon, $topdir); 

sub changeIcon { 
    return if not /documents$/i; # Skip non-documents folders 
    return if not -d;    # Skip non-directories. 

    my $file = createFile(
     "$_\\Desktop.ini", 
     { 
       Access  => 'w',  # Write access 
       Attributes => 'hs',  # Hidden system file 
       Create  => 'tc',  # Truncate/create 
     } 
    ) or die "Can't create Desktop.ini - " . fileLastError(); 

    WriteFile(
     $file, 
     "[.ShellClassInfo]\r\n" . 
     "IconFile=%SystemRoot%\\system32\\SHELL32.dll\r\n" . 
     "IconIndex=41\r\n", 
     0, [], [] 
    ) or die "Can't write Desktop.ini - " . fileLastError(); 

    CloseHandle($file) or die "Can't close Desktop.ini - " . fileLastError(); 
} 

Niestety, właśnie odkryli, że ikona tylko ulega zmianie, jeśli katalog ma obecnie lub raz, ikona ... Jest oczywiste, że atrybut, który jest ustawiony na samym katalogu, powoduje, że system Windows szuka pliku Desktop.ini, ale nie mogę do końca życia dowiedzieć się, co to jest. Jako takie, powyższe rozwiązanie jest niekompletne; musimy również znaleźć i naprawić atrybuty w katalogu, w którym dodajemy ikonę.

Paul

+3

Zgodnie z http://msdn.microsoft.com/en-us/library/cc144102.aspx należy również ustawić atrybut systemowy w folderze zawierającym. – ephemient

+0

http://www.google.com/search?btnI=&q=%22Dostosowywanie + folderów z +Desktop.ini%22 –

0

Aby uzyskać ikonę, aby odświeżyć, trzeba będzie powołać jakieś voodoo SHChangeNotify (C++ przykład, ale masz pomysł):

int imageIndex = Shell_GetCachedImageIndexW(wPath, GetSyncFolderIconIndex(), 0); 
if (imageIndex != -1) 
{ 
    // If we don't do this, and we EVER change our icon, Explorer will likely keep 
    // using the old one that it's already got in the system cache. 
    SHChangeNotify(SHCNE_UPDATEIMAGE, SHCNF_DWORD | SHCNF_FLUSHNOWAIT, &imageIndex, NULL); 
} 
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATHW | SHCNF_FLUSHNOWAIT, wPath, NULL); 
2

1.

[.ShellClassInfo] 
[email protected]%SystemRoot%\system32\shell32.dll,-21790 
[email protected]%SystemRoot%\system32\shell32.dll,-12689 
IconResource=%SystemRoot%\system32\imageres.dll,-108 
IconFile=%SystemRoot%\system32\shell32.dll 
IconIndex=-237 

2.

[.ShellClassInfo] 
[email protected]%SystemRoot%\system32\shell32.dll,-21803 
[email protected]%SystemRoot%\system32\shell32.dll,-12689 
IconResource=%SystemRoot%\system32\imageres.dll,-3 
Powiązane problemy