Powershell インストールされたアプリのだいたいのリストを出力する

# ソフト（ウェア）なの？アプリ（ケーション）なの？
最近あいまいですね。
昔はハードの性能主体だったのでハードに対してソフトと言っていたのですが、いまはハードから独立しているのと、そもそもVBAとかではアプリケーションやexeでソフトウェアと呼ばれないこと、さらにスマホがアプリと呼んでいるのでそちらの影響が大きいこともあるでしょう。
もっとも会計基準などではソフトウェアと呼ばれているのですが。
さらにプログラムもあります。

# コントロールパネルの内容をリストにしたい
主だったソフトウェア（アプリ）のリストを取得する
なるべくならインストールした日が知りたい
さらに容量も知りたい
というテーマです

# Windows10とWindows11
Windows11では プログラムの追加と削除 はインストールされているアプリに変更されています。
というかプログラムのアンインストールと変更というのもあります。
ある意味正しいかも。
しかしこれ自体は<b>アプリ</b>のというカテゴリにあるのですが、
- インストールされているアプリ
- <font color = blue>アプリの詳細設定</font> アプリの取得、アーカイブ、更新のアンインストール
- <font color = blue>既定のアプリ</font> ファイルの既定値、リンクの既定値、その他
- <font color = blue>オンラインマップ</font>　ダウンロード、保存場所、マップの更新
- <font color = blue>Web用のアプリ</font>　ブラウザーではなくアプリで開くことができる<b>webサイト</b>
- <font color = blue>ビデオの再生</font> ビデオ調整、HDR、ストリーミング、<b>バッテリーオプション</b>
- <font color = blue>スタートアップ </font> サインイン時に自動的に開始されるアプリ

とビデオの再生といったバッテリーオプションまでいくところもあり、なんだかよくわからないものが混ざっています。
とにかくWindows10ではプログラムの追加と削除ですが、Windows11ではインストールされているアプリになります。
ただし
[Windows でアプリとプログラムをアンインストールまたは削除する](https://support.microsoft.com/ja-jp/windows/windows-%E3%81%A7%E3%82%A2%E3%83%97%E3%83%AA%E3%81%A8%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E3%82%A2%E3%83%B3%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%BE%E3%81%9F%E3%81%AF%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B-4b55f974-2cc6-2d2b-d092-5905080eaf98#ID0EBD=Windows_11)

>アプリまたはプログラムが見つからない場合は、「Windows 10内のすべてのアプリを表示する」のヒントを試してください。プログラムはインストール後にプログラムの追加と削除に一覧表示されません。
とまたいい加減なことがかいてあります。

あとプログラムと機能は、こちらで開けます。あとから述べますが、これはこういう使い方しかできないようです。

```powershell
Get-ControlPanelItem "*機能*", '*Feat*' | Show-ControlPanelItem
```
`Feat`はCannonicalnameです。プログラムと機能 Microsoft.ProgramsAndFeaturesを拾っています。


# WOW6432Nodeのレジストリはバージョンに違いがある？
今回はこちらを参考に作成させていただきました。
https://qiita.com/sakekasunuts/items/106f9c0f828a07e81592

# コントロールパネルだからと言って、検索してはいけない
※リンクは5.1ベースです
探すと[Get-ControlPanelitem](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/get-controlpanelitem?view=powershell-5.1)
[Show-ControlPanelItem](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/show-controlpanelitem?view=powershell-5.1)
が出てきますが<b>全く関係ありません。</b>`
なおGet-ControlPanelitemはWin8以降、Show-ControlpanelItemはWin10以降です。
同じVer5.1でもOSにより使えるかどうかが異なっています。
Windows10ではこれらを組み合わせることでコントロールパネルを開くことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/00c13fcf-d379-aa73-65b2-1e9ca3827df4.png)

# これから出すリストは名前が空白が出て、数が合わない
Windows　ロゴキーを押しながらRで「ファイル名を指定して実行」でPowershellと入力して立ち上げてから、
以下を貼り付けます。Powershell7だと警告が出ます。
またDドライブに作ることを想定しています。既存のファイルと同名の時は注意してください
```powershell
if (test-path D:\InstalledAppList.csv){Remove-item D:\InstalledAppList.csv};Get-ChildItem -Path(
'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
'HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
'HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall') |
% { Get-ItemProperty $_.PsPath | Select-Object DisplayName, DisplayVersion, Language, Publisher, EstimatedSize, Installdate  , UninstallString } | Sort-Object DisplayName | Export-Csv -NoTypeInformation -Noclobber -Encoding utf8 D:\InstalledAppList.csv
```

## WOW6432の違い
参考にさせていただいたサイトは最後
`Uninstal`になっていましたが、手持ちのWindows10とWIndows11では`Uninstall`とL(エル）が２つになっていました。これはレジストリも同じでした、バージョンの違いでしょうか。

https://www.powershellgallery.com/packages/PSWinGlue/0.3.1/Content/Functions%5CGet-InstalledPrograms.ps1
こちらのように存在したら追加する方がいいのかもしれません。

## 出力される数の違い
手持ちの環境ではプロブラムの追加と削除では60くらいですが、これで出力すると90以上になります。
また名前のない空白行が多く出ます。これは
'HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
ここを削ると40くらいに減ります。空白行も３つです。
まずこの空白の原因ははっきりとしないのですが、アンインストールやパスにAdobe がでてくるのでADOBEのもののようです。
完全な空白はよくわかりません。

つまり手持ちの環境で出力された数をまとめると、
<ol>
<li>Win10 プログラムのアンインストールまたは変更 約60
<li>これで出力した数　名前が空白を除くと約90
<li>Win11 インストールされているアプリ 約110
</ol>
となっています。しかし3.は言語パックなどがカウントされています。つまりインストールされているアプリを表示するものになっているようです。
なので2.は1.を網羅しているので1.と合わせて修正して完成するようです。
1～3の差はよくわかりません。
なお、2.は「更新されたプログラムのアンインストール」はリストに含まれていませんでした。
これも環境やアンインストールによって変わってくると思われます。

## UnistallStringで削除しない方がよい
つまりこのことから、1.とは違う、2.で得られる UninstllStrig で削除するのはどこに影響するのかわからないので、基本的にUnitstallStringでインストールすべきではないことがわかります。少なくとも1.の方が安全です。
Windows11はすべてのプログラムからアンインストールする手順を基本としています。（ないときはWindows10と同様コントロールパネル）

# 出力項目はレジストリの項目
Select-Objectの各項目はレジストリから来ているようです。
しかし、各アプリがレジストリに登録している項目数は異なっています。
また項目があっても空白になっているということもあります。
上記のスクリプトでは、おおむね持っていそうなものをすべて上げるようにしていますが、名前があるものでも、空白は存在します。
# 現状で日付が文字列
一番単純な解決方法はExcelに出力した後変換することでしょう
`=DATEVALUE(LEFT(F33,4)&"/"&MID(F33,5,2)&"/"&RIGHT(F33,2))`
こんな感じですね。なおセルを日付形式に変えます
しかし、先に出力された方が楽なのですが、現在はわかっていません。
https://tech.guitarrapc.com/entry/2012/12/20/211206
`@{Name = "InstallDate";Expression　=　{$_.ConvertToDateTime($_.InstallDate)}}`
こうかな？と思ったのですが、効きませんでした。パターンが似てるので有効かなと思ったのですが無理でした。
こうしたい場合には
https://www.powershellgallery.com/packages/PSWinGlue/0.3.1/Content/Functions%5CGet-InstalledPrograms.ps1
こちらのようにした方がいいのかもしれません。

# まとめ
とりあえず出力することはできる。
しかしプログラムの追加と削除より多い。
突き合わせて減らして整形。
日付を変換する。
一応、これで出力はできます。