xlogI125’s blog

パソコン作業を効率化したい

ファイル作成時に通知領域にアイコンを表示 3

メモ

NotifyIconにおけるContextMenuStripGUIが固まらないようにするため、試しにForm表示時のみContextMenuStripを設定する。

スクリプト

NotifyIconにおけるContextMenuStripの動作確認が目的

# PowerShell 5.1, Windows 11 (2024年1月頃)
Set-StrictMode -Version Latest

$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
$VerbosePreference = [System.Management.Automation.ActionPreference]::Continue

# Register-ObjectEventコマンドレットの使用ではなくC#でイベントハンドラを追加
Add-Type -Language CSharp -TypeDefinition @'
namespace MyNS {
  public abstract class MyCls {
    public static void AddCreated(dynamic obj, dynamic lambdaMethod) {
      obj.Created += lambdaMethod;
    }
    public static void RemoveCreated(dynamic obj, dynamic lambdaMethod) {
      obj.Created -= lambdaMethod;
    }
  }
}
'@ -ReferencedAssemblies Microsoft.CSharp

Add-Type -AssemblyName System.Drawing, System.Windows.Forms

$watcher = [System.IO.FileSystemWatcher]::new()
$form = [System.Windows.Forms.Form]::new()

# SynchronizingObjectプロパティ
$watcher.SynchronizingObject = $form

$watcher.Path = "${env:USERPROFILE}\Desktop"
$watcher.Filter = "*"
$watcher.IncludeSubdirectories = $true
$watcher.NotifyFilter = [System.IO.NotifyFilters]::FileName
$watcher.EnableRaisingEvents = $true

$lambdaMethod = [System.IO.FileSystemEventHandler]{
  param ([object]$sender, [System.IO.FileSystemEventArgs]$e)
  # ローカル変数を表示
  Get-Variable -Scope Local | Out-String -Width 80 | Write-Verbose
  # $this と $_ の確認
  Write-Host "`$this と `$sender : $([object]::Equals($this, $sender))" -ForegroundColor Cyan
  Write-Host "$($sender | Format-List | Out-String)" -ForegroundColor Cyan
  Write-Host "`$_    と `$e      : $([object]::Equals($_, $e))" -ForegroundColor Green
  Write-Host "$($e      | Format-List | Out-String)" -ForegroundColor Green
  # スコープを指定して変数を変更
  $global:numCreated++
  Write-Host "numCreated: $($global:numCreated)"
}

$numCreated = 0

$notify = [System.Windows.Forms.NotifyIcon]::new()
$notify.Icon = [System.Drawing.SystemIcons]::Exclamation
$notify.Text = "通知領域アイコン"
$notify.Visible = $true

# ContextMenuStrip
$cm = [System.Windows.Forms.ContextMenuStrip]::new()
$cm.Items.Add("フォームのCloseメソッドを呼び出す", $null, [System.EventHandler]{
  $global:form.Close()
})

# 通知領域アイコンのクリック時にフォームのShowDialogメソッドを呼び出す
$notify.add_MouseClick([System.Windows.Forms.MouseEventHandler]{
  if ($global:form.Visible -eq $false) {
    $global:form.ShowDialog()
  }
})

# フォームのLoadイベント発生時にイベントハンドラを追加
$form.add_Load([System.EventHandler]{
  Write-Verbose "form: Load" -Verbose
  [MyNS.MyCls]::AddCreated($watcher, $global:lambdaMethod)
  $notify.ContextMenuStrip = $cm
})

# フォームのFormClosingイベント発生時にイベントハンドラを削除
$form.add_FormClosing([System.Windows.Forms.FormClosingEventHandler]{
  Write-Verbose "form: Closing" -Verbose
  [MyNS.MyCls]::RemoveCreated($watcher, $global:lambdaMethod)
  $notify.ContextMenuStrip = $null
})

# コンソール上で Ctrl + C を押した後に
# FileSystemWatcher.Createdイベントが発生するとエラーになる

$form.ShowDialog()