2009-06-24 4 views
6

Gibt es eine Möglichkeit, ein Windows-Ordnersymbol mit einem Perl-Skript zu ändern?Gibt es eine Möglichkeit, ein Windows-Ordnersymbol mithilfe eines Perl-Skripts zu ändern?

Meine Absicht ist es, das gewöhnliche Symbol des Ordners "xxx_documents" in ein anderes Symbol zu ändern. Ich muss das Skript so ausführen, dass es sich um das ganze Laufwerk kümmert.

Das Laufwerk enthält viele Ordner. Ich muss nach jedem Ordner mit dem Namen "Dokumente" (z. B. "xxx_documents" oder einfach "Dokumente") suchen und sein Symbol zu einem aus der "%SystemRoot%\system32\SHELL32.dll"-Bibliothek ändern.

Ist das in Perl möglich? Danke an alle, die mir dabei helfen.

Antwort

8

Sie können es sicher mit Perl machen. Windows steuert Verzeichnissymbole mithilfe einer versteckten Systemdatei Dekstop.ini in jedem Ordner. Der Inhalt sieht ungefähr so ​​aus:

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

Unter Windows XP (und ich nehme an, auf anderen Systemen), Symbol 41 ist ein Baum. Windows benötigt diese Datei explizit als System Datei eingestellt werden, für sie zu arbeiten, dies bedeutet, dass wir nach unten in Win32API::File graben müssen, um es zu schaffen:

#!/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(); 

Wenn Sie den Code oben ausgeführt, sollte es eingestellt das Symbol für das aktuelle Verzeichnis zu einem Baum. Möglicherweise müssen Sie Ihre Verzeichnisliste aktualisieren, bevor der Explorer die Änderung übernimmt.

Jetzt, da wir eine Möglichkeit haben, Icons zu ändern, können wir jetzt einfach durch ein ganzes Laufwerk gehen und jeden Ordner ändern, der unserem Muster entspricht. Wir können dies tun, ziemlich leicht mit File::Find, oder einem seiner Alternativen (zB File::Find::Rule oder 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(); 
} 

Leider habe ich gerade entdeckt, dass das Symbol nur geändert wird, wenn das Verzeichnis hat derzeit , oder einmal, ein Icon ... Es gibt eindeutig ein Attribut, das auf dem Verzeichnis selbst gesetzt wird, das Windows veranlasst, nach einer Desktop.ini Datei zu suchen, aber ich kann nicht für das Leben von mir herauszufinden, was es ist. Als solche ist die obige Lösung unvollständig; Außerdem müssen wir die Attribute in dem Verzeichnis suchen und korrigieren, in dem wir das Symbol hinzufügen.

Paul

+3

Nach http://msdn.microsoft.com/en-us/library/cc144102.aspx müssen Sie auch das Systemattribut für den enthaltenden Ordner festlegen. – ephemient

+0

http://www.google.com/search?btnI=&q=%22Kundenanpassung+mit+Desktop.ini%22 –

0

Um das Symbol zu erhalten zu aktualisieren, werden Sie einige SHChangeNotify Voodoo aufrufen müssen (C++ Beispiel, aber Sie erhalten die Idee):

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 
Verwandte Themen