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.
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
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 ;-) –
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