xlogI125’s blog

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

PowerShell練習 Add-Type (StrCmpLogicalW)

メモ

  • 自然順ソートとして StrCmpLogicalW を DllImport して Add-Type で加える
  • ソートは List.Sort メソッドかバブルソート

使い捨てスクリプト

# PowerShell 5.1, Windows 10

Set-StrictMode -Version Latest

# デスクトップにあるファイル名を取得
Set-Location "${env:USERPROFILE}\Desktop"
$str = @(Get-ChildItem -File -Name)

$srcCSharp = @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace MyNamespace
{
    public class MyClass
    {
        [DllImport("Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode)]
        public static extern int StrCmpLogicalW(
            [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
            [MarshalAs(UnmanagedType.LPWStr)] string psz2
            );

        public static void MySort(ref string[] str) {
            List<string> tmp = new List<string>(str);
            tmp.Sort(StrCmpLogicalW);
            tmp.CopyTo(str);
        }
    }
}
'@

Add-Type -Language CSharp -TypeDefinition $srcCSharp

# ソート
[MyNamespace.MyClass]::MySort([ref]$str)

# 画面に表示
$str

# クリップボードにコピー
$str | Set-Clipboard
  • ショートカットアイコンにドラッグされたファイルのファイル名を StrCmpLogicalW の順にしてクリップボードにコピーする使い捨てスクリプト
# PowerShell 5.1, Windows 10

# このスクリプトのファイル名
#  "%USERPROFILE%\Desktop\MySortStr.ps1"
# 文字コード
#  UTF-8 (BOM付き)

# ショートカット(.lnk)
#  リンク先(T):
#   PowerShell.exe -NoLogo -NoExit -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\MySortStr.ps1"
#  作業フォルダー(S):
#   ""

Set-StrictMode -Version Latest

$strCSharp = @'
[DllImport("Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(
    [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
    [MarshalAs(UnmanagedType.LPWStr)] string psz2
    );
'@

Add-Type -Language CSharp -MemberDefinition $strCSharp -Namespace "Win32API" -Name "NativeMethods"

# ショートカットのアイコンに他のファイルのアイコンをドラッグして
# このスクリプトを実行させるので、
# argsはファイルのパスであるものとします。
$strNames = @(Split-Path -Path $args -Leaf)

# バブルソート
for ($i = 0; $i -lt $strNames.Length - 1; $i++) {
    for ($j = $strNames.Length - 1; $j -gt $i; $j--) {
        if ([Win32API.NativeMethods]::StrCmpLogicalW($strNames[$j - 1], $strNames[$j]) -gt 0) {
            $strTmp = $strNames[$j - 1]
            $strNames[$j - 1] = $strNames[$j]
            $strNames[$j] = $strTmp
        }
    }
}

# 画面に表示
$strNames

# クリップボードにコピー
$strNames | Set-Clipboard