работает
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);
})
Используйте Именованные каналы. Если Вы не знаете, как использовать их, то теперь время для изучения.
С именованными каналами можно отправить любой тип структуры данных (как долго, поскольку и сервер и клиент знают то, что та структура данных). Я обычно использую массив записей для отправки большого количества информации назад и вперед.Очень удобно.
Я использую свободного 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.
Опция 1: пользовательская очередь сообщений
Можно создать пользовательскую очередь сообщений, и продвинуть сообщения очереди, отсортировать очередь на основе бизнес-правил и вытолкать сообщения от очереди от основного потока для обработки. Используйте критический раздел для синхронизации.
Опция 2: обратные вызовы
Используйте обратные вызовы для отправки данных назад и вперед от потоков. Снова, используйте критический раздел для синхронизации.
OmniThreadLibrary содержит очень эффективную очередь сообщений в OtlComm.pas
единица.
Документация не очень хороша в данный момент (запустите здесь), но можно всегда использовать форум.
Да – Gabr можно использовать сообщения окон в сервисе.
==============================
Перед Windows Vista Вы, возможно, настроили свой сервис для взаимодействия с рабочим столом. Это заставляет сервис работать на том же рабочем столе как зарегистрированный пользователь, таким образом, программа, работающая как тот пользователь, могла отправить сообщения в окна Вашего сервиса. Windows Vista изолирует сервисы, хотя; они не могут больше взаимодействовать с рабочим столом никакого пользователя.
=============================
Кавычка от ответа Rob Kennedy до ‘TService не обработает сообщения
Но я не буду способный использовать 'frmMain. Дескриптор' для добавления сообщений от RDM до основной формы в Windows Vista.
Все, что я должен сделать, является находкой различный способ отправить, и получите сообщение
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.
Создатели библиотеки madExcept и т. Д. Предоставляют функциональные возможности IPC, которые можно использовать вместо сообщений Windows.
http://help.madshi.net/IPC.htm
Я разработал заставка Windows на одном этапе, и я хотел, чтобы моя заставка отправляла какое-то уведомление в другую программу, и пока она была активна, я не мог заставить оконные сообщения работать между двумя приложениями.
Я заменил ее на упомянутые выше функции IPC.
Сработало.
Я использую эту библиотеку для IPc (использует разделяемую память + мьютекс): http://17slon.com/gp/gp/gpsync.htm
Он имеет TGpMessageQueueReader и TGpMessageQueueWriter. Используйте "Global \" перед именем, чтобы вы могли использовать его для связи между службой Windows и "Service GUI Helper", когда пользователь входит в систему. (Префикс Global \ необходим для Vista из-за кольца безопасности сеанса, но также и для Windows XP / 2003 между сеансами пользователя).
Он очень быстрый, многопоточный и т. д. Я бы использовал его вместо WM_COPYDATA (медленный и много накладных расходов, если вы его часто используете, но для мелочей сообщения могут быть в порядке)