1

WM_COPYDATAを使用して、次のようにDelphiXEでコマンドラインパラメータを別のアプリインスタンスに渡します。

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

#2を使用して文字列を引用するか、何か(#3、#4)を追加すると、最終的に3つのパラメーターとして表示されます。

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

3 に答える 3

5

@TOndrejが問題の主な原因を突き止めたと思います。ただし、もう1つ微妙なバグがあると思います。

メッセージを受信するアプリは、nullで終了する文字列として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));
于 2011-09-24T19:42:26.250 に答える
4

私はあなたcopyData.cbdata := 1 * SizeOf(Char) + ...がただの代わりに意味したと思います1 + ...

于 2011-09-24T18:20:43.960 に答える
4

別の関連するメモでは、ParamStr()(それ自体に多くの既知のバグがあります)を使用して元のコマンドラインを解析し、そこから新しい文字列を再構築するのではGetCommandLine()なく、代わりに元のコマンドラインを取得して送信するために使用できますそのまま。

于 2011-09-25T16:20:45.557 に答える