Chiamare un altro programma da un servizio di Windows

0

Problema: Sto lavorando a un servizio che eseguirà alcune elaborazioni automatizzate in un orario configurabile ogni notte. Fa alcune comunicazioni su Internet, formatta alcune informazioni e crea un file. Questo file verrà utilizzato da un altro programma. Non voglio specificare quale programma è, perché ho firmato NDA e davvero non penso che sia importante per la domanda. Il mio problema è che non riesco a far funzionare questo programma dal servizio. Se eseguo il mio programma come normale applicazione per console, funziona perfettamente. Sto chiamando il programma esterno inviando un comando shell con il percorso dell'eseguibile e diversi parametri (per la configurazione di come verrà eseguito e il percorso del file che creo con il mio programma). Il mio comando è corretto, poiché verrà eseguito incollato in una shell di comandi o se il mio programma viene eseguito come applicazione di console.

Quello che ho provato: Chiamando il programma esterno direttamente dal mio servizio (sto usando C # e il metodo Process.Start, ma non è qui né lì. Sento che la mia domanda è più concettuale della mia specifica implementazione). Questo non fa nulla. Il programma che sto chiamando è impostato per l'esecuzione in modalità non presidiata (questo non ha alcuna interfaccia utente o altro). Ho provato a eseguire un file .bat con il comando e gli argomenti corretti anche dal mio servizio, senza fortuna (ho testato indipendentemente .bat). Il mio servizio è impostato per poter interagire con il desktop.

La mia domanda: Come posso ottenere un servizio di Windows per eseguire un programma esterno? Più genericamente, qual è la soluzione o il modello preferito da utilizzare quando si deve chiamare un altro processo da un servizio (Daemon in * nix-land)? Se dovessi essere in grado di chiamare il programma e il mio problema è specifico dell'implementazione, aprirò una domanda su StackOverflow. Ma mi piacerebbe sapere qual è l'approccio standard per questo problema.

So che questo è presumibilmente un cattivo progetto, perché c'è la possibilità che nessun utente abbia effettuato l'accesso. Ma il programma da eseguire non dovrebbe richiedere autorizzazioni speciali o preoccuparsi di quale utente è stato eseguito.

Non riesco a utilizzare l'Utilità di pianificazione poiché ciò era espressamente vietato nei requisiti a causa di problemi di affidabilità. Questo è in realtà il motivo per cui il programma viene eseguito come servizio in primo luogo anziché come attività pianificata.

    
posta dprice 10.10.2014 - 23:05
fonte

2 risposte

1

Ricordo di avere un problema simile, ed è finito correlato a quale utente è il servizio in esecuzione. Funzionava solo se era in esecuzione come utente connesso, in contrapposizione al sistema locale predefinito. È possibile specificare le credenziali dell'utente nel pannello di controllo Servizi (Accedi come) e anche a livello di programmazione. Il problema con questo approccio è che devi essenzialmente conoscere l'utente in anticipo e hardcode. Nel nostro caso, abbiamo finito per dimenticare un servizio e sostituirlo con una normale applicazione desktop, che non aveva una finestra nella barra delle applicazioni, ma un'icona nell'area di notifica.

    
risposta data 11.10.2014 - 01:16
fonte
0

I servizi sono molto più affidabili per operazioni non presidiate rispetto a qualsiasi altra cosa. Ho scritto diversi e uno che accetta comandi arbitrari da una stringa di registro per eseguire (inviare e-mail di solito) su un evento. Devi stare attento a utente, permessi e percorsi (usa assoluto), ma ecco qual è l'essenza delle chiamate:

Nella mia classe:

// the action we are supposed to perform
private ProcessStartInfo psi = null;

Opzioni di analisi per creare informazioni di avvio del processo:

                int ind = go.ArgIndex;
                if ( ind < args.Length)
                    psi = new ProcessStartInfo(args[ind++]);
                for (; ind < args.Length; ind++) {
                        psi.Arguments = psi.Arguments +       
                            CommandLine.Escape(args[ind]) + " ";
                }

Nel codice di avvio del servizio (fare attenzione alla differenza tra le righe di comando del servizio e gli argomenti iniziali):

                Process p = null;
                try {
                    p = Process.Start(psi);
                } catch (InvalidOperationException) {
                    psi.UseShellExecute = false;
                    p = Process.Start(psi);
                }
                p.WaitForExit();

Risolvi i problemi effettuando una semplice chiamata, senza argomenti, su un eseguibile assoluto del percorso che non utilizza stdin, stdout, stderr. Vai da lì.

    
risposta data 22.02.2016 - 20:43
fonte

Leggi altre domande sui tag