Last active
November 29, 2024 07:54
-
-
Save uemuraj/4ef91ec039da85c0db88a493578a301d to your computer and use it in GitHub Desktop.
エクスプローラーの「PC」に表示されるアイコンを選択します
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
エクスプローラーの「PC」に表示されるアイコンを選択します | |
.DESCRIPTION | |
以下のキーを使って操作します。 | |
[ENTER] ... 選択結果をレジストリへ書き込んで終了します。選択は、サインアウト後に有効になります。 | |
[SPACE] ... 各項目を On/Off できます。 | |
[UP][DOWN] ... 項目間を移動できます。 | |
[ESC] ... 何もせず終了します。 | |
#> | |
using namespace System.Management.Automation.Host | |
function SetBufferContent([Coordinates] $pos, [char] $char) { | |
$cell = $Host.UI.RawUI.NewBufferCellArray($char, $Host.UI.RawUI.ForegroundColor, $Host.UI.RawUI.BackgroundColor) | |
$Host.UI.RawUI.SetBufferContents($pos, $cell) | |
} | |
class CheckBox { | |
[bool] $checked | |
[Coordinates] $pos | |
CheckBox([int] $x, [int] $y, [bool] $checked) { | |
$this.pos = [Coordinates]::new($x, $y) | |
$this.checked = $checked | |
$this.Mark() | |
} | |
[void] Flip() { | |
$this.checked = -not $this.checked | |
$this.Mark() | |
} | |
[void] hidden Mark() { | |
if ($this.checked) { | |
SetBufferContent $this.pos '*' | |
} | |
else { | |
SetBufferContent $this.pos ' ' | |
} | |
} | |
} | |
function MultiSelection([ScriptBlock] $Initial, [ScriptBlock] $Selected, [ScriptBlock] $Unselected) { | |
<# | |
.SYNOPSIS | |
テキストベースの複数選択メニューを表示します | |
.PARAMETER Initial | |
アイテムの初期状態を返すスクリプトブロック。 True を返すと、メニューには選択済として表示されます。 | |
.PARAMETER Selected | |
終了時、アイテムが選択済だった場合に呼び出されるスクリプトブロック。 [ESC] で終了した場合は呼び出されません。 | |
.PARAMETER Unselected | |
終了時、アイテムが非選択だった場合に呼び出されるスクリプトブロック。 [ESC] で終了した場合は呼び出されません。 | |
#> | |
$objects = @($input) | |
$objects | ForEach-Object { Write-Host -NoNewline " [ ] "; Write-Host $_ } | |
$pos = $Host.UI.RawUI.CursorPosition | |
$count = $objects.Count | |
$items = $objects | ForEach-Object { [CheckBox]::new($pos.X + 2, $pos.Y - $count--, (& $Initial)) } | |
$index = 0 | |
$Host.UI.RawUI.CursorPosition = $items[$index].pos | |
try { | |
while ($true) { | |
$key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') | |
if ([System.ConsoleKey]::Enter -eq $key.VirtualKeyCode) { | |
break | |
} | |
if ([System.ConsoleKey]::Escape -eq $key.VirtualKeyCode) { | |
return | |
} | |
if ([System.ConsoleKey]::Spacebar -eq $key.VirtualKeyCode) { | |
$items[$index].Flip() | |
continue | |
} | |
if ([System.ConsoleKey]::DownArrow -eq $key.VirtualKeyCode) { | |
$index++ | |
if ($index -eq $items.Count) { | |
$index = 0 | |
} | |
$Host.UI.RawUI.CursorPosition = $items[$index].pos | |
continue | |
} | |
if ([System.ConsoleKey]::UpArrow -eq $key.VirtualKeyCode) { | |
$index-- | |
if ($index -lt 0) { | |
$index = 0 | |
} | |
$Host.UI.RawUI.CursorPosition = $items[$index].pos | |
continue | |
} | |
} | |
} | |
finally { | |
$Host.UI.RawUI.CursorPosition = $pos | |
} | |
$index = 0 | |
$objects | ForEach-Object { if ($items[$index++].checked) { & $Selected } else { & $Unselected } } | |
} | |
enum Policy { | |
Show = $true | |
Hide = $false | |
} | |
class FolderDescription { | |
[bool] static $dirty | |
[string] $path | |
[string] $desc | |
[Policy] $policy | |
FolderDescription([string]$guid, [string]$desc) { | |
$this.path = 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\' + $guid + '\PropertyBag' | |
$this.desc = $desc | |
$prop = Get-ItemProperty -Path $this.path -Name 'ThisPCPolicy' -ErrorAction SilentlyContinue | |
if ($prop -ne $null) { | |
$this.policy = $prop.ThisPCPolicy | |
} | |
else { | |
$this.policy = [Policy]::Show | |
} | |
} | |
[string] ToString() { | |
return $this.desc | |
} | |
[void] SetPolicy([Policy]$policy) { | |
if ($this.policy -ne $policy) { | |
if (!(Test-Path $this.path)) { | |
New-Item $this.path -Force | |
} | |
Set-ItemProperty -Path $this.path -Name 'ThisPCPolicy' -Value $policy | |
$this.policy = $policy | |
[FolderDescription]::dirty = $true | |
} | |
# Write-Host "$([FolderDescription]::dirty) $($this.policy) $($this.desc)" | |
} | |
} | |
$icons = @( | |
[FolderDescription]::new('{31C0DD25-9439-4F12-BF41-7FF4EDA38722}', '「3Dオブジェクト」フォルダのアイコンを表示する'), | |
[FolderDescription]::new('{b4bfcc3a-db2c-424c-b029-7fe99a87c641}', '「デスクトップ」フォルダのアイコンを表示する'), | |
[FolderDescription]::new('{7d83ee9b-2244-4e70-b1f5-5393042af1e4}', '「ダウンロード」フォルダのアイコンを表示する'), | |
[FolderDescription]::new('{f42ee2d3-909f-4907-8871-4c22fc0bf756}', '「ドキュメント」フォルダのアイコンを表示する'), | |
[FolderDescription]::new('{a0c69a99-21c8-4671-8703-7934162fcf1d}', '「ミュージック」フォルダのアイコンを表示する'), | |
[FolderDescription]::new('{0ddd015d-b06c-45d5-8c4c-f59713854639}', '「ピクチャ」フォルダのアイコンを表示する'), | |
[FolderDescription]::new('{35286a68-3c57-41a1-bbb1-0eae73d76c95}', '「ビデオ」フォルダのアイコンを表示する') | |
) | |
[FolderDescription]::dirty = $false | |
$icons | MultiSelection -Initial { $_.policy } -Selected { $_.SetPolicy([policy]::Show) } -Unselected { $_.SetPolicy([policy]::Hide) } | |
if ([FolderDescription]::dirty) { | |
Write-Host "設定が変更されました。エクスプローラーを再起動してください。" | |
} | |
else { | |
Write-Host "設定は変更されませんでした。" | |
} |
OneDrive と 3DObject にも対応しておきたいところ。
[HKEY_CLASSES_ROOT\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}]
"System.IsPinnedToNameSpaceTree"=0
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{31C0DD25-9439-4F12-BF41-7FF4EDA38722}]
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
テキストベースの複数選択式メニューを実装してみました。こんな感じになります。