【powershell】アプリ起動ランチャー作ってみた

## ＜はじめに＞
Windows10サポート終了が告知され、会社の端末もWindows11に切り替わりました。
Windows11になったことにより、Windows10で個人的に使用していた「ツールバー」が無くなっていました😭
（よく使うアプリとかフォルダとか設定できて便利だったのに・・）

```
(´・x・).oO◯（ ないものはしょうがないね・・
```

さて、
アプリ起動ランチャーほしいけど、会社端末なので勝手にツールをインストールできない。
<br>
とりあえず、
Windowsアプリっぽいものが作れそうなpowershellをやってみよう、会社の端末にデフォルトで入ってるし。（本当はpythonやってみたけど、インストール必要だし）
<br>

＞やりたいこと・・
・アプリ起動ランチャー的なやつがほしい
・タスクバーに常駐する
・指定したフォルダ内にあるショートカットファイルを一覧で表示して、選択すると起動するみたいな感じ
・起動する際に、見るフォルダを指定できる

## ＜作ってみた＞
参考ページをベースに、
・パラメータを取得を追加
・アイコン取得やメニューの処理を変更

参考ページ :　[私PowerShellだけど、君のタスクトレイで暮らしたい](https://qiita.com/magiclib/items/cc2de9169c781642e52d)
→ 参考になりました。ありがとうございます。

``` powershell:launcher.ps1
param(
    [string]$arg1 # 引数としてフォルダのパス
)
Add-Type -AssemblyName System.Windows.Forms

$MUTEX_NAME ="Global\mutex"

# 重複起動防止
$mutex = New-Object System.Threading.Mutex($false, $MUTEX_NAME)

if($mutex.WaitOne(0, $false)){
    
    $application_context = New-Object System.Windows.Forms.ApplicationContext
    # とりあえず、explorerのアイコンを拝借
    $icon = [System.Drawing.Icon]::ExtractAssociatedIcon("C:\Windows\explorer.exe")

    # タスクバー
    $notify_icon = New-Object System.Windows.Forms.NotifyIcon
    $notify_icon.icon = $icon
    $notify_icon.Visible = $true
    $notify_icon.Text = "アプリ一覧"

    # メニューを作成（exit）
    $menuExit = New-Object System.Windows.Forms.ToolStripMenuItem
    $menuExit.Text = "Exit"
    $menuExit.Image = $icon
    $menuExit.add_click({
        # クリックしたら終了させる
        $application_context.ExitThread()
    })
    $notify_icon.ContextMenuStrip = New-Object System.Windows.Forms.ContextMenuStrip
    $notify_icon.ContextMenuStrip.Items.Add($menuExit)

    # メニューに区切り線を追加
    $sep = New-Object System.Windows.Forms.ToolStripSeparator
    $notify_icon.ContextMenuStrip.Items.Add($sep)

    # フォルダにあるショートカットファイルを取得
    foreach( $file in (Get-ChildItem "$arg1*.lnk" -File )){
        
        # メニューを作成（各ショートカットファイル）
        $menu = New-Object System.Windows.Forms.ToolStripMenuItem
        $menu.Text = $file.Name.replace(".lnk","")
        $menu.Tag = $file.FullName
        $menu.Image = [System.Drawing.Icon]::ExtractAssociatedIcon($file.FullName)
        $menu.add_click({
            # フルパスを指定して起動
            Invoke-Item $this.Tag
        })
        $notify_icon.ContextMenuStrip.Items.Add($menu)
        
    }
    # アプリを起動
    [void][System.Windows.Forms.Application]::Run($application_context)

    $notify_icon.Visible = $false
    $mutex.ReleaseMutex()
}
$mutex.Close()

```
<br>
あと、powershellのウィンドウが出っ放しになるので、起動する際はvbsからやる。

``` vb:launcher.vbs
Dim obj
Set obj = WScript.CreateObject("WScript.Shell")
obj.Run "powershell.exe -ExecutionPolicy RemoteSigned -File C:\\work\\launcher.ps1 C:\\work\\tool\\" , 0

```

## ＜出来上がり＞

指定のフォルダを用意
![スクリーンショット 2024-06-06 212303.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693459/77cbde98-6833-45ee-42e9-10d2bc1f7551.png)

launcher.vbsを実行
![スクリーンショット 2024-06-06 212525.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693459/e457ff5d-0098-4ba1-7295-2eb77c4546ff.png)

タスクバーにエクスプローラーのアイコンが表示された
![スクリーンショット 2024-06-06 212808.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693459/ca738e5b-ce97-fd3d-7796-f75fbf96daa4.png)


右クリックで指定フォルダのショートカットファイル一覧が表示された
![スクリーンショット 2024-06-06 215323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693459/6635b0d2-6a25-92d0-66e8-3b5e8e79558f.png)

```
( ´ー`).oO◯（ 意外とイメージ通り出来た・・
```


## ＜おわりに＞
・ぶっちゃけ、Windows PowerShell ISE より Visual Studio Code のほうが使いやすい。

・add_clickの処理内で、自身のオブジェクトを取得する方法がわからず苦戦した。（$thisで取れるらしい📝）