マウスボタンの接触不良が原因でショートカット(*.lnk)アイコンへのドラッグ&ドロップ操作を失敗すると大変なことになるので、フォームへのドラッグ&ドロップを考える。
# PowerShell 5.1, Windows 11 (2024年2月頃) $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop $VerbosePreference = [System.Management.Automation.ActionPreference]::Continue Set-StrictMode -Version Latest Add-Type -AssemblyName System.Windows.Forms Add-Type -Language CSharp -TypeDefinition @' using System.Runtime.InteropServices; namespace Win32API { public class Shlwapi { [DllImport("Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode)] public static extern int StrCmpLogicalW( [MarshalAs(UnmanagedType.LPWStr)] string psz1, [MarshalAs(UnmanagedType.LPWStr)] string psz2 ); } } '@ # フォームにドラッグ&ドロップされたファイルのパスを取得 $paths = Invoke-Command -ScriptBlock { $refPaths = [ref]$null $form = [Windows.Forms.Form]::new() $form.AllowDrop = $true $form.Text = "ドラッグ&ドロップ" $form.Width = 300 $form.Height = 200 # ドラッグ $form.add_DragEnter([System.Windows.Forms.DragEventHandler]{ param([object]$sender, [Windows.Forms.DragEventArgs]$e) try { # ドラッグされた項目のパスを取得 $paths = $e.Data.GetFileDropList() if ($paths.Count -eq 0) { return } # ファイル以外を含む場合はドロップ不可とする foreach ($path in $paths) { if ( -not [System.IO.File]::Exists($path) ) { return } } $e.Effect = [Windows.Forms.DragDropEffects]::Copy # ドラッグされた項目のパスを確認 $paths.ForEach({ [PSCustomObject]@{ Event = "DragEnter"; Value = $_ } }) | Format-Table -AutoSize -Wrap | Out-String -Width 80 | Write-Verbose } catch { Write-Error -ErrorRecord $_ -ErrorAction Continue } }) # ドロップ $form.add_DragDrop([System.Windows.Forms.DragEventHandler]{ param([object]$sender, [Windows.Forms.DragEventArgs]$e) try { # ドロップされたファイルのパスを取得 $refPaths.Value = [string[]]$e.Data.GetFileDropList() # パスをソート [System.Array]::Sort($refPaths.Value, [System.Comparison[string]]{ param ([string]$x, [string]$y) return [Win32API.Shlwapi]::StrCmpLogicalW($x, $y) }) # ソート後のパスを確認 $refPaths.Value.ForEach({ [PSCustomObject]@{ Event = "DragDrop"; Value=$_ } }) | Format-Table -AutoSize -Wrap | Out-String -Width 80 | Write-Verbose } catch { Write-Error -ErrorRecord $_ -ErrorAction Continue } }) $null = $form.ShowDialog() $form.Dispose() # unary array expression return (, $refPaths.Value) } $paths