2009-08-11 13 views
5

In che modo un'applicazione desktop può comunicare con un servizio Windows in Vista/Windows 2008/Windows 7? L'applicazione deve inviare stringhe di piccole dimensioni al servizio e ricevere risposte di stringa. Entrambi sono scritti in Delphi 2009. (Si prega di fornire anche il codice di esempio)Delphi 2009: come comunicare tra il servizio Windows e l'applicazione desktop in Vista?

+0

È incredibile! Ho chiesto più o meno la stessa domanda ed ero anche più umile, ma ho ricevuto solo critiche invece di risposte ... ;-) – PSyLoCKe

risposta

6

La strada da percorrere è named pipes, probabilmente dovrai dare un'occhiata alla comunicazione tra diversi Integrity levels.

This article esplora come farlo in Vista. Sebbene sia scritto in C++, è solo una semplice chiamata API di Windows, quindi dovrebbe essere abbastanza veloce da essere tradotto in Delphi.

Se si desidera cercare altro su questo argomento, questa comunicazione è denominata Inter Process Communication, ma un termine di ricerca migliore è IPC.

+1

È vero? Ho eseguito diversi servizi Windows come server TCP e client TCP. Hanno funzionato tutti bene come "sistema locale". Ho sempre creduto che la restrizione fosse sulle risorse di rete (// macchina/risorsa/...). –

+1

La prima affermazione è completamente falsa. Ogni servizio Windows che abbia mai scritto è stato un demone di rete di qualche tipo. L'unica volta in cui sono necessarie le autorizzazioni funky era quella che doveva essere in grado di visualizzare anche l'interfaccia utente. –

+0

Sì, mi sono ricordato male, non è consentito creare una connessione di rete con risorse esterne, o devi eseguire come NetworkService. Ho cancellato la prima affermazione. Ma ancora, le named pipe sono un modo migliore per comunicare con il tuo servizio (problema nell'individuare l'articolo di compatibilità vista su IPC) –

2

Non l'ho provato, ma penso che potreste usare named pipe.

3

Dai un'occhiata alle risposte in Exchange Data between two apps across PC on LAN che è praticamente la stessa domanda al giorno d'oggi. Le comunicazioni locali via TCP sono standard. Come ho detto nella mia risposta, le soluzioni che utilizzano le interfacce di tipo "Remote Procedure Call" funzionano bene. Io uso RemObjects SDK per questo genere di cose, e rende facile espandere il controllo attraverso la rete se si desidera in seguito.

Entrambi consentono di creare una connessione che per la maggior parte del codice è "trasparente" e basta chiamare un'interfaccia che invia i dati sul filo e restituisce i risultati. È quindi possibile programmare come di solito si fa e dimenticare i dettagli delle prese ecc.

+1

Un servizio non deve avere permessi speciali per usare la rete, anche se è solo ascoltando localmente? –

+0

@Rob, dipende da quale account viene eseguito il servizio come. – Kevin

+0

Non ho riscontrato problemi nell'utilizzo di RemObjects utilizzando l'account di sistema o un account utente. Il problema riguarda più i diritti degli utenti di dominio rispetto all'accesso al socket TCP/IP che è indipendente. – mj2008

5

Utilizzando Indy è possibile creare in modo relativamente semplice una connessione TCP tra le proprie app. Soprattutto se hai solo bisogno di inviare messaggi di stringa. Per il cliente (nel tuo caso l'applicazione desktop) è fondamentalmente

var 
    Client : TIdTCPClient; 
... 
Client.Host := 'localhost'; 
Client.Port := AnyFreePortNumber; 
Client.Connect; 
Client.IOHandler.Writeln (SomeString); 
Response := Client.Readln; 
... 
Client.Disconnect; 

Per il server (sarebbe il servizio nel tuo caso)

var 
    Server : TIdTCPServer; 
    Binding : TIdSocketHandle; 
... 
Server.DefaultPort := SameFreePortNumberAsInClient; 
Binding := Server.Bindings.Add; 
Binding.IP := '127.0.0.1';  
Binding.Port := Server.DefaultPort; 
Server.OnConnect := HandleConnection; 
Server.OnDisconnect := HandleDisconnection; 
Server.OnExecute := HandleCommunication; 
Server.Active := True; 

Basta implementare il metodo HandleCommunication. Si chiama ogni volta che il cliente decide di inviare qualcosa. Esempio:

procedure MyClass.HandleCommunication (AContext : TIdContext); 
var 
    Request : String; 
begin 
    Request := AContext.Connection.IOHandler.Readln; 
    if (Request = Command1) then 
    HandleCommand1 
    else if (Request = Command2) then 
    HandleCommand2 
    ... 
end; 

IIRC un servizio è consentito solo per avere un'interfaccia utente grafica o avere accesso alla rete, quindi questo potrebbe essere un problema se il servizio ha bisogno di una GUI (che si dovrebbe evitare in ogni caso, vedere questo question). Non so come sia gestito in Windwos Vista e in seguito.

3

È necessario modificare l'utente del servizio da localsystem a networkservice e quindi il servizio può utilizzare TCPIP fine. Ho diversi servizi che usano TCPIP per un hook di controllo esterno. Assicurati che la tua porta di servizio sia configurabile in modo da poter gestire eventuali collisioni.

Alcune delle mie interfacce di controllo sono basate su pagine XML servite da un server HTTP interno. Questo mi consente di controllare a distanza lo stato del servizio utilizzando qualsiasi browser Web che possa raggiungere la porta su quella macchina. Il vantaggio dell'utilizzo di HTTP rispetto ad altri metodi è che funziona bene quando è necessario lavorare su hardware di rete esistente.

Se l'unico SOLO sta comunicando localmente, quindi named pipe, mail slots or a memory mapped file potrebbe essere il metodo migliore.

+0

Non è necessario utilizzare l'account NetworkService solo per utilizzare TCP. Funziona perfettamente anche con gli account LocalSystem e LocalService. –

1

Uso nelle applicazioni di servizio un set di componenti, freeware con codice sorgente denominato IPC semplice.

Cerca torry.net. Ha funzionato molto bene in tutte le mie app di servizio quando comunico con un'app desktop.

John

Problemi correlati