Skip to content

Instantly share code, notes, and snippets.

@ryrun
Created October 2, 2025 20:35
Show Gist options
  • Select an option

  • Save ryrun/8b7af76d0bcf7d7a34d2381b69ef373b to your computer and use it in GitHub Desktop.

Select an option

Save ryrun/8b7af76d0bcf7d7a34d2381b69ef373b to your computer and use it in GitHub Desktop.
Send WM_COPYDATA message with PowerShell to Renoise for Sample flipping
# ================== 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