2013-05-08 16 views
6

Ho controllato la risposta a: How can I return both an error string and error code to VB6 from an ATL activex control?Come restituire il codice di errore positivo da ATL a VB6?

Sono in grado di restituire codici di errore negativi personalizzati, vale a dire con il set di bit di gravità e un messaggio di errore personalizzato. Ma, mi piacerebbe essere in grado di generare un codice che VB6 presenterà come un numero positivo per Err.Number che l'utente troverà più facile da usare. Sono abbastanza sicuro che possa essere fatto da quando la DLL DAO 3.6 di Microsoft è in grado di farlo. Ad esempio, restituisce Err.Number = 3078 con Err.Description "Il database Microsoft Jet ..." se una tabella non esiste.

Nota che ho implementato ISupportErrorInfo, ecc. Per la segnalazione degli errori.

risposta

5

Annotare la risposta di Mark un po '. Ha ragione sull'uso di FACILITY_CONTROL. Inoltre, è necessario assicurarsi che il codice di errore sia maggiore di 512, in modo che non interferisca con i codici di errore del runtime VB6. Quindi utilizzare qualcosa del genere:

HRESULT MakeVB6Error(UINT errCode) { 
    assert(errCode > 0 && errCode < 65536 - 513); 
    return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_CONTROL, errCode + 513); 
} 
+0

Grazie, usando FACILITY_CONTROL ha fatto il trucco! – veneff

+0

Ecco una risposta simile su come fare la stessa cosa da C# (per quelli che arrivano qui tramite Google): [Sollevare i codici di errore stile VB positivo tramite l'interoperabilità COM da C#] (http://stackoverflow.com/a/32868308/ 588.306) – Deanna

4

VB esegue molti mapping dei valori HRESULT su valori Err.Number. Per esempio, se il HRESULT era 0x8007002, VB rompe giù utilizzando lo standard COM come segue:

Bit 31 - Severity (set to 1 in all errors) 
Bit 30 - Reserved 
Bit 29 - Customer Bit 
Bit 28 - Reserved 
Bit 27 
    - 16 Facility code 
Bit 15 
    - 0 Error code 

In pratica il nibble superiore è sempre 8. Il Fondo varia, e ti dice che tipo di errore che si tratta di . In questo caso, il codice della struttura è 0x007 (FACILITY_WIN32), il che significa che si tratta di un errore Win32 standard. I due byte inferiori rappresentano l'errore effettivo. Guardando in winerror.h, questo errore è 2 - ERROR_FILE_NOT_FOUND. VB è abbastanza intelligente per mappare questo errore all'errore VB standard 53 "File non trovato".

Nella documentazione VB, siamo sempre stati incoraggiati ad aggiungere il costante vbObjectError ai nostri numeri di errore quando li abbiamo sollevati da un componente VB. Questo era quasi equivalente a ORing del numero intero a 32 bit 0x80040000 del numero di errore (supponendo che fosse < = 65535). In questo caso, il codice della funzione era 0x4 (FACILITY_ITF) che indicava che l'errore veniva generato dall'interfaccia specifica di una coclasse. In pratica, questo ha reso i nostri numeri di errore grandi e negativi, e difficili da capire.

Quello che avremmo dovuto fare era ignorare la documentazione e sollevare semplicemente i numeri di errore. Dietro le quinte, VB OR aveva il suo codice impianto - 0xA (FACILITY_CONTROL). Tuttavia, ogni componente VB che vede un HRESULT con quel codice di impianto cancellerebbe automaticamente i primi due byte, quindi vedremmo il numero come positivo, non negativo.

Suggerisco di utilizzare FACILITY_CONTROL per i propri numeri di errore. Altri client COM potrebbero essere confusi, ma i client VB vedono il tuo numero di errore come positivo.

In alternativa, è possibile ignorare il normale meccanismo HRESULT per i valori di ritorno. Invece restituisci HRESULT = S_OK e usa un parametro [retval, out] alla fine della funzione per far sembrare che sia una funzione VB.

+0

Grazie, utilizzando FACILITY_CONTROL ha fatto il trucco! – veneff