2011-10-26 11 views
7

Ho un programma C# (framework di destinazione .NET 4.0) che effettua chiamate a oggetti COM (codice non gestito), tutti gli oggetti gestiti correttamente , distrutto quando non più necessario, ecc.Errore C# "Tentativo di leggere o scrivere memoria protetta" o "Componente esterno ha generato un'eccezione"

Ho anche poche eccezioni di gestione, prova/cattura blocchi senza eccezioni personalizzate. Tuttavia alcune volte questo programma si è arrestato in modo anomalo, funziona il più delle volte, il comportamento casuale. stack anche variare, ad esempio:

System.AccessViolationException was unhandled 
    Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
    Source=System.Windows.Forms 
    StackTrace: 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.Run(Form mainForm) 
     at IndexerTester.Program.Main() in D:\Tester\Program.cs:line 17 
    InnerException: 

Nel Program.cs, Linea 17: Application.Run (new Form1());

System.Runtime.InteropServices.SEHException was unhandled 
    Message=External component has thrown an exception. 
    Source=System.Windows.Forms 
    ErrorCode=-2147467259 
    StackTrace: 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.Run(Form mainForm) 
     at IndexerTester.Program.Main() in D:\Tester\Program.cs:line 17 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 

Sono in fase di isolamento per scoprire la radice di questo errore.

  • Avete suggerimenti di questo errore?
  • Qualsiasi suggerimento su intercettare queste eccezioni ed uscire con garbo.

Grazie per il vostro aiuto.

+0

È necessario eseguire il debug del codice nativo. Ciò richiede un debugger non gestito. –

+0

Passa i riferimenti sugli oggetti .NET ai componenti COM? – Seb

risposta

0

Uno dei vostri coomponents COM causa l'eccezione, come indicato dal:

Messaggio = componente esterno ha generato un'eccezione

Queste due linee dovrebbero aiutare a individuare quale componente COM e la chiamata metodo che causa il problema:

at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 

Suppongo che tu abbia scritto un wrapper per interfacciare questi componenti COM? O stai usando chiamate Invoke dirette?

Forse le informazioni di InnerException potrebbero fornire ulteriori dettagli.

Fondamentalmente cercare qualsiasi cosa che si possa riconoscere correlata a questi componenti COM.

6

L'origine delle eccezioni sono codice non modificato e molto probabilmente i componenti COM. La traccia dello stack indica che le eccezioni sono catturate nel tuo loop di messaggi e questo potrebbe essere il risultato di effettuare chiamate cross apartment dal tuo codice .NET in un oggetto COM in uno STA (Single Threaded Apartment). Le chiamate ai metodi vengono quindi sottoposte a un marshalling e inviate tramite i messaggi di Windows al componente.

Non c'è niente di sbagliato nel fare chiamate in appartamento, ma ho visto alcuni componenti COM che non eseguivano il corretto marshalling quando venivano forniti puntatori da un altro appartamento e, in generale, ignoravano le regole di threading in COM. Se c'è un qualsiasi tipo di multi-threading nella tua applicazione dovresti assolutamente dare un'occhiata a questo. Questi oggetti COM "danneggiati" si comportano bene quando vengono chiamati dal thread STA principale, ma potrebbero non riuscire quando vengono chiamati o creati su thread diversi.

Per essere più specifici: diciamo che il thread dell'interfaccia utente dell'applicazione all'avvio entra in uno STA (Single Threaded Apartment) e crea il componente COM. Quindi si crea un nuovo thread (che si troverà in un altro apartment) e da questo thread si chiama un metodo sul componente COM. Questa è una chiamata tra appartamenti. Il tuo componente COM può essere eseguito solo sul thread dell'interfaccia utente (il thread dell'appartamento in cui vive).Il framework COM noterà che si sta effettuando una chiamata tra appartamenti e che serializzerà la chiamata in un buffer (marshall la chiamata in COM). Questo buffer viene quindi inviato al thread dell'interfaccia utente utilizzando un messaggio di Windows. Se la tua applicazione non ha una finestra COM creerà una finestra nascosta per ricevere questi messaggi. Il ciclo del messaggio dell'applicazione decomprimerà quindi la chiamata marshalled e la eseguirà sul thread dell'interfaccia utente.

Ora, si assume che tu o il componente COM non comprendiate le regole degli appartamenti COM e del marshalling. Uno degli argomenti nella chiamata al metodo è un puntatore o qualcosa che si risolve in un puntatore e questo puntatore non è valido nell'appartamento del componente COM. Quindi, quando il componente COM derefaccia il puntatore si ottiene un errore. Il runtime .NET rileverà questo e genererà uno dei due tipi di eccezione che vedi. Tuttavia, questa eccezione viene generata nel loop dei messaggi del thread dell'interfaccia utente, un codice a cui non si ha accesso. L'utilizzo di un blocco try-catch al chiamante non aiuta a rilevare l'eccezione poiché viene generata su un altro thread. Ad ogni modo, non dovresti prendere l'eccezione perché è un segno di qualcosa di veramente brutto nella tua applicazione.

Per la registrazione il codice di errore -2147467259 è 0x8004005 che si traduce in E_FAIL. Non molto utile, ma gli errori che si verificano sono molto probabilmente dovuti a puntatori non validi utilizzati nel componente COM.

Per risolvere questo problema è necessario utilizzare i componenti COM correttamente e/o correggere eventuali codici danneggiati nei componenti.

+0

Sfortunatamente, non ho accesso all'origine del componente COM. Mi chiedo perché l'eccezione non venga catturata nel mio gestore di eccezioni generale. Qualche pensiero? – Din

+0

Ho modificato la mia domanda per spiegare perché non è possibile rilevare le eccezioni. –

Problemi correlati