質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

Windowsのエクスプローラー上のフォルダアイコンのサムネイルの変更方法(できればPythonで)

shiki980
shiki980

総合スコア1

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1回答

1グッド

1クリップ

438閲覧

投稿2022/10/23 15:15

前提

Windowsのエクスプローラーで表示されるフォルダ内のサムネイルを、Pythonを使って変更したいのですが、方法が分からないため教えていただきたいです。
(Windowsのエクスプローラーで、特大アイコン表示をすると以下のようにフォルダ内の画像がサムネイルとして表示されますが、画像が複数枚ある時にはランダムで画像が選択されるため、Pythonを使ってこの画像を指定したいです。)
イメージ説明

フォルダのプロパティからも手動で画像を指定できるのですが、指定したいフォルダの数が大量にあり、機械的に処理したいと思っています。
Python指定なのは私がPythonしか使えないためです。
ただ、他の言語等で解決策がある場合、そちらでもよいので教えていただけると幸いです。

調べたことなど

以下の、SHFOLDERCUSTOMSETTINGS構造体に含まれるpszLogoが、フォルダのサムネイル画像を指しているのだと思い、これを変更しようと試みました。
https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-shfoldercustomsettings

以下のコードを参考にして、pszLogoを書き換えるようなコードを書いて実行してみましたが、サムネイルは変化しませんでした。
https://stackoverflow.com/questions/4662759/how-to-change-folder-icons-with-python-on-windows
(上記コードはサムネイルではなくアイコン自体を書き換える処理です。一応、上記を実行するとアイコンの書き換えはできました)

実行したソースコード

python3

1import os 2import ctypes 3from ctypes import POINTER, Structure, c_wchar, c_int, sizeof, byref 4from ctypes.wintypes import BYTE, WORD, DWORD, LPWSTR, LPSTR 5import win32api 6 7HICON = c_int 8LPTSTR = LPWSTR 9TCHAR = c_wchar 10MAX_PATH = 260 11FCS_READ = 0x00000001 12FCSM_LOGO = 0x00000020 13FCSM_ICONFILE = 0x00000010 14FCS_FORCEWRITE = 0x00000002 15SHGFI_ICONLOCATION = 0x000001000 16 17class GUID(Structure): 18 _fields_ = [ 19 ('Data1', DWORD), 20 ('Data2', WORD), 21 ('Data3', WORD), 22 ('Data4', BYTE * 8)] 23 24class SHFOLDERCUSTOMSETTINGS(Structure): 25 _fields_ = [ 26 ('dwSize', DWORD), 27 ('dwMask', DWORD), 28 ('pvid', POINTER(GUID)), 29 ('pszWebViewTemplate', LPTSTR), 30 ('cchWebViewTemplate', DWORD), 31 ('pszWebViewTemplateVersion', LPTSTR), 32 ('pszInfoTip', LPTSTR), 33 ('cchInfoTip', DWORD), 34 ('pclsid', POINTER(GUID)), 35 ('dwFlags', DWORD), 36 ('pszIconFile', LPTSTR), 37 ('cchIconFile', DWORD), 38 ('iIconIndex', c_int), 39 ('pszLogo', LPTSTR), 40 ('cchLogo', DWORD)] 41 42class SHFILEINFO(Structure): 43 _fields_ = [ 44 ('hIcon', HICON), 45 ('iIcon', c_int), 46 ('dwAttributes', DWORD), 47 ('szDisplayName', TCHAR * MAX_PATH), 48 ('szTypeName', TCHAR * 80)] 49 50def setthumbnail(folderpath, thumbnailpath): 51 52 shell32 = ctypes.windll.shell32 53 54 folderpath = str(os.path.abspath(folderpath)) 55 thumbnailpath = str(os.path.abspath(thumbnailpath)) 56 57 fcs = SHFOLDERCUSTOMSETTINGS() 58 fcs.dwSize = sizeof(fcs) 59 fcs.dwMask = FCSM_LOGO 60 fcs.pszLogo = thumbnailpath 61 fcs.cchLogo = 0 62 63 hr = shell32.SHGetSetFolderCustomSettings(byref(fcs), folderpath, 64 FCS_FORCEWRITE) 65 66 if hr: 67 raise WindowsError(win32api.FormatMessage(hr)) 68 69 sfi = SHFILEINFO() 70 hr = shell32.SHGetFileInfoW(folderpath, 0, byref(sfi), sizeof(sfi), 71 SHGFI_ICONLOCATION) 72 if hr == 0: 73 raise WindowsError(win32api.FormatMessage(hr)) 74 75 index = shell32.Shell_GetCachedImageIndexW(sfi.szDisplayName, sfi.iIcon, 0) 76 if index == -1: 77 raise WindowsError() 78 79 shell32.SHUpdateImageW(sfi.szDisplayName, sfi.iIcon, 0, index) 80 81setthumbnail({対象フォルダのパス}, {.pngのパス})

setthumbnailで、icoファイルはbmpファイルを指定しても変化はありませんでした。

どなたかわかる方がいらっしゃいましたらご教示お願い致します。

teamikl👍を押しています

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

3

ベストアンサー

私の環境では win10/python3.10 で、WindowsError が出ますが、設定自体は正常に変更できました。
(追記: SHGetSetFolderCustomSettings 迄で変更可能だったので、関数内の後半は不要です)

イメージ説明

隠しファイルを表示する設定にして、対象フォルダ内のdesktop.ini ファイルの中身を確認してみてください。

Desktop.iniを使用してフォルダーをカスタマイズする方法

  • PathMakeSystemFolder (attrib +s FolderName コマンド) で
    対象フォルダをシステムフォルダに変更 (desktop.ini によるカスタマイズを有効にする)
  • desktop.ini を配置
  • エクスプローラー(explorer.exe) を再起動。キャッシュが影響しないように 設定変更を反映させるため再読込。

 追記: SHChangeNotify により設定変更を通知

フォルダプロパティのカスタマイズから変更した場合
フォルダー内の desktop.ini の [ViewState] セクション内の Logo に記録されます。
上記のスクリプトを用いた場合は [.ShellClassInfo] セクションの Logo に記録されます。

カスタマイズから変更した場合や、上記のスクリプト(win32 API)で変更した場合は即時反映されますが
desktop.ini ファイルをエディタで直接編集や、プログラムで直接編集した場合は即時反映されないようです。
(訂正: 恐らくキャッシュなどの影響 変更した設定は再読み込みまで反映されない)

追記: 設定の反映方法について、SHChangeNotify により通知できるようです。folderikonより、ctypesを用いた呼び出し例
https://github.com/demberto/FolderIkon/blob/master/folderikon/notify_shell.py


尚、できれば Python でとのことですが、ファイルを直接編集するコードの場合は
desktop.ini は 標準ライブラリの configparser モジュールにより扱うことができます。
より簡潔で解りやすいコードにできるはずです。

※ サムネイルではなくアイコンですが、desktop.ini を configparser で操作するコードの参考に。


ctypes でwin32 API を使う方法(質問に掲載のコードの方法) は、
同様のコードを書く場合は C言語で書いたほうが短くかけます。
(ctypes で扱う場合は、構造体館の宣言が必要ですが、C言語では必要なヘッダを読み込むのみ)

C言語と言うと、巨大な開発環境のインストールが必要そうに思われるかもしれませんが、
これくらいの規模のユーティリティーであれば、tcc (Tiny C Compiler) がお勧めです。
C 言語の学習コストがあるかもしれませんが、C言語で行う必要があるのは API 呼び出し部分のみなので
Python でフォルダーの一覧のループ処理をして、path 情報のみを C言語で作ったプログラムへ subprocess.call 等で渡す
といった使い方であれば、学習コストを必要最低限に抑えることができます。

投稿2022/10/24 03:41

編集2022/10/24 06:49
teamikl

総合スコア8566

sigefuji😄を押しています
spoofy_dragon, shiki980を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

shiki980

2022/10/26 12:46

反応が遅くなり申し訳ありません。 大変ご丁寧な回答、ありがとうございます。 SHGetSetFolderCustomSettingsはdesktop.iniを作成、編集していたんですね。 色々試した結果私の環境ではなぜか画像のパスに日本語や環境変数が含まれていると変更が反映されないようで、 それらを含まない相対パスを入力にするとスクリプト実行直後にサムネイルを変更することができました(元々絶対パスしか試していませんでした)。 結局Pythonによるiniファイルの修正作業等は不要でしたが、色々と詳しく補足情報も書いていただき、大変ありがとうございました。 また、今後win32 APIを使う機会があった場合、C言語での実装も検討してみたいと思います。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。