2011-01-21 20 views
6

Sto lavorando a un progetto C++ con componenti diversi. Abbiamo bisogno di avviare l'applicazione come servizio di Windows. Il progetto è codice C++ non gestito. Ho scritto un servizio Windows C# e una dll in stile C che avrà una funzione per avviare i diversi componenti e un'altra per fermarli. La dll ha due file, un colpo di testa e un file cpp: RTSS.h:Chiamare una dll C++ (codice non gestito) da un servizio Windows C# (scritto nel codice gestito)

namespace PFDS 
{ 
    extern "C" __declspec(dllexport) int runRTS(char*); 
} 

RTSS.cpp:

using namespace PFDS; 
/* ... includes and declarations */ 
extern "C" __declspec(dllexport) int runRTS(char* service_name) 
{ 
    g_reserved_memory = (char*) malloc(sizeof(char) * RESERVED_MEMORY_SIZE); 
    _set_new_handler(memory_depletion_handler); 
    // this function is from a C++ .lib which is included in 
    // the linker input for the RTSS dll project setting. 
    // SetUnhandledExceptionHandler("RTS");  
    return 0; 
} 

nella sottoclasse ServiceBase del servizio di Windows, ho il seguente :

[DllImport("RTSSd.dll")] 
public static extern int runRTS(string serviceName); 

protected override void OnStart(string[] args) 
{ 
    try 
    { 
    // the bin directory has all dependencies (dlls needed) 
    Environment.CurrentDirectory = "D:/work/projects/bin"; 
    eventLog1.WriteEntry("RTSWinService: Starting " + this.ServiceName); 
    int result = runRTS(this.ServiceName); 
    eventLog1.WriteEntry("Result of invoking runRTS = " + result); 
    } 
    catch (Exception e) 
    { 
    eventLog1.WriteEntry("Exception caught: " + e.ToString()); 
    } 
} 

Inoltre, ho un'applicazione di test della console con codice all'interno principale simile a quella di OnStart. Sia l'applicazione che il servizio Windows vengono eseguiti senza problemi quando la funzione SetUnhandledException viene commentata. Ma quando ho rimuovere il commento che la funzione, l'applicazione di console Windows esegue ok, ma il servizio di Windows emette il seguente eccezione:

System.DllNotFoundException: Impossibile caricare la DLL 'RTSSd.dll': il modulo specificato non è stato trovato . (Eccezione da HRESULT: 0x8007007E) a RTSWS.RTSWinService.runRTS (String serviceName) a RTSWS.RTSWinService.OnStart (String [] args) in D: \ work \ project \ ... \ RTSWinService.cs: riga 39

Ho letto in alcuni thread in diversi forum che i servizi di Windows iniziano in C: \ WINDOWS \ System32, ed è vero sin da quando si inizializza un DirectoryInfo e la stampa del suo nome completo lo mostra. Ho provato a cambiare la directory di avvio predefinita con Environment.CurrentDirectory = "directory in cui il file eseguibile del servizio Windows e le DLL sono", ma non ha funzionato. Ho anche provato a cambiare la directory di processo, ma anche quella non è riuscita. Altri thread portano a questa conclusione link text, ma è davvero così? Potrebbe essere qualcosa di più semplice? Devo notare che la funzione SetUnhandledException è scritta in C++, non C, e quindi ci sono molte altre funzioni che ho bisogno di chiamare. Tutte le DLL necessarie sono posizionate accanto al file eseguibile del servizio. Il tuo feedback è molto apprezzato.

Grazie.

+0

Controllo di integrità: apri il walker delle dipendenze, controlla da cosa dipende la tua DLL, quindi assicurati che sia la DLL che le DLL dipendono da qualche parte nel tuo percorso. – Shog9

+0

Inoltre, è possibile eseguire il filemon di SysInternal per controllare le DLL che il servizio tenta di caricare. Tenere presente che un servizio Windows viene eseguito in una sessione utente diversa (e desktop) e quindi ha il proprio ambiente. E assicurati che il tuo 'd:' (o dovunque tu abbia installato) sia in realtà un vero e proprio percorso locale, non di rete o SUBST'ed (stato fatto ;-) –

+0

Ha il controllo di dipendenza, ma poiché l'applicazione della console viene eseguita con nessun problema, presumo che non ci siano dipendenze mancanti. A proposito, mi sono imbattuto nel problema dell'installazione del servizio su unità subst'ed ed è stato un problema rimuoverlo :) – vnammour

risposta

2

Quando qualcosa funziona sulla console ma non come servizio, esco le autorizzazioni di accesso sospetto. Assicurarsi che l'utente il servizio sia in esecuzione come, ha letto/eseguito l'accesso a d: \ work \ projects \ bin.

L'altro suggerimento è chiamare SetDllDirectory, che è un modo più diretto per dire dove sono le DLL che utilizzare la directory corrente. Vedere this SO thread nel percorso di ricerca pinvoke dll

È anche possibile utilizzare SysInternal's ProcMon per controllare che il sistema provi a individuare la DLL. A volte non è la DLL, ma una DLL che la tua DLL dipende da questo ha il problema e ProcMon è utile per trovare questi problemi.

+0

Grazie mille per la risposta e i commenti. Sono contento che sia stato veloce :) – vnammour

+0

Sto eseguendo il servizio come servizio locale. Ho anche provato come utente (e il mio account è un amministratore su questa macchina) e sistema locale, ma non era diverso. Ho anche effettuato una chiamata a SetDllDirectory ("D: \ work \ projects \ bin") dall'interno del metodo OnStart e ha restituito true, ma non ha risolto il problema. Quando apro lo strumento dipendenza (depends.exe) ed esamino RTSSd.dll, viene visualizzato un errore relativo alla mancata individuazione di IESHIMS.DLL e WER.DLL (le dll di sistema). Ma suppongo che l'applicazione della console sarebbe fallita se ci fossero delle dipendenze mancanti. – vnammour

+0

Vale la pena imparare come usare procmon, dato che le cose ovvie non stanno risolvendo il tuo problema, potresti provare a risolvere quello sbagliato. Procmon aiuta spesso a vedere di cosa si tratta. –

1

Volevo solo aggiornare questo thread. Si è scoperto che il problema era esclusivo per la mia macchina. Lo stesso codeset ha funzionato come un incantesimo su una macchina diversa, la stessa versione di Windows (Windows XP 32 bit, SP2). Su entrambe le macchine è stato utilizzato Visual Studio 2008 per creare il servizio. Grazie mille per tutti i commenti e la risposta. Lo apprezzo.

Problemi correlati