Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there is a way to change a Windows folder icon using a Perl script?

Is there is a way to change a Windows folder icon using a Perl script?

My intention is to change the ordinary icon of the "xxx_documents" folder to some other icon. I have to run the script in such a way that it takes care for the whole drive.

The drive contains many folders. I have to search for each folder named "documents" (e.g. "xxx_documents" or simply "documents") and change its icon to one from the "%SystemRoot%\system32\SHELL32.dll" library.

Is that possible in Perl? Thanks to all who help me with this.

like image 961
User1611 Avatar asked Jun 24 '09 07:06

User1611


People also ask

How do I change a folder icon step by step?

Step 1: Right-click on a folder you want to customize and select "Properties." Step 2: In the "Customize" tab, go to the "Folder icons" section and click the "Change Icon" button. Step 3: Choose one of the many icons listed in the box then click OK. These icons are located in C:\Windows\system32\SHELL32.

How do I change the icon for multiple folders?

Hi, You cannot change the multiple folder icons by changing the properties of the folders. You may need third party application. Use your favorite search engine to search for the third party software that will help you change the multiple folder icons at a time.

How do I change my folder icon to star?

First, right-click the folder you want to change to a different icon and select Properties. The folder Properties window comes up. Click the Customize tab, then Change Icon. Now select a default icon that's included in Windows if you find one that you like.


2 Answers

You sure can do it with Perl. Windows controls directory icons by use of a hidden systemDekstop.ini file in each folder. The contents looks something like this:

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

On Windows XP (and I assume on other systems), icon 41 is a tree. Windows requires this file be explicitly set as a system file for it to work, this means we'll need to dig down into Win32API::File to create it:

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

If you run the code above, it should set the icon for the current directory to a tree. You may need to refresh your directory listing before explorer picks up the change.

Now that we have a way to change icons, we can now just walk through a whole drive and change every folder that matches our pattern. We can do this pretty easily with File::Find, or one of its alternatives (eg, File::Find::Rule, or 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();
 }

Unfortunately, I've just discovered that the icon only gets changed if the directory currently has, or once had, an icon... There's clearly an attribute that's being set on the directory itself that causes Windows to look for a Desktop.ini file, but I can't for the life of me figure out what it is. As such, the above solution is incomplete; we also need to find and fix the attributes on the directory where we're adding the icon.

Paul

like image 188
pjf Avatar answered Oct 06 '22 01:10

pjf


1.

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

2.

[.ShellClassInfo]
LocalizedResourceName=@%SystemRoot%\system32\shell32.dll,-21803
InfoTip=@%SystemRoot%\system32\shell32.dll,-12689
IconResource=%SystemRoot%\system32\imageres.dll,-3
like image 24
Juan Avatar answered Oct 06 '22 02:10

Juan