gpt4 book ai didi

delphi - 将字符串传递给已运行的应用程序实例

转载 作者:行者123 更新时间:2023-12-03 14:39:38 25 4
gpt4 key购买 nike

我有一个应用程序,可以检测是否有该应用程序的另一个实例正在运行,如果找到则退出。这部分似乎工作可靠。我的应用程序采用一个命令行参数,我想将其传递给已经运行的实例。到目前为止我有以下代码:

项目1.dpr

program Project1;

uses
...
AppInstanceControl in 'AppInstanceControl.pas';

if not AppInstanceControl.RestoreIfRunning(Application.Handle) then
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TFormMain, FormMain);
Application.Run;
end;

end.

AppInstanceControl.pas

{ 基于 Zarko Gajic 的代码 http://delphi.about.com/library/code/ncaa100703a.htm }

unit AppInstanceControl;

interface

uses
Windows,
SysUtils;

function RestoreIfRunning(const AAppHandle: THandle; const AMaxInstances: integer = 1): boolean;

implementation

uses
Messages;

type
PInstanceInfo = ^TInstanceInfo;
TInstanceInfo = packed record
PreviousHandle: THandle;
RunCounter: integer;
end;

var
UMappingHandle: THandle;
UInstanceInfo: PInstanceInfo;
UMappingName: string;

URemoveMe: boolean = True;

function RestoreIfRunning(const AAppHandle: THandle; const AMaxInstances: integer = 1): boolean;
var
LCopyDataStruct : TCopyDataStruct;
begin
Result := True;

UMappingName := StringReplace(
ParamStr(0),
'\',
'',
[rfReplaceAll, rfIgnoreCase]);

UMappingHandle := CreateFileMapping($FFFFFFFF,
nil,
PAGE_READWRITE,
0,
SizeOf(TInstanceInfo),
PChar(UMappingName));

if UMappingHandle = 0 then
RaiseLastOSError
else
begin
if GetLastError <> ERROR_ALREADY_EXISTS then
begin
UInstanceInfo := MapViewOfFile(UMappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
SizeOf(TInstanceInfo));

UInstanceInfo^.PreviousHandle := AAppHandle;
UInstanceInfo^.RunCounter := 1;

Result := False;
end
else //already runing
begin
UMappingHandle := OpenFileMapping(
FILE_MAP_ALL_ACCESS,
False,
PChar(UMappingName));
if UMappingHandle <> 0 then
begin
UInstanceInfo := MapViewOfFile(UMappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
SizeOf(TInstanceInfo));

if UInstanceInfo^.RunCounter >= AMaxInstances then
begin
URemoveMe := False;

if IsIconic(UInstanceInfo^.PreviousHandle) then
ShowWindow(UInstanceInfo^.PreviousHandle, SW_RESTORE);
SetForegroundWindow(UInstanceInfo^.PreviousHandle);
end
else
begin
UInstanceInfo^.PreviousHandle := AAppHandle;
UInstanceInfo^.RunCounter := 1 + UInstanceInfo^.RunCounter;

Result := False;
end
end;
end;
end;
if (Result) and (CommandLineParam <> '') then
begin
LCopyDataStruct.dwData := 0; //string
LCopyDataStruct.cbData := 1 + Length(CommandLineParam);
LCopyDataStruct.lpData := PChar(CommandLineParam);

SendMessage(UInstanceInfo^.PreviousHandle, WM_COPYDATA, Integer(AAppHandle), Integer(@LCopyDataStruct));
end;
end; (*RestoreIfRunning*)

initialization

finalization
//remove this instance
if URemoveMe then
begin
UMappingHandle := OpenFileMapping(
FILE_MAP_ALL_ACCESS,
False,
PChar(UMappingName));
if UMappingHandle <> 0 then
begin
UInstanceInfo := MapViewOfFile(UMappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
SizeOf(TInstanceInfo));

UInstanceInfo^.RunCounter := -1 + UInstanceInfo^.RunCounter;
end
else
RaiseLastOSError;
end;

if Assigned(UInstanceInfo) then UnmapViewOfFile(UInstanceInfo);
if UMappingHandle <> 0 then CloseHandle(UMappingHandle);

end.

在主表单单元中:

procedure TFormMain.WMCopyData(var Msg: TWMCopyData);
var
LMsgString: string;
begin
Assert(Msg.CopyDataStruct.dwData = 0);
LMsgString := PChar(Msg.CopyDataStruct.lpData);

//do stuff with the received string

end;

我很确定问题是我正在尝试将消息发送到正在运行的应用程序实例的句柄,但尝试在主窗体上处理消息。我想我这里有两个选择:

A) 从应用程序的句柄中以某种方式获取其主窗体的句柄并向那里发送消息。

B) 在应用程序而不是主表单级别处理消息接收。

我也不知道该怎么做。有更好的方法吗?

谢谢。

最佳答案

如果使用 WM_COPYDATA,则无需创建文件映射。这就是 WM_COPYDATA 的全部意义 - 它为您完成所有这些工作。

发送字符串

procedure IPCSendMessage(target: HWND;  const message: string);
var
cds: TCopyDataStruct;
begin
cds.dwData := 0;
cds.cbData := Length(message) * SizeOf(Char);
cds.lpData := Pointer(@message[1]);

SendMessage(target, WM_COPYDATA, 0, LPARAM(@cds));
end;

接收字符串

procedure TForm1.WMCopyData(var msg: TWMCopyData);
var
message: string;
begin
SetLength(message, msg.CopyDataStruct.cbData div SizeOf(Char));
Move(msg.CopyDataStruct.lpData^, message[1], msg.CopyDataStruct.cbData);

// do something with the message e.g.
Edit1.Text := message;
end;

根据需要进行修改以发送其他数据。

关于delphi - 将字符串传递给已运行的应用程序实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/220719/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com