hack のためのネタ帳, etc,,,

状況

先月末くらいにインフラが更新されたせいなのか、Windows Update 側に何らかの変更が加わったのか、原因は不明だが、承前の話が解決して自動アップデートが無事通って 1909 → 20H2 になったのが昨日の話。
で、こいつ 2022-05-10 がサポート終了予定日なので、余命1ヶ月を切ってるんで、とっとと 21H2 振ってきてほしいのだが、何故か振ってこない。

それはさておき、タイトルの件。
winget は App Installer に同梱されたので、Microsoft Store で勝手に最新版にアップデートされて winget.exe は含まれてるはずなのに PATH が通ってないと言われる。
> gcm winget.exe
gcm : 用語 'winget.exe' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されま
せん。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してく
ださい。
発生場所 行:1 文字:1
+ gcm winget.exe
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (winget.exe:String) [Get-Command], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand

winget は で正式リリースされて、App Installer に組み込まれたので、現在 では Windows 10 1709 以降をサポートと言ってるので App Installer が最新版になってれば 20H2 で使えるはずである。

確認してみるとちゃんとある。アプリ実行エイリアスも ON になっていた。
PS C:\Users\kou> Get-AppxPackage |? name -match installer


Name              : Microsoft.DesktopAppInstaller
Publisher         : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture      : X64
ResourceId        :
Version           : 1.17.10271.0
PackageFullName   : Microsoft.DesktopAppInstaller_1.17.10271.0_x64__8wekyb3d8bbwe
InstallLocation   : C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.17.10271.0_x64__8wekyb3d8bbwe
IsFramework       : False
PackageFamilyName : Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
PublisherId       : 8wekyb3d8bbwe
IsResourcePackage : False
IsBundle          : False
IsDevelopmentMode : False
NonRemovable      : False
Dependencies      : {Microsoft.UI.Xaml.2.7_7.2203.17001.0_x64__8wekyb3d8bbwe, Microsoft.VCLibs.140.00.UWPDesktop_14.0.3
                    0704.0_x64__8wekyb3d8bbwe, Microsoft.DesktopAppInstaller_1.17.10271.0_neutral_split.language-ja_8we
                    kyb3d8bbwe, Microsoft.DesktopAppInstaller_1.17.10271.0_neutral_split.scale-100_8wekyb3d8bbwe}
IsPartiallyStaged : False
SignatureKind     : Store
Status            : Ok



PS C:\Users\kou> Get-AppxPackage |? name -match installer | Get-AppxPackageManifest |% Package |% Applications |% Application


Id             : App
Executable     : AppInstaller.exe
EntryPoint     : AppInstaller.App
VisualElements : VisualElements
Extensions     : Extensions

Id             : PythonRedirector
Executable     : AppInstallerPythonRedirector.exe
EntryPoint     : Windows.FullTrustApplication
VisualElements : VisualElements
Extensions     : Extensions

Id             : winget
Executable     : winget.exe
EntryPoint     : Windows.FullTrustApplication
VisualElements : VisualElements
Extensions     : Extensions




おかしいなーと思って、環境変数 Path を確認してみる以下の通り。
PS C:\Users\kou> $Env:Path -split ";" |sls WindowsApps

%USERPROFILE%\AppData\Local\Microsoft\WindowsApps


一瞬、ちゃんと設定されてるのに、と思ったのだが、あれ? %USERPROFILE% が展開されてないのでは!?
レジストリ確認してみると、なぜか REG_EXPAND_SZ じゃなくて REG_SZ になっている。
PS C:\Users\kou> REG Query HKCU\Environment /V Path

HKEY_CURRENT_USER\Environment
    Path    REG_SZ    C:\Users\kou\local\bin;C:\Users\kou\local\w32tex\bin;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\borland\bcc55\Bin;%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;

嘘やん。
どこで、REG_EXPAND_SZ から REG_SZ にすり替わった?

とりあえず、PowerShell から
PS C:\Users\kou> $path = (gi Registry::HKEY_CURRENT_USER\Environment).GetValue("Path",$null,"DoNotExpandEnvironmentNames")
のようにして $path に現状の REG_EXPAND_SZ の値を展開しない状態で取り出して
PS C:\Users\kou> $path
C:\Users\kou\local\bin;C:\Users\kou\local\w32tex\bin;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\borland\bcc55\Bin;%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;
PS C:\Users\kou> $path -split ";"
C:\Users\kou\local\bin
C:\Users\kou\local\w32tex\bin
C:\Program Files\Intel\WiFi\bin\
C:\Program Files\Common Files\Intel\WirelessCommon\
C:\borland\bcc55\Bin
%USERPROFILE%\AppData\Local\Microsoft\WindowsApps

のような値を
PS C:\Users\kou> sp Registry::HKEY_CURRENT_USER\Environment Path $path -Type ExpandString
として書き込むことで
PS C:\Users\kou> REG QUERY HKCU\Environment /V Path

HKEY_CURRENT_USER\Environment
    Path    REG_EXPAND_SZ    C:\Users\kou\local\bin;C:\Users\kou\local\w32tex\bin;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\borland\bcc55\Bin;%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;

のように、REG_EXPAND_SZ 型に入れ直した。

これで直った。
直ったんだけど、PowerShell の sp (Set-ItemProperty) で Path の型を REG_EXPAND_SZ ↔ REG_SZ で変更してもこの設定は即座には反映されない。

「システムのプロパティ」ダイアログの「詳細設定」タブ(SystemPropertiesAdvanced.exe)から、「環境変数」 ダイアログ開いて「OK」で閉じたタイミングで反映される。
これ、「環境変数」ダイアログが何か特殊なことしてるの間違いないけど、要 GUI 操作なので Path の変更自動化できんじゃん orz

reg_expand_sz update not expand」でググってみたところ以下のページを見つけた。
RegenerateUserEnvironment in shell32.dll って何よ!?
どうも「環境変数」 ダイアログで Path 変更すると新しく立ち上げたプロセスには環境変数が即座に反映されるのは、 こいつが関係してそうな雰囲気だが、ExpandEnvironmentStrings() がその場で expand せずプロセス起動時の状態使うの衝撃だわ。
ってことで、「regenerateuserenvironment」でググってみるが、断片的な情報しか見つからない。
  • ハングアップの日々 / 2010-05-30: URL memo
によると、undocumented API で
  • BOOL RegenerateUserEnvironment(WCHAR**, BOOL);
となっており、第1引数に再生成された環境変数が返って来るんだそうで、返ってきたポインタは不要になったら FreeEnvironmentVariable() で解放するようだ。
第2引数がTRUEなら自身の環境も同時に更新され、FALSEなら自身の環境はそのままということだが、これは子プロセスに渡す用の環境変数を作るやつ???

なんか、
シェル(Explorer)はこのWM_SETTINGCHANGEを受け取って、自分が持ってる環境変数領域を再生成して、以降子プロセスを起動する際に新しい環境変数領域を渡している。
って言ってるけど、私が欲しいのはこいつなのでは???

という事で「WM_SETTINGCHANGE powershell」でググったら以下の gist を見つけた。
素晴らしい。これです。求めてたのこれです。
Set-ItemProperty した結果が即座に explorer.exe に反映されました。

で、この WM_SETTINGCHANGE の件、セパレートして にまとめたんだけど、REG_SZ 縛りがあるものの [Environment]::SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) が WM_SETTINGCHANGE 発行してくれるの分かったので、WM_SETTINGCHANGE を発行するために SetTimeoutMessage() インポートするよりは、無いと分かってる変数をこいつで消す方が一番手間が少ないので以下のコードで WM_SETTINGCHANGE 発行しとけって結論に至った。
[Environment]::SetEnvironmentVariable("WM_SETTINGCHANGE","","User")

まとめ

HKCU\Environment の Path が REG_SZ になっていた場合の自動修正は以下のコマンドで OK
if ((gi HKCU:\Environment).GetValueKind("Path") -eq "String") {sp Registry::HKEY_CURRENT_USER\Environment Path (gi HKCU:\Environment).GetValue("Path",$null,"DoNotExpandEnvironmentNames") -Type ExpandString; [Environment]::SetEnvironmentVariable("WM_SETTINGCHANGE","","User")}

反映されてるかどうかの確認はショートカット キー [田]+[R] で「ファイル名を指定して実行」開いて、以下のコマンドを実行すると良い。
powershell -C "reg QUERY HKCU\Environment /v Path;$Env:Path -split """;""" |sls WindowsApp; pause"

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

フリーエリア

管理人/副管理人のみ編集できます