I use FilePathDialog.SelectedPath get folder's path I also know icon's path but i don't know how to set that folder's icon
It seems important to set some file attributes.
Based on https://github.com/dimuththarindu/FIC-Folder-Icon-Changer here is the slimmed down version.
Within the folder, whose attribute you want to set, create three files:
MyIcon.ico
The icon you want to display. You may use a different file name.
desktop.ini - Containing the below text
[.ShellClassInfo]
IconResource=MyIcon.ico,0
[ViewState]
Mode=
Vid=
FolderType=Generic
.hidden- Containing the below text
desktop.ini
MyIcon.ico
File types in my case were UTF-8 with BOM.
Then you need to set attributes for all three files to
hidden
readonly
Finally, you need to notify the system that a change occurred
SHChangeNotify(0x08000000, 0x0000, (IntPtr)null, (IntPtr)null);
Assuming you created a Visual Studio solution with a folder named Resources holding your three files, here's the code to set the icon:
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace SetFolderIcon
{
class Program
{
[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern void SHChangeNotify(
int wEventId, int uFlags, IntPtr dwItem1, IntPtr dwItem2);
static void Main(string[] args)
{
string location = $"C:\\Users\\Balint\\Desktop";
string folderPath = Path.Combine(location, "My Folder");
string desktopIniPath = Path.Combine(folderPath, "desktop.ini");
string iconPath = Path.Combine(folderPath, "MyIcon.ico");
string hiddenPath = Path.Combine(folderPath, ".hidden");
Directory.CreateDirectory(folderPath);
File.Copy($"Resources\\desktop.ini", desktopIniPath);
File.Copy($"Resources\\Klinng.ico", iconPath);
File.Copy($"Resources\\.hidden", hiddenPath);
File.SetAttributes(desktopIniPath,
File.GetAttributes(desktopIniPath)
| FileAttributes.Hidden
| FileAttributes.ReadOnly);
File.SetAttributes(iconPath,
File.GetAttributes(iconPath)
| FileAttributes.Hidden
| FileAttributes.ReadOnly);
File.SetAttributes(hiddenPath,
File.GetAttributes(hiddenPath)
| FileAttributes.Hidden
| FileAttributes.ReadOnly);
File.SetAttributes(folderPath,
File.GetAttributes(folderPath)
| FileAttributes.ReadOnly);
SHChangeNotify(0x08000000, 0x0000, (IntPtr)null, (IntPtr)null);
}
}
}
You have to write the desktop.ini
file.
[.ShellClassInfo]
IconResource=Icon.ico,0
IconFile=Icon.ico
IconIndex=0
[ViewState]
Mode=
Vid=
FolderType=Pictures
C# code
string dir = "Folder Path";
string[] lines = { "[.ShellClassInfo]", "IconResource=Icon.ico,0", "[ViewState]", "Mode=", "Vid=", "FolderType=Pictures" };
File.WriteAllLines(dir + @"\desktop.ini", lines);
IconResource: {Icon Path},0
FolderTypes: Generic
, Documents
, Pictures
, Music
, Videos
If you need more information, check this GitHub project: https://github.com/FIC-Folder-Icon-Changer
There is a GitHub project Vanara, which wraps Windows P/Invoke Methods in very nice and well maintained nuget packages.
For your purpose I would suggest Vanara.PInvoke.Shell32.
I tested it in Visual Studio 2022 with .NET 8 with nuget Vanara.PInvoke.Shell32 v3.4.17 with a Command Line tool.
using Vanara.PInvoke;
using static Vanara.PInvoke.Shell32;
SetIconToFolder(@"C:\my folder", @"C:\my folder\my icon.ico");
static void SetIconToFolder(string folder, string? fullFilenameToIcon = null)
{
if (string.IsNullOrWhiteSpace(fullFilenameToIcon)) return;
HRESULT result;
SHFOLDERCUSTOMSETTINGS folderSettings = default;
result = Shell32.SHGetSetFolderCustomSettings(ref folderSettings, folder, FCS.FCS_READ);
if (result == HRESULT.S_OK)
{
folderSettings.dwMask = FOLDERCUSTOMSETTINGSMASK.FCSM_ICONFILE;
folderSettings.pszIconFile = fullFilenameToIcon;
result = Shell32.SHGetSetFolderCustomSettings(ref folderSettings, folder, FCS.FCS_WRITE);
if (result != HRESULT.S_OK)
{
throw new Exception($"Error with {result}");
}
}
}
Important: Don't forget to set
folderSettings.dwMask = FOLDERCUSTOMSETTINGSMASK.FCSM_ICONFILE;
:-) This took me a while to figure that missing value out,
I was trying to use, also this notation "shell32.dll,-44" to get a yellow star from the Windows Icons, but I failed. Just as an info for you.
...
- folderSettings.pszIconFile = fullFilenameToIcon;
+ folderSettings.pszIconFile = "shell32.dll";
+ folderSettings.iIconIndex = -44; // 44;
...
There are basically two steps involved in assigning an icon to a folder (or possibly three steps, if you count creating the folder):
Create a desktop.ini file inside the folder for which to create the icon (the "Target Folder"). Set the Target Folder's attribute to "System".
more :
If you want the folder icon to change immediately, every time (and of course you do), you need to add a "zero width" space to the folder name too. This will trigger an instant refresh of the folder. You can do this like this:
string tempFolderPath = folderPath + "\u200B";
Directory.Move(folderPath, tempFolderPath);
© 2022 - 2024 — McMap. All rights reserved.