You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell发送WM_COPYDATA至MPC-HC遇指针转换错误求助

Fixing WM_COPYDATA Communication with MPC-HC in PowerShell

Let's break down the issues in your code and fix them step by step:

Key Problems in Your Original Code

  1. Incorrect P/Invoke Declaration: Your SendMessage method declares lParam as ref IntPtr, but for WM_COPYDATA, this parameter needs to be a reference to a COPYDATASTRUCT instance to match the Windows API requirement.
  2. String to IntPtr Conversion: You can't directly assign a .NET string or its first character to lpData—you need to marshal the string to unmanaged memory to get a valid pointer that MPC-HC can read.
  3. Invalid SendMessage Call: Passing [ref]$cds[0] is incorrect; you need to pass the COPYDATASTRUCT instance directly via [ref]$cds.
  4. Race Condition: Start-Process might return before MPC-HC's window is fully initialized, leading to an invalid MainWindowHandle.

Corrected Working Code

Add-Type @"
using System;
using System.Runtime.InteropServices;

public class MpcMessages {
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

    [StructLayout(LayoutKind.Sequential)]
    public struct COPYDATASTRUCT {
        public IntPtr dwData;
        public int cbData;
        public IntPtr lpData;
    }
}
"@

# Constants for MPC-HC commands and WM_COPYDATA message
$WM_COPYDATA = 0x004A
$CMD_OSDSHOWMESSAGE = 0xA0005000

# Start MPC-HC and wait for its window to be ready
$mpcProcess = Start-Process -PassThru -FilePath "C:\Program Files (x86)\K-Lite Codec Pack\MPC-HC64\mpc-hc64.exe" -ArgumentList "/new"
# Wait until MainWindowHandle is valid (non-zero)
while ($mpcProcess.MainWindowHandle -eq [IntPtr]::Zero) {
    Start-Sleep -Milliseconds 100
}

# Prepare the message to send
$message = "Hello from PowerShell!"
# Marshal the string to unmanaged Unicode memory (MPC-HC uses Unicode encoding)
$messagePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($message)

try {
    # Initialize the COPYDATASTRUCT with correct values
    $cds = New-Object MpcMessages+COPYDATASTRUCT
    $cds.dwData = [IntPtr]$CMD_OSDSHOWMESSAGE
    # cbData = total bytes of the string (Unicode = 2 bytes per char) + 2 bytes for null terminator
    $cds.cbData = ($message.Length + 1) * 2
    $cds.lpData = $messagePtr

    # Send the WM_COPYDATA message to MPC-HC
    $result = [MpcMessages]::SendMessage(
        $mpcProcess.MainWindowHandle,
        $WM_COPYDATA,
        [System.Diagnostics.Process]::GetCurrentProcess().MainWindowHandle,
        [ref]$cds
    )

    if ($result -eq [IntPtr]::Zero) {
        Write-Warning "Message might not have been received by MPC-HC"
    } else {
        Write-Host "Message sent successfully! You should see it in MPC-HC's OSD."
    }
} finally {
    # Free the unmanaged memory to avoid leaks
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($messagePtr)
}

Explanation of Critical Changes

  • Fixed P/Invoke Signature: The SendMessage method now correctly accepts a ref COPYDATASTRUCT for lParam, aligning with how WM_COPYDATA works in the Windows API.
  • Proper String Marshaling: Marshal.StringToHGlobalUni converts the .NET string to an unmanaged Unicode pointer that MPC-HC can interpret. We free this memory in a finally block to prevent memory leaks.
  • Valid cbData Calculation: For Unicode strings, each character uses 2 bytes, so we multiply the string length by 2 and add an extra 2 bytes for the required null terminator.
  • Window Readiness Check: The loop ensures we don't send the message until MPC-HC's window handle is fully initialized, avoiding invalid handle errors.
  • Correct SendMessage Call: We pass the COPYDATASTRUCT directly via [ref]$cds and use the current PowerShell process's window handle for wParam (as required by WM_COPYDATA).

内容的提问来源于stack exchange,提问作者Keith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:13:47