Created
October 2, 2025 20:35
-
-
Save ryrun/8b7af76d0bcf7d7a34d2381b69ef373b to your computer and use it in GitHub Desktop.
Send WM_COPYDATA message with PowerShell to Renoise for Sample flipping
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ================== Settings ================== | |
| $windowTitleContains = "renoise" # case-insensitive match in window title | |
| $wavPath = "C:\Windows\Media\tada.wav" # example WAV file from Windows | |
| $dwData = 3 # use same protocol id as your C# example | |
| # ================== Win32 P/Invoke ================== | |
| $src = @" | |
| using System; | |
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| public static class Win32 { | |
| public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); | |
| [DllImport(""user32.dll"")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); | |
| [DllImport(""user32.dll"")] public static extern bool IsWindowVisible(IntPtr hWnd); | |
| [DllImport(""user32.dll"", CharSet=CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); | |
| [DllImport(""user32.dll"", CharSet=CharSet.Auto)] public static extern int GetWindowTextLength(IntPtr hWnd); | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct COPYDATASTRUCT { | |
| public IntPtr dwData; | |
| public int cbData; | |
| public IntPtr lpData; | |
| } | |
| public const int WM_COPYDATA = 0x004A; | |
| [DllImport(""user32.dll"", CharSet=CharSet.Auto)] | |
| public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam); | |
| } | |
| "@ | |
| Add-Type -TypeDefinition $src -Language CSharp | |
| # ================== Find window ================== | |
| $match = $null | |
| $callback = [Win32+EnumWindowsProc]{ | |
| param([IntPtr]$h,[IntPtr]$p) | |
| if (-not [Win32]::IsWindowVisible($h)) { return $true } | |
| $len = [Win32]::GetWindowTextLength($h) | |
| if ($len -le 0) { return $true } | |
| $sb = New-Object System.Text.StringBuilder ($len + 1) | |
| [void][Win32]::GetWindowText($h, $sb, $sb.Capacity) | |
| $title = $sb.ToString() | |
| if ($title -ne $null -and $title.ToLower().Contains($windowTitleContains.ToLower())) { | |
| $script:match = $h | |
| return $false # stop enumeration | |
| } | |
| return $true | |
| } | |
| [Win32]::EnumWindows($callback, [IntPtr]::Zero) | Out-Null | |
| if (-not $match) { | |
| Write-Host "No visible window found whose title contains '$windowTitleContains'." | |
| return | |
| } | |
| Write-Host ("Found window handle: 0x{0}" -f $match.ToString("X")) | |
| # ================== Send WM_COPYDATA (ANSI) ================== | |
| if (-not (Test-Path $wavPath)) { | |
| Write-Host "Warning: file does not exist: $wavPath" | |
| } | |
| # Allocate unmanaged memory for ANSI (LPStr) null-terminated string | |
| $ptr = [Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($wavPath) | |
| try { | |
| $cds = New-Object Win32+COPYDATASTRUCT | |
| $cds.dwData = [IntPtr]::op_Explicit($dwData) | |
| # cbData = byte length INCLUDING null terminator | |
| $byteCount = [Text.Encoding]::Default.GetByteCount($wavPath) # system ANSI codepage | |
| $cds.cbData = $byteCount + 1 | |
| $cds.lpData = $ptr | |
| $result = [Win32]::SendMessage($match, [Win32]::WM_COPYDATA, [IntPtr]::Zero, [ref]$cds) | |
| Write-Host ("SendMessage(WM_COPYDATA) return value: 0x{0}" -f $result.ToString("X")) | |
| } | |
| finally { | |
| if ($ptr -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::FreeHGlobal($ptr) } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment