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

时间:2011-09-24 17:40:27

标签: delphi unicode delphi-xe wm-copydata

使用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;
如果引用/附加字符串,

会产生不同的结果。

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

C:\Users\MX4399\Research\delphi\instance\doc with spaces.doc

最终将被视为3个参数,而使用#2引用字符串或附加任何内容(#3,#4)会导致

"C:\Users\MX4399\Research\delphi\instance\doc with spaces.doc"'#$FF00'궳獧

3 个答案:

答案 0 :(得分:5)

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

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

所以发送你写的字符串:

copyData.lpData := PChar(cmdParams);
copyData.cbData := ByteLength(cmdParams))
copyData.dwData := WaterMark; 

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

SetString(cmdParams, PChar(copyData.lpData), copyData.cbData div SizeOf(Char));

答案 1 :(得分:4)

我认为您的意思是copyData.cbdata := 1 * SizeOf(Char) + ...,而不仅仅是1 + ...

答案 2 :(得分:4)

在一个单独但相关的注释上,而不是使用ParamStr()(它本身有许多已知的错误)来解析原始命令行并从中重建一个新字符串,你可以使用{{1获取原始命令行并按原样发送。