C#无法捕获所有异常

时间:2015-06-25 15:50:11

标签: c# exception exception-handling mono try-catch

我正在编写一个C#应用程序(在Linux中使用mono,但这应该没关系)我正在使用duplicati dll进行编程。我希望程序永远不会崩溃所以我试图捕获每个异常。问题现在是抛出一个异常,我无法抓住它。也许来自一个帖子?!?

旁注:仅出于测试目的,我故意尝试备份到我没有权限的位置。如果我给予许可,那么我没有错误。

代码如下所示:

try {
    Interface i = new Interface(backend, options);
    result = i.Backup(folders.ToArray());
} catch (Exception e) {
    //Write to log.
    //Here is no throw; !!
}

我得到以下堆栈跟踪:

Error : System.Exception: Failed to retrieve file listing: Access to the path "/home/pi/test" is denied. ---> System.UnauthorizedAccessException: Access to the path "/home/pi/test" is denied.
  at System.IO.Directory.GetFileSystemEntries (System.String path, System.String searchPattern, FileAttributes mask, FileAttributes attrs) [0x00000] in <filename unknown>:0
  at System.IO.Directory.GetFiles (System.String path, System.String searchPattern) [0x00000] in <filename unknown>:0
  at System.IO.Directory.GetFiles (System.String path) [0x00000] in <filename unknown>:0
  at Duplicati.Library.Backend.File.List () [0x00000] in <filename unknown>:0
  at Duplicati.Library.Main.BackendWrapper.ListInternal () [0x00000] in <filename unknown>:0
  --- End of inner exception stack trace ---
  at Duplicati.Library.Main.BackendWrapper.ListInternal () [0x00000] in <filename unknown>:0
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0

为什么我无法捕捉到所有异常?我做错了吗?

2 个答案:

答案 0 :(得分:3)

Error : System.Exception: Failed to retrieve file listing: Access to the path...

嗯,这是一个托管异常,你应该能够抓住它,期间。 Duplicati正在将Interop用于本机库,并且该调用中的失败是调用堆栈所在的位置,但它正在通过托管调用堆栈展开和传播。

我写了一个非常快速的Duplicati示例,它捕获了所有异常......

没有例外:

mono HelloDup.exe "/tmp"
File: Local folder or drive

发现异常:

ls /home/private/privateinfo
ls: : Permission denied
mono HelloDup.exe "/home/private/privateinfo"
Exception: Access to the path "/home/private/privateinfo" is denied.: Type:System.UnauthorizedAccessException

发现异常:

mono HelloDup.exe "/foobar"
Exception: The folder /foobar does not exist: Type:Duplicati.Library.Interface.FolderMissingException

发现异常:

ls -l /noperms/private.txt
--w-------  1 root  wheel  0 Jun 25 14:16 /noperms/private.txt
mono HelloDup.exe "/noperms/private.txt"
Exception: The folder /noperms/private.txt does not exist: Type:Duplicati.Library.Interface.FolderMissingException

代码示例:

try {
    var file = new Duplicati.Library.Backend.File(args[0], options);
    file.CreateFolder();
    Console.WriteLine ("File: {0}", file.DisplayName);
} catch (Exception e) {
    Console.WriteLine ("Exception: {0}: Type:{1}", e.Message, e.GetType());
}

后续步骤:

我会检查你正在使用的Mono和Duplicati的版本......如果你是Mono的基本系统安装,你可能会落后于时代。我还使用xbuild编译Duplicati,所以我使用了GitHub主分支的HEAD。

答案 1 :(得分:1)

catch块可能会抛出异常吗?

无论如何,@ gunr2171想法的变体 - 创建一个单独的Vis。具有单个文件(类)的Studio项目及其所做的只是调用包含在try/catch中的主程序;所以这是应用程序的最顶层。

如果您的库是线程化的,它应该公开一些东西来测试线程异常;很像BackgroundWorker.RunWorkerCompleted event

注册AppDomain.UnhandledException事件

A simple tutorial

值得捕捉

自由使用Exception.Data属性。有时我会明确地在我的课程中覆盖ToString(),以便将其投入Exception.Data

在应用程序正文中尽可能地捕获(这似乎是OP所做的)。此上下文将帮助您在Exception.Data中捕获特别相关的信息。阅读库的 - 和.NET - 文档。

在应用程序的顶部有一个通用的try/catch

避免重新捕捉不会添加上下文的层。

重新投掷: throw e将堆栈跟踪丢弃到该点。而是throw

让您的应用程序更加健壮

  • 定义默认状态。 The null object pattern
  • 强制客户端使用您的构造函数。不要公开属性并期望客户端正确初始化。 Alan Kay强调说暴露属性(状态)不是面向对象的编程。
  • 我讨厌null字符串。以下是我最喜欢的实时生产代码:if(string.IsNullOrEmpty(myString.Trim()))

一些希望有用的链接