Używam obiektu COM (MODI) z mojej aplikacji .net. Wywoływana przeze mnie metoda zgłasza wyjątek System.AccessViolationException, który jest przechwytywany przez program Visual Studio. Dziwne jest to, że zawinąłem moje wywołanie w try catch, który ma programy obsługi dla AccessViolationException, COMException i wszystkiego innego, ale kiedy Visual Studio (2010) przechwytuje AccessViolationException, debugger przerywa wywołanie metody (doc.OCR), a jeśli przejdę przez nie, przechodzi do następnej linii zamiast wchodzić do bloku catch. Dodatkowo, jeśli uruchomię to poza Visual Studio, moja aplikacja ulegnie awarii. Jak mogę obsłużyć ten wyjątek, który jest zgłaszany w obiekcie COM?
MODI.Document doc = new MODI.Document();
try
{
doc.Create(sFileName);
try
{
doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false);
sText = doc.Images[0].Layout.Text;
}
catch (System.AccessViolationException ex)
{
//MODI seems to get access violations for some reason, but is still able to return the OCR text.
sText = doc.Images[0].Layout.Text;
}
catch (System.Runtime.InteropServices.COMException ex)
{
//if no text exists, the engine throws an exception.
sText = "";
}
catch
{
sText = "";
}
if (sText != null)
{
sText = sText.Trim();
}
}
finally
{
doc.Close(false);
//Cleanup routine, this is how we are able to delete files used by MODI.
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
doc = null;
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
Exception
obsługi (tymczasowo!), Aby przechwycić wszystkie wyjątki i zobaczyć, czym właściwie jest wyjątek ?Odpowiedzi:
W .NET 4.0 środowisko uruchomieniowe obsługuje pewne wyjątki zgłoszone jako błędy obsługi błędów strukturalnych systemu Windows (SEH) jako wskaźniki stanu uszkodzonego. Te wyjątki stanu uszkodzonego (CSE) nie mogą zostać przechwycone przez standardowy kod zarządzany. Nie będę się zagłębiać w dlaczego i jak tu jest. Przeczytaj ten artykuł o CSE w .NET Framework 4.0:
http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035
Ale jest nadzieja. Można to obejść na kilka sposobów:
Przekompiluj jako zestaw .NET 3.5 i uruchom go w .NET 4.0.
Dodaj wiersz do pliku konfiguracyjnego aplikacji w elemencie configuration / runtime:
<legacyCorruptedStateExceptionsPolicy enabled="true|false"/>
Udekoruj metody, w których chcesz przechwycić te wyjątki,
HandleProcessCorruptedStateExceptions
atrybutem. Szczegółowe informacje można znaleźć pod adresem http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035 .EDYTOWAĆ
Wcześniej odnosiłem się do posta na forum, aby uzyskać dodatkowe informacje. Ale ponieważ Microsoft Connect został wycofany, oto dodatkowe szczegóły na wypadek zainteresowania:
Od Gaurava Khanny, programisty z zespołu Microsoft CLR
Następnie przechodzi do dokumentacji dotyczącej obiektu HandleProcessCorruptedStateExceptionsAttribute i do powyższego artykułu. Wystarczy powiedzieć, że zdecydowanie warto przeczytać, jeśli rozważasz wyłapywanie tego typu wyjątków.
źródło
HandleProcessCorruptedStateExceptions
działa dla mnie w .Net 4.5.OR
” sposób na zrobienie tego. :)Dodaj następujący element do pliku konfiguracyjnego, a zostanie on przechwycony w bloku try catch. Słowo ostrzeżenia ... spróbuj uniknąć tej sytuacji, ponieważ oznacza to, że doszło do jakiegoś naruszenia.
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>
źródło
Zebrane z powyższych odpowiedzi, działały dla mnie, wykonałem następujące kroki, aby to złapać.
Krok # 1 - Dodaj następujący fragment do pliku konfiguracyjnego
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>
Krok 2
Dodaj -
[HandleProcessCorruptedStateExceptions] [SecurityCritical]
w górnej części funkcji, którą łączysz, złap wyjątek
źródło: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html
źródło
Microsoft: „Wyjątki dotyczące uszkodzonego stanu procesu to wyjątki wskazujące, że stan procesu został uszkodzony. Nie zalecamy uruchamiania aplikacji w tym stanie ..... Jeśli masz absolutną pewność , że chcesz zachować ich obsługę wyjątki, musisz zastosować
HandleProcessCorruptedStateExceptionsAttribute
atrybut „Microsoft: „Użyj domen aplikacji do izolowania zadań, które mogą spowolnić proces”.
Poniższy program ochroni twoją główną aplikację / wątek przed nieodwracalnymi awariami bez ryzyka związanego z używaniem
HandleProcessCorruptedStateExceptions
i<legacyCorruptedStateExceptionsPolicy>
public class BoundaryLessExecHelper : MarshalByRefObject { public void DoSomething(MethodParams parms, Action action) { if (action != null) action(); parms.BeenThere = true; // example of return value } } public struct MethodParams { public bool BeenThere { get; set; } } class Program { static void InvokeCse() { IntPtr ptr = new IntPtr(123); System.Runtime.InteropServices.Marshal.StructureToPtr(123, ptr, true); } private static void ExecInThisDomain() { try { var o = new BoundaryLessExecHelper(); var p = new MethodParams() { BeenThere = false }; Console.WriteLine("Before call"); o.DoSomething(p, CausesAccessViolation); Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); //never stops here } catch (Exception exc) { Console.WriteLine($"CSE: {exc.ToString()}"); } Console.ReadLine(); } private static void ExecInAnotherDomain() { AppDomain dom = null; try { dom = AppDomain.CreateDomain("newDomain"); var p = new MethodParams() { BeenThere = false }; var o = (BoundaryLessExecHelper)dom.CreateInstanceAndUnwrap(typeof(BoundaryLessExecHelper).Assembly.FullName, typeof(BoundaryLessExecHelper).FullName); Console.WriteLine("Before call"); o.DoSomething(p, CausesAccessViolation); Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); // never gets to here } catch (Exception exc) { Console.WriteLine($"CSE: {exc.ToString()}"); } finally { AppDomain.Unload(dom); } Console.ReadLine(); } static void Main(string[] args) { ExecInAnotherDomain(); // this will not break app ExecInThisDomain(); // this will } }
źródło
Możesz spróbować użyć AppDomain.UnhandledException i sprawdzić, czy to pozwoli Ci go złapać.
**EDYTOWAĆ*
Oto więcej informacji, które mogą być przydatne (to długa lektura).
źródło