Zenn
🐾

PowerShell7でもトーストを出したい

に公開

...何で、PowerShell5ではトースト出せてPowerShell7ではトースト出せないじゃヽ(`Д´)ノ
ってわけでどうにかした。どー見ても手口はマルウェアだが後悔はしていない。
いや、大丈夫、小細工でencOdeDCommAndとかにはしてないし?

もっと簡単な方法を見つけてしまった...orz

本題

20250117cmd.exe要らんやんけ
20250206文字列化なんぞ要らんやんけ

function ShowToast {
    param (
        [Parameter(Mandatory = $true)] [string] $Title,
        [Parameter(Mandatory = $true)] [string] $Message,
        [Parameter(Mandatory = $true)] [string] $Detail
    )
    begin {}
    process {
        $null = powershell {
            param ($Title, $Message, $Detail)
            [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
            [Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
            [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
            $app_id = "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe"
            $content = ""
            $content += "<?xml version='1.0' encoding='utf-8'?>"
            $content += "<toast>"
            $content += "  <visual>"
            $content += "    <binding template='ToastGeneric'>"
            $content += "        <text>$Title</text>"
            $content += "        <text>$Message</text>"
            $content += "        <text>$Detail</text>"
            $content += "    </binding>"
            $content += "  </visual>"
            $content += "</toast>"
            $xml = New-Object Windows.Data.Xml.Dom.XmlDocument
            $xml.LoadXml($content)
            $toast = New-Object Windows.UI.Notifications.ToastNotification $xml
            [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($app_id).Show($toast)
        } -args $Title, $Message, $Detail
    }
    end {}
}

説明

えー当初想像もしなかったんでスクリプトブロックを文字列化した挙げ句
Base64Encodeしてpowershellに実行させてたんですが、そんな苦労は不要でした
...pwshでpowershellにスクリプトブロックが渡せるだなんて思わないじゃんorz
つーわけでトーストどころかWinRT関連も割とコレでどーにかなりやがります
嘘だろ、オイ

ちなみにトースト表示自体の元ネタはココ

https://qiita.com/magiclib/items/12e2a9e1e1e823a7fa5c

蛇足

ここまで書いてなんだけど自分への通知はIP Messengerでいい気もする
割と多用するであろうUNCリンクとかも自動生成してくれるし必要ならリモートにも飛ばせる
電文はただのUDPらしいから直接送信したろーかと思ったけどパケットIDとやらで挫折中

function SendIPMsg {
    param (
        [Parameter(Mandatory = $false)] [string] $ExePath = "$ENV:USERPROFILE\AppData\Local\IPMsg\IPMsg.exe",
        [Parameter(Mandatory = $false)] [string] $TargerIP = "127.0.0.1",
        [Parameter(Mandatory = $true)]  [string] $Message
    )
    begin {}
    process {
        $Message = $Message.Replace("`r`n","\n")
        $Message = $Message.Replace("`n","\n")
        Start-Process -FilePath $ExePath -ArgumentList "/MSGEX", $TargerIP, $Message -NoNewWindow -Wait
    }
    end {}
}

因みにIP MessengerにはWinGetなDSCまである
流石多分日本製で一番有名なソフト(いやそれFastCopy)

properties:
  configurationVersion: 0.2.0
  resources:
    - resource: Microsoft.WinGet.DSC/WinGetPackage
      id: installIPMsg
      directives:
        description: Install IP Messenger
      settings:
        id: FastCopy.IPMsg
        source: winget

このほかにも権限設定さえできりゃmsgコマンドなんつー手段もあるにはある
※自分への送信だけなら権限不要だったよーな気がする

蛇足の蛇足

おっさん的にはカーニハン版C言語とか思い出すんでParam構文が読みやすいとかいう能書きがキチガイにしか思えないんDeathが最近の若者的にはこんなクソダルい構文がナウでヤングな竹の子族なわけDeathか?

20250206
世の中にはCsWinRTなんつー素敵な物体があるらしい
コイツでpwsh7からWinRTを弄れるらしいんだぜーって聞いて調べてみたら以下のスレを発見
powershell {get-host}で結果を受け取れる...だと!?というお話だったのでした

https://github.com/PowerShell/PowerShell/issues/13042

Discussion

ログインするとコメントできます