2009-02-04 14 views
17

मेरे प्रोग्राम के एक उदाहरण से एक स्ट्रिंग भेजने के लिए सबसे अच्छा और आसान तरीका मेरे प्रोग्राम के दूसरे उदाहरण में क्या है? प्राप्त करने वाले प्रोग्राम को पैरामीटर के रूप में प्राप्त स्ट्रिंग का उपयोग करके प्रक्रिया को निष्पादित करना होता है।मैं अपने डेल्फी प्रोग्राम के एक उदाहरण से दूसरे में एक स्ट्रिंग कैसे भेजूं?

मैंने डीडीई के बारे में पढ़ना शुरू कर दिया लेकिन मुझे उलझन में आया। मेरे पास अन्य विकल्प क्या हैं, और इसे लागू करने का सबसे आसान तरीका क्या है?

+1

@ आर्थर: मैंने आपके प्रश्न को वर्गीकृत करना और बाद में खोजना आसान बना दिया। इसलिए न केवल आपके लिए समस्याओं का त्वरित समाधान प्राप्त करना है, बल्कि विकी की तरह ज्ञान के एक खोज योग्य निकाय को भी बनाना है। – mghie

+0

उदाहरणों के बीच जानकारी संचारित करने के लिए रजिस्ट्री का उपयोग करने में कुछ भी गलत है? या इससे प्रदर्शन पर असर पड़ेगा? – Optavius

उत्तर

18

नामित पाइप्स का उपयोग करें, लेकिन मैं रसेल लिबी के नामित पाइप घटकों की अनुशंसा करता हूं। एक TPipeClient और TPipeServer घटक है।

की (2013-10-04) Francoise Piette and [email protected] updated this source code के रूप में डेल्फी 7 XE5 के साथ संकलन (पहले के संस्करणों लेकिन अपरीक्षित संकलन सकता है) और इसे यहाँ डाल करने के लिए: http://www.overbyte.be/frame_index.html?redirTo=/blog_source_code.html

इन 2 घटकों नामित पाइप का उपयोग कर अविश्वसनीय रूप से आसान बनाने के लिए, और नामित पाइप इंटर-प्रोसेस संचार (आईपीसी) के लिए बहुत अच्छे हैं।

His website is here। "Pipes.zip" के लिए देखो। स्रोत से विवरण है: // विवरण: डेल्फी के लिए पाइप घटकों नामक क्लाइंट और सर्वर का सेट, // कंसोल पाइप रीडायरेक्शन घटक के रूप में अच्छी तरह से।

इसके अलावा, रसेल ने नामक पाइप पर संदेश भेजने/प्राप्त करने के लिए कंसोल ऐप में काम करने के लिए इस घटक के पुराने संस्करण का उपयोग करने के साथ विशेषज्ञों-एक्सचेंज पर मेरी मदद की। यह आपको अपने घटकों का उपयोग करने और चलाने के लिए एक गाइड के रूप में मदद कर सकता है। कृपया ध्यान दें, कि एक वीसीएल ऐप या सेवा में, आपको अपना कंसोल ऐप में अपना खुद का संदेश लूप लिखने की आवश्यकता नहीं है।

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. 
+0

पुस्तकालय काफी दिलचस्प लगता है, इसे इसके माध्यम से पढ़ना होगा। :) – PetriW

+4

मुझे लगता है कि लिंक टूटा हुआ है, क्योंकि मैं इसे एक्सेस नहीं कर सकता। –

+0

@ एंड्रिया रैमोंडी आप यहां pipes.pas देख सकते हैं http://r3code.livejournal.com/117012.html –

15

मैं इसके लिए नामित पाइप का उपयोग करता हूं, यह मुझे सबसे आसान मिला। जब मैं काम से घर जाता हूं तो मैं कोड पोस्ट करूंगा। http://www.delphi3000.com/articles/article_2918.asp?SK=

वहाँ जिस तरह से यह करने के लिए एक लाख समाधान है उन सभी को परेशान होने लगते हैं,:

यहाँ कैसे डेल्फी में इसका इस्तेमाल करने पर एक लेख है। पाइप्स अब तक का सबसे अच्छा है।

यहां कोड है, देरी के बारे में खेद है। आपको मिक द्वारा वर्णित पाइप लाइब्रेरी भी देखना चाहिए। मैंने जो काम किया है वह एक बहुत तेज़ प्रयोग था। कृपया ध्यान दें कि डेल्फी में किया गया था 2009.

unit PetriW.Pipes; 

interface 

uses 
    Windows, 
    Classes, 
    Forms, 
    SyncObjs, 
    SysUtils 
    ; 

type 
    TPBPipeServerReceivedDataEvent = procedure(AData: string) of object; 

    TPBPipeServer = class 
    private 
    type 
     TPBPipeServerThread = class(TThread) 
     private 
     FServer: TPBPipeServer; 
     protected 
     public 
     procedure Execute; override; 

     property Server: TPBPipeServer read FServer; 
     end; 
    private 
    FOnReceivedData: TPBPipeServerReceivedDataEvent; 
    FPath: string; 
    FPipeHandle: THandle; 
    FShutdownEvent: TEvent; 
    FThread: TPBPipeServerThread; 
    protected 
    public 
    constructor Create(APath: string); 
    destructor Destroy; override; 

    property Path: string read FPath; 

    property OnReceivedData: TPBPipeServerReceivedDataEvent read FOnReceivedData write FOnReceivedData; 
    end; 

    TPBPipeClient = class 
    private 
    FPath: string; 
    protected 
    public 
    constructor Create(APath: string); 
    destructor Destroy; override; 

    property Path: string read FPath; 

    procedure SendData(AData: string); overload; 
    class procedure SendData(APath, AData: string); overload; 
    end; 

implementation 

const 
    PIPE_MESSAGE_SIZE = $20000; 

{ TPipeServer } 

constructor TPBPipeServer.Create(APath: string); 
begin 
    FPath := APath; 

    FShutdownEvent := TEvent.Create(nil, True, False, ''); 

    FPipeHandle := CreateNamedPipe(
    PWideChar(FPath), 
    PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED, 
    PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT, 
    PIPE_UNLIMITED_INSTANCES, 
    SizeOf(Integer), 
    PIPE_MESSAGE_SIZE, 
    NMPWAIT_USE_DEFAULT_WAIT, 
    nil 
); 

    if FPipeHandle = INVALID_HANDLE_VALUE then 
    RaiseLastOSError; 

    FThread := TPBPipeServerThread.Create(true); 
    FThread.FreeOnTerminate := false; 
    FThread.FServer := self; 
    FThread.Resume; 
end; 

destructor TPBPipeServer.Destroy; 
begin 
    FShutdownEvent.SetEvent; 
    FreeAndNil(FThread); 
    CloseHandle(FPipeHandle); 
    FreeAndNil(FShutdownEvent); 

    inherited; 
end; 

{ TPipeServer.TPipeServerThread } 

procedure TPBPipeServer.TPBPipeServerThread.Execute; 
var 
    ConnectEvent, ReadEvent: TEvent; 
    events: THandleObjectArray; 
    opconnect, opread: TOverlapped; 
    Signal: THandleObject; 
    buffer: TBytes; 
    bytesRead, error: Cardinal; 
begin 
    inherited; 

    //SetThreadName('TPBPipeServer.TPBPipeServerThread'); 

    ConnectEvent := TEvent.Create(nil, False, False, ''); 
    try 
    setlength(events, 2); 
    events[1] := Server.FShutdownEvent; 

    FillMemory(@opconnect, SizeOf(TOverlapped), 0); 
    opconnect.hEvent := ConnectEvent.Handle; 

    while not Terminated do 
    begin 
     ConnectNamedPipe(Server.FPipeHandle, @opconnect); 

     events[0] := ConnectEvent; 
     THandleObject.WaitForMultiple(events, INFINITE, False, Signal); 
     if Signal = ConnectEvent then 
     try 
     // successful connect! 
     ReadEvent := TEvent.Create(nil, True, False, ''); 
     try 
      FillMemory(@opread, SizeOf(TOverlapped), 0); 
      opread.hEvent := ReadEvent.Handle; 
      setlength(buffer, PIPE_MESSAGE_SIZE); 

      if not ReadFile(Server.FPipeHandle, buffer[0], PIPE_MESSAGE_SIZE, bytesRead, @opread) then 
      begin 
      error := GetLastError; 
      if error = ERROR_IO_PENDING then 
      begin 
       if not GetOverlappedResult(Server.FPipeHandle, opread, bytesRead, True) then 
       error := GetLastError 
       else 
       error := ERROR_SUCCESS; 
      end; 
      if error = ERROR_BROKEN_PIPE then 
       // ignore, but discard data 
       bytesRead := 0 
      else if error = ERROR_SUCCESS then 
       // ignore 
      else 
       RaiseLastOSError(error); 
      end; 

      if (bytesRead > 0) and Assigned(Server.OnReceivedData) then 
      Server.OnReceivedData(TEncoding.Unicode.GetString(buffer, 0, bytesRead)); 

      // Set result to 1 
      PInteger(@buffer[0])^ := 1; 
      if not WriteFile(Server.FPipeHandle, buffer[0], SizeOf(Integer), bytesRead, @opread) then 
      begin 
      error := GetLastError; 
      if error = ERROR_IO_PENDING then 
      begin 
       if not GetOverlappedResult(Server.FPipeHandle, opread, bytesRead, True) then 
       error := GetLastError 
       else 
       error := ERROR_SUCCESS; 
      end; 
      if error = ERROR_BROKEN_PIPE then 
       // ignore 
      else if error = ERROR_SUCCESS then 
       // ignore 
      else 
       RaiseLastOSError(error); 
      end; 
     finally 
      FreeAndNil(ReadEvent); 
     end; 
     finally 
     DisconnectNamedPipe(Server.FPipeHandle); 
     end 
     else if Signal = Server.FShutdownEvent then 
     begin 
     // server is shutting down! 
     Terminate; 
     end; 
    end; 
    finally 
    FreeAndNil(ConnectEvent); 
    end; 
end; 

{ TPBPipeClient } 

constructor TPBPipeClient.Create(APath: string); 
begin 
    FPath := APath; 
end; 

destructor TPBPipeClient.Destroy; 
begin 

    inherited; 
end; 

class procedure TPBPipeClient.SendData(APath, AData: string); 
var 
    bytesRead: Cardinal; 
    success: Integer; 
begin 
    if not CallNamedPipe(PWideChar(APath), PWideChar(AData), length(AData) * SizeOf(Char), @success, SizeOf(Integer), bytesRead, NMPWAIT_USE_DEFAULT_WAIT) then 
    RaiseLastOSError; 
end; 

procedure TPBPipeClient.SendData(AData: string); 
var 
    bytesRead: Cardinal; 
    success: boolean; 
begin 
    if not CallNamedPipe(PWideChar(FPath), PWideChar(AData), length(AData) * SizeOf(Char), @success, SizeOf(Integer), bytesRead, NMPWAIT_USE_DEFAULT_WAIT) then 
    RaiseLastOSError; 
end; 

end. 

यहाँ कैसे मैं कुछ भेज दिया गया है:

TPBPipeClient.SendData('\\.\pipe\pipe server E5DE3B9655BE4885ABD5C90196EF0EC5', 'HELLO'); 

यहाँ कैसे मैं कुछ पढ़ा है:

procedure TfoMain.FormCreate(Sender: TObject); 
begin 
    PipeServer := TPBPipeServer.Create('\\.\pipe\pipe server E5DE3B9655BE4885ABD5C90196EF0EC5'); 
    PipeServer.OnReceivedData := PipeDataReceived; 
end; 

procedure TfoMain.PipeDataReceived(AData: string); 
begin 
    if AData = 'HELLO' then 
    // do something, but note that you're not in the main thread, you're in the pipe server thread 
end; 
+1

इस उदाहरण को जोड़ने के लिए धन्यवाद। यह स्पष्ट करने में मदद करता है। – Mick

+0

डेल्फी 3000 लेख लिंक टूटा हुआ है। – gabr

10

बहुत ही कम संदेशों के लिए, WM_COPYDATA है शायद सबसे आसान। इसके अलावा, पेट्रीडब्ल्यू नामित पाइप, या सॉकेट का सुझाव है।

+3

WM_COPYDATA का उपयोग वास्तव में आसान है, हालांकि हमेशा सवाल यह है कि संदेश को भेजने के लिए विंडो को कैसे संभालना है। यह अधिक कठिन हिस्सा प्रतीत होता है। – mghie

4

JCL में JclAppInstances देखें।

+0

मैं ऐसा करने की कोशिश कर रहा था। यह किसी प्रकार का "अस्पष्ट" पुरस्कार जीतता है। TJclSwapFileMapping ... मैं अभी यह कोशिश कर रहा हूं। –

+0

यह इंटर-प्रोसेस संचार का एक मानक तरीका है: मेमोरी-मैप की गई फ़ाइल, सिस्टम पेजिंग फ़ाइल द्वारा समर्थित (CreateFileMapping को INVALID_HANDLE_VALUE के साथ बुलाया जाता है)। अन्य उदाहरण के लिए कमांड लाइन पास करने के लिए इस्तेमाल किया जा सकता है। –

+0

मुझे लगता है कि मैं हमेशा खुद को अस्पष्टता के किसी प्रकार के मध्यस्थ के रूप में सोचता हूं। :-) इंटरप्रोसेस संचार तकनीक के रूप में फ़ाइलों को स्वैप करें। :-) वाह। –

0

मैं InterAppComm का उपयोग करता हूं और यह बहुत अच्छा है।

यह दो या दो से अधिक अनुप्रयोगों के बीच डेटा भेजता है। यह तार, पूर्णांक और अन्य डेटा प्रकार भेज सकता है।

1

Cromis.IPC चेक करें, आंतरिक रूप से यह नामित पाइप का उपयोग करता है, लेकिन एक बहुत आसान एपीआई प्रदान करता है, और यह हाल ही में डेल्फी संस्करणों के साथ संगत है।

2

ज़ीरोएमक्यू पर एक नज़र डालें। यदि आपको आर्किटेक्चर के पीछे विचार मिलते हैं तो यह आपके विचार से नाटकीय रूप से बदल सकता है। जहां तक ​​मेरे पास पैदल यात्रा थी, उनके पास डेल्फी समेत कई प्रोग्रामिंग भाषाओं के लिए पुस्तकालय हैं। लेकिन मुझे इसे आजमाने का मौका नहीं था। पुस्तकालय की

ZeroMQ

Here is Delphi बंदरगाह।

1

मैं सुझाव दिया गया है कि टेम्प्डफाइल - नामित पाइप से अधिक कुशल।

संबंधित मुद्दे