带有和不带引号的WM_COPYDATA会产生不同的结果

MX4*_*399 1 delphi unicode wm-copydata delphi-xe

使用WM_COPYDATA将命令行参数传递给另一个使用Delphi XE的应用程序实例,如下所示:

function DAppInstance.SendParamsToPrevInstance(AWindowHandle: THandle): Boolean;
var
  copyData: TCopyDataStruct;
  cmdParams : string;
  i : integer;
begin
  cmdParams := '';
  for i := 1 to ParamCount do
    cmdParams := cmdParams + ParamStr(i); //#1
  //cmdParams := cmdParams + '"' + ParamStr(i) + '" '; //#2
  //cmdParams := cmdParams + format('"%s" ', [ParamStr(i)]); //#3
  //cmdParams := cmdParams + format('%s;', [ParamStr(i)]); //#4

  copyData.lpData := pchar(cmdParams);
  copyData.cbData := 1 + (bytelength(cmdParams));
  copyData.dwData := WaterMark;  //ID for APP

  result := SendMessage(AWindowHandle, 
    WM_COPYDATA, 
    Application.Handle, 
    LPARAM(@copyData)) = 1;
end;
Run Code Online (Sandbox Code Playgroud)

如果引用/附加字符串,则会产生不同的结果.

如果使用#1 - 字符串是干净的,但如果没有引用则不可用,因为文件名可以有空格,这个:

C:\Users\MX4399\Research\delphi\instance\doc with spaces.doc
Run Code Online (Sandbox Code Playgroud)

将最终看作3个参数,同时使用#2引用字符串,或附加任何内容(#3,#4)导致

"C:\Users\MX4399\Research\delphi\instance\doc with spaces.doc"'#$FF00'??
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

我相信@TOndrej已经发现问题的主要原因.但是,我认为你还有一个更微妙的错误.

WM_COPYDATA我认为,接收邮件的应用程序被lpData视为以空字符结尾的字符串.如果数据格式不正确,那么您将有一个缓冲区溢出.我相信这正是你的例子中发生的事情,但事实证明它是良性的.WM_COPYDATA副本的编组只是指定的缓冲区大小cbData.你必须确保你不要超越它.恶意应用程序可以向您WM_COPYDATA发送包含数据的消息,以便您做到这一点.相反,我建议你cbData在阅读时使用.

所以发送你写的字符串:

copyData.lpData := PChar(cmdParams);
copyData.cbData := ByteLength(cmdParams))
copyData.dwData := WaterMark; 
Run Code Online (Sandbox Code Playgroud)

然后当你收到它时,你会分配一个缓冲区并根据其值复制到该缓冲区cbData.

SetString(cmdParams, PChar(copyData.lpData), copyData.cbData div SizeOf(Char));
Run Code Online (Sandbox Code Playgroud)