xlogI125’s blog

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

PowerShell: フォームにドラッグされたファイルのパスを取得

フォームでのドロップ操作を省略し、ドラッグ操作とクリック操作を考える。
普通にショートカット(*.lnk)アイコンへのドラッグ&ドロップのほうが便利な気がする。

# [テスト環境]
#  PowerShell 5.1, Windows 11 (2024年2月頃)
# [スクリプトファイル(.ps1)]
#  <ファイル名>
#   "%USERPROFILE%\Desktop\test.ps1"
#  <エンコード>
#   UTF-8 (BOM付き)
# [ショートカット(.lnk)]
#  <リンク先(T)>
#   PowerShell.exe -NoLogo -NoExit -NoProfile -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\test.ps1"
#  <作業フォルダー(S)>
#   ""

$ErrorActionPreference = "Stop"
$VerbosePreference = "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);
  }
}
'@

# Comparison
$cmp = [System.Comparison[string]]{
  param ([string]$x, [string]$y)
  return [Win32API.Shlwapi]::StrCmpLogicalW($x, $y)
}

$paths = [string[]]$args
[System.Array]::Sort($paths, $cmp)
$paths.ForEach({ [PSCustomObject]@{Type="lnk";Value=$_} }) | Out-String | Write-Verbose

$form = [System.Windows.Forms.Form]::new()
$form.AllowDrop = $true

$form.add_DragEnter({
  try {
    # フォルダやテキストなどのドラッグ操作も受け付けるけど気にしない
    $_.Effect = [System.Windows.Forms.DragDropEffects]::Copy
    $list = [System.Collections.Generic.List[string]][string[]]$_.Data.GetFileDropList()
    $list.Sort($cmp)
    $list | Select-Object -Property @{Name="Type";Expr={"drag"}}, @{Name="Value";Expr={$_}} | Out-String | Write-Verbose
    $script:paths = [string[]]$list
  }
  catch {
    Write-Error -ErrorRecord $_ -ErrorAction Continue
  }
})

$form.add_Click({
  $this.Close()
})

[void]$form.ShowDialog()
$form.Dispose()

$paths

dy100ms.hatenadiary.jp