2009-06-24 63 views
6

是否有方法使用Perl腳本更改Windows文件夾圖標?是否有方法使用Perl腳本更改Windows文件夾圖標?

我的意圖是將「xxx_documents」文件夾的普通圖標更改爲其他圖標。我必須以這樣的方式運行腳本,以便照顧整個驅動器。

驅動器包含許多文件夾。我必須搜索名爲「文檔」的每個文件夾(例如「xxx_documents」或簡單地「文檔」),並將其圖標從"%SystemRoot%\system32\SHELL32.dll"庫中更改爲一個。

Perl中可能嗎?感謝所有幫助我的人。

回答

8

你確實可以用Perl來做到這一點。 Windows通過使用每個文件夾中的隱藏系統Dekstop.ini文件來控制目錄圖標。內容看起來是這樣的:

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

在Windows XP(我假設在其他系統),圖標41是一棵樹。 Windows需要此文件中明確設置爲系統文件爲它工作,這意味着我們需要挖成Win32API::File來創建它:

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

如果你運行上面的代碼,它應該設置當前目錄的圖標轉換爲樹狀圖。您可能需要在資源管理器提取更改之前刷新您的目錄列表。

現在我們有了一種方法來更改圖標,現在我們可以遍歷整個驅動器並更改與我們的模式相匹配的每個文件夾。我們可以File::Find,或者其替代品之一(例如,File::Find::Rule,或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(); 
} 

不幸的是,我剛剛發現圖標只有如果該目錄目前已得到改變,或者曾經有過一個圖標......顯然有一個屬性被設置在目錄本身上,導致Windows查找Desktop.ini文件,但是我不知道它是什麼。因此,上述解決方案是不完整的;我們還需要查找並修復添加圖標的目錄中的屬性。

保羅

+3

根據http://msdn.microsoft.com/en-us/library/cc144102.aspx,您還需要在包含文件夾中設置系統屬性。 – ephemient 2009-06-24 19:08:02

0

爲了讓圖標刷新,你將不得不調用一些SHChangeNotify巫毒(C++的例子,但你的想法):

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 
相關問題