Поиск альтернативы сообщениям окон используется в межпроцессном взаимодействии

работает

let results=[{"city_name":"Bradford","counter":1},{"city_name":"Aberdeen","counter":1},{"city_name":"Aberfeldy","counter":1},{"city_name":"Aberaeron","counter":1},{"city_name":"Aberdare","counter":0},{"city_name":"Abergavenny","counter":0},{"city_name":"Abergele","counter":0}]


for(var i = 0; i  < results.length; i++) {
    var obj = results[i];                   
    console.log(obj.city_name);
    console.log(obj.counter);
}
//second way
results.forEach(a=>{
console.log(a.city_name);
    console.log(a.counter);
})

10
задан menjaraz 15 March 2012 в 11:32
поделиться

7 ответов

Используйте Именованные каналы. Если Вы не знаете, как использовать их, то теперь время для изучения.

С именованными каналами можно отправить любой тип структуры данных (как долго, поскольку и сервер и клиент знают то, что та структура данных). Я обычно использую массив записей для отправки большого количества информации назад и вперед.Очень удобно.

Я использую свободного Russell Libby (и открытый исходный код) компоненты именованного канала. Идет с TPipeServer и TPipeClient визуальный компонент. Они делают именованные каналы использования, невероятно легкие, и именованные каналы являются большими для межпроцессного взаимодействия (IPC).

Можно получить компонент здесь. Описание из источника://Описание: Набор компонентов именованного канала клиента и сервера для Delphi, как//хорошо консольный компонент перенаправления канала.

Кроме того, Russell выручил меня на Exchange экспертов с использованием более старой версии этого компонента для работы в консольном приложении для отправления/получения сообщений по именованным каналам. Это может помочь как руководство в подъеме Вас и выполнении с использованием его компонентов. Обратите внимание на то, что в приложении VCL или сервисе, Вы не должны писать свой собственный цикл сообщения, как я сделал в этом консольном приложении.

program CmdClient;
{$APPTYPE CONSOLE}

uses
  Windows, Messages, SysUtils, Pipes;

type
  TPipeEventHandler =  class(TObject)
  public
     procedure  OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
  end;

procedure TPipeEventHandler.OnPipeSent(Sender: TObject; Pipe: HPIPE; Size: DWORD);
begin
  WriteLn('On Pipe Sent has executed!');
end;

var
  lpMsg:         TMsg;
  WideChars:     Array [0..255] of WideChar;
  myString:      String;
  iLength:       Integer;
  pcHandler:     TPipeClient;
  peHandler:     TPipeEventHandler;

begin

  // Create message queue for application
  PeekMessage(lpMsg, 0, WM_USER, WM_USER, PM_NOREMOVE);

  // Create client pipe handler
  pcHandler:=TPipeClient.CreateUnowned;
  // Resource protection
  try
     // Create event handler
     peHandler:=TPipeEventHandler.Create;
     // Resource protection
     try
        // Setup clien pipe
        pcHandler.PipeName:='myNamedPipe';
        pcHandler.ServerName:='.';
        pcHandler.OnPipeSent:=peHandler.OnPipeSent;
        // Resource protection
        try
           // Connect
           if pcHandler.Connect(5000) then
           begin
              // Dispatch messages for pipe client
              while PeekMessage(lpMsg, 0, 0, 0, PM_REMOVE) do DispatchMessage(lpMsg);
              // Setup for send
              myString:='the message I am sending';
              iLength:=Length(myString) + 1;
              StringToWideChar(myString, wideChars, iLength);
              // Send pipe message
              if pcHandler.Write(wideChars, iLength * 2) then
              begin
                 // Flush the pipe buffers
                 pcHandler.FlushPipeBuffers;
                 // Get the message
                 if GetMessage(lpMsg, pcHandler.WindowHandle, 0, 0) then DispatchMessage(lpMsg);
              end;
           end
           else
              // Failed to connect
              WriteLn('Failed to connect to ', pcHandler.PipeName);
        finally
           // Show complete
           Write('Complete...');
           // Delay
           ReadLn;
        end;
     finally
        // Disconnect event handler
        pcHandler.OnPipeSent:=nil;
        // Free event handler
        peHandler.Free;
     end;
  finally
     // Free pipe client
     pcHandler.Free;
  end;

end.
10
ответ дан 3 December 2019 в 22:02
поделиться

Опция 1: пользовательская очередь сообщений

Можно создать пользовательскую очередь сообщений, и продвинуть сообщения очереди, отсортировать очередь на основе бизнес-правил и вытолкать сообщения от очереди от основного потока для обработки. Используйте критический раздел для синхронизации.

Опция 2: обратные вызовы

Используйте обратные вызовы для отправки данных назад и вперед от потоков. Снова, используйте критический раздел для синхронизации.

2
ответ дан 3 December 2019 в 22:02
поделиться

OmniThreadLibrary содержит очень эффективную очередь сообщений в OtlComm.pas единица.

Документация не очень хороша в данный момент (запустите здесь), но можно всегда использовать форум.

2
ответ дан 3 December 2019 в 22:02
поделиться

Да – Gabr можно использовать сообщения окон в сервисе.

==============================

Перед Windows Vista Вы, возможно, настроили свой сервис для взаимодействия с рабочим столом. Это заставляет сервис работать на том же рабочем столе как зарегистрированный пользователь, таким образом, программа, работающая как тот пользователь, могла отправить сообщения в окна Вашего сервиса. Windows Vista изолирует сервисы, хотя; они не могут больше взаимодействовать с рабочим столом никакого пользователя.

=============================

Кавычка от ответа Rob Kennedy до ‘TService не обработает сообщения

Но я не буду способный использовать 'frmMain. Дескриптор' для добавления сообщений от RDM до основной формы в Windows Vista.

Все, что я должен сделать, является находкой различный способ отправить, и получите сообщение

2
ответ дан 3 December 2019 в 22:02
поделиться

Windows передает CAN все еще использоваться в Windows Vista! Текущий вопрос - то, что технология в Изоляции Полномочия Интерфейса вызываемого пользователя перспективы (UIPI) предотвращает процессы с более низким уровнем целостности (IL) от отправки сообщений к процессу с высоким IL (например, сервис окон имеет высокий IL, и приложения непривилегированного режима имеют средний IL).

Однако это может быть обойдено, и средним приложениям IL можно позволить отправить wm's в высокие процессы IL.

Википедия говорит это лучше всего:

UIPI не является границей безопасности и не имеет целью защищать от всех, разрушают нападения. Приложения Доступности UI могут обойти UIPI путем устанавливания их значения "uiAccess" к TRUE как часть их файла манифеста. Это требует, чтобы приложение было в каталоге Program Files или Windows, а также было подписано допустимыми полномочиями подписывания кода, но эти требования будут не обязательно мешать вредоносному программному обеспечению уважать их.

Кроме того, некоторые сообщения все еще позволяются через, такие как WM_KEYDOWN, который позволяет более низкому процессу IL управлять входом к поднятой командной строке.

Наконец, функциональный ChangeWindowMessageFilter позволяет среднему процессу IL (все неподнятые процессы кроме Защищенного режима Internet Explorer) изменять сообщения, что высокий процесс IL может получить от более низкого процесса IL. Это эффективно позволяет обходить UIPI, если, работая от Internet Explorer или одного из его дочерних процессов.

Кто-то в Delphi-PRAXIS (ссылка находится на немецком языке. Используйте Google для Перевода страницы), уже занялся этой проблемой и отправил их использование кода ChangeWindowMessageFilter. Я полагаю, что их проблема - то, что WM_COPYDATA не работал бы над Vista, пока они не изменили свой код для обхода UIPI для WM_COPYDATA.

Исходная ссылка (немецкий язык)

unit uMain; 

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, ExtCtrls, StdCtrls, uallHook, uallProcess, uallUtil, uallKernel; 

type 
  TfrmMain = class(TForm) 
    lbl1: TLabel; 
    tmrSearchCondor: TTimer; 
    mmo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure tmrSearchCondorTimer(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
  private 
    { Private-Deklarationen } 
    fCondorPID : DWord; 
    fInjected : Boolean; 
    fDontWork : Boolean; 
    procedure SearchCondor; 
    procedure InjectMyFunctions; 
    procedure UnloadMyFunctions; 
    function GetDebugPrivileges : Boolean; 
    procedure WriteText(s : string); 
    procedure WMNOTIFYCD(var Msg: TWMCopyData); message WM_COPYDATA; 
  public 
    { Public-Deklarationen } 
  end; 

var 
  frmMain: TfrmMain; 
  ChangeWindowMessageFilter: function (msg : Cardinal; dwFlag : Word) : BOOL; stdcall; 

implementation 

{$R *.dfm} 

type Tmydata = packed record 
       datacount: integer; 
       ind: boolean; 
     end; 

const cCondorApplication = 'notepad.exe'; 
      cinjComFuntionsDLL = 'injComFunctions.dll'; 

var myData : TMydata; 

procedure TfrmMain.WMNOTIFYCD(var Msg: TWMCopyData); 
begin 
  if Msg.CopyDataStruct^.cbData = sizeof(TMydata) then 
  begin 
    CopyMemory(@myData,Msg.CopyDataStruct^.lpData,sizeof(TMyData)); 
    WriteText(IntToStr(mydata.datacount)) 
  end; 
end; 

procedure TfrmMain.WriteText(s : string); 
begin 
  mmo1.Lines.Add(DateTimeToStr(now) + ':> ' + s); 
end; 

procedure TfrmMain.InjectMyFunctions; 
begin 
  if not fInjected then begin 
    if InjectLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)) then fInjected := True; 
  end; 
end; 

procedure TfrmMain.UnloadMyFunctions; 
begin 
  if fInjected then begin 
    UnloadLibrary(fCondorPID, PChar(GetExeDirectory + cinjComFuntionsDLL)); 
    fInjected := False; 
  end; 
end; 

procedure TfrmMain.SearchCondor; 
begin 
  fCondorPID := FindProcess(cCondorApplication); 
  if fCondorPID <> 0 then begin 
    lbl1.Caption := 'Notepad is running!'; 
    InjectMyFunctions; 
  end else begin 
    lbl1.Caption := 'Notepad isn''t running!'; 
  end; 
end; 

procedure TfrmMain.FormDestroy(Sender: TObject); 
begin 
  UnloadMyFunctions; 
end; 

function TfrmMain.GetDebugPrivileges : Boolean; 
begin 
  Result := False; 
  if not SetDebugPrivilege(SE_PRIVILEGE_ENABLED) then begin 
    Application.MessageBox('No Debug rights!', 'Error', MB_OK); 
  end else begin 
    Result := True; 
  end; 
end; 

procedure TfrmMain.FormCreate(Sender: TObject); 
begin 
  @ChangeWindowMessageFilter := GetProcAddress(LoadLibrary('user32.dll'), 'ChangeWindowMessageFilter'); 
  ChangeWindowMessageFilter(WM_COPYDATA, 1); 
  fInjected := False; 
  fDontWork := not GetDebugPrivileges; 
  tmrSearchCondor.Enabled := not fDontWork; 
end; 

procedure TfrmMain.tmrSearchCondorTimer(Sender: TObject); 
begin 
  tmrSearchCondor.Enabled := False; 
  SearchCondor; 
  tmrSearchCondor.Enabled := True; 
end; 

end.
0
ответ дан 3 December 2019 в 22:02
поделиться

Создатели библиотеки madExcept и т. Д. Предоставляют функциональные возможности IPC, которые можно использовать вместо сообщений Windows.

http://help.madshi.net/IPC.htm

Я разработал заставка Windows на одном этапе, и я хотел, чтобы моя заставка отправляла какое-то уведомление в другую программу, и пока она была активна, я не мог заставить оконные сообщения работать между двумя приложениями.

Я заменил ее на упомянутые выше функции IPC.

Сработало.

0
ответ дан 3 December 2019 в 22:02
поделиться

Я использую эту библиотеку для IPc (использует разделяемую память + мьютекс): http://17slon.com/gp/gp/gpsync.htm

Он имеет TGpMessageQueueReader и TGpMessageQueueWriter. Используйте "Global \" перед именем, чтобы вы могли использовать его для связи между службой Windows и "Service GUI Helper", когда пользователь входит в систему. (Префикс Global \ необходим для Vista из-за кольца безопасности сеанса, но также и для Windows XP / 2003 между сеансами пользователя).

Он очень быстрый, многопоточный и т. д. Я бы использовал его вместо WM_COPYDATA (медленный и много накладных расходов, если вы его часто используете, но для мелочей сообщения могут быть в порядке)

0
ответ дан 3 December 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: