IPreviewHandler抛出无法捕获的异常

Bra*_*ith 3 c# com winforms

我已经将COM接口IPreviewHandler导入WinForms应用程序并使用它来显示各种类型文档的预览(我在注册表中查找相应预览处理程序的GUID,然后用于Activator.CreateInstance(guid)实例化特定的COM类.

非常适用于绝大多数文件类型 - Office格式,PDF,视频等 - 但是,在我实例化"Microsoft Windows TXT预览处理程序"之后{1531d583-8375-4d3f-b5fb-d23bbd169f22},使用包含普通.txt文件的流初始化它,设置边界预览窗口,然后最后调用DoPreview(),我得到一个异常,无法使用try ... catch捕获:

try {
    Type comType = Type.GetTypeFromCLSID(guid);
    object handler = Activator.CreateInstance(comType);

    if (handler is IInitializeWithStream) {
        Stream s = File.Open(filename, FileMode.Open);
        // this just passes the System.IO.Stream as the COM type IStream
        ((IInitializeWithStream)handler).Initialize(new StreamWrapper(s), 0);
    }
    else {
        throw new NotSupportedException();
    }

    RECT r = new RECT();
    r.Top = 0;
    r.Left = 0;
    r.Right = hostControl.Width;
    r.Bottom = hostControl.Height;

    ((IPreviewHandler)handler).SetWindow(hostControl.Handle, ref r);
    ((IPreviewHandler)handler).DoPreview();    // <-- crash occurs here
}
catch (Exception) {
    // this will never execute
}
Run Code Online (Sandbox Code Playgroud)

当我使用调试器时,Visual Studio Hosting Process崩溃了.没有调试器,应用程序崩溃而不触发AppDomain.UnHandledExceptionApplication.ThreadException事件.

我真的不介意我无法使用这种技术预览纯文本文件(Office格式的工作预览处理程序等足以满足我的应用程序的要求),但我担心如果用户选择我的应用程序会无法控制地崩溃一个.txt文件.有什么方法可以捕捉到这个错误并优雅地处理它?更好的是,有什么方法可以克服它并使处理程序工作?

Han*_*ant 7

我无法让GetPreviewHandlerGUID()识别.txt文件,并且必须直接注入GUID.使用Project + Properties,Debug,tick启用非托管代码调试时,您可以看到出现了什么问题.

调试器现在将停止问题并显示

遇到`STATUS_STACK_BUFFER_OVERRUN

调用堆栈的顶部如下所示:

kernel32.dll!_UnhandledExceptionFilter@4()  + 0x1a368 bytes 
shell32.dll!___report_gsfailure()  + 0xc8 bytes 
shell32.dll!CRTFPreviewHandler::_StreamInCallback()  + 0x74 bytes   
msftedit.dll!CLightDTEngine::ReadPlainText()  + 0xed bytes  
msftedit.dll!CLightDTEngine::LoadFromEs()  + 0x202b3 bytes  
msftedit.dll!CTxtEdit::TxSendMessage()  + 0x1e25f bytes 
msftedit.dll!_RichEditWndProc@16()  + 0x13d bytes   
Run Code Online (Sandbox Code Playgroud)

问题出在StreamInCallback()函数中.它由RichTextBox调用,用于显示加载文件的预览(msftedit.dll).此回调函数中的代码有一个错误,它会破坏用于检测堆栈帧因缓冲区溢出而损坏的"canary".

这是微软采取的防止病毒通过缓冲区溢出注入自身的措施的一部分.Visual Studio中用于C/C++语言的/ GS编译选项.一旦检测到,CRT就会很快终止程序.这种情况发生时没有异常被提升,堆栈无法安全解开,因为它已被泄露.因此,CLR无法捕获异常.

此错误特定于TXT文件查看器.除了不使用它之外,你无能为力.将此错误报告给connect.microsoft.com可能没用,他们会将其关闭为"外部".这是一个微妙的提示,当您让非托管代码在您的程序中运行时会发生什么;)