我是MFC的com,当处理异常的时候,我希望能抛出异常,让JS可以捕捉的到,但现在很多地方讲到的都是基于ATL的error返回,我查了些资料,
                  CComQIPtr< ICreateErrorInfo> spCEI;
::CreateErrorInfo( &spCEI ); spCEI->SetGUID( IID_IDeskConsole ); // 发生错误的接口IID
spCEI->SetSource( L"EcmUploadComponent.EcmDfcUpload" ); // ProgID
spCEI->SetDescription( L"cuowuxinxi");
CComQIPtr < IErrorInfo > spErrInfo = spCEI;
if( spErrInfo )
::SetErrorInfo( 0, spErrInfo );
throw _com_error(hr, spErrInfo);
但这样方式的处理还是不能解决问题,直接就出现VC的红叉叉了。不知道可以如何解决

解决方案 »

  1.   

    throw _com_error是抛出C++异常,不是JS异常。
    你的组件不是有方法吗?方法不是返回HRESULT吗?直接返回E_...开头的值就能被JS捕获,只要不是返回S_OK或者S_FALSE就可以了。
      

  2.   

    那我怎么才能把一些出错的信息带出去呢,比如CString的值
      

  3.   

    看看IDispatch::Invoke的倒数第二个参数
      

  4.   

    有点迷糊。我现在的理解是这样,只要我的com中的调用函数返回是HRESULT,当出现异常的时候,可以返回系统已经定义好的一些以E开头的HRESULT,这样JS就可以catch到这些信息。接下来的问题可能就是我怎么构造出我自己的HRESULT,把我自己的错误信息放进去了。然后你说了IDispatch::Invoke的倒数第二个参数。这句话的意思是我有些不明白
      

  5.   

    在com接口里添加方法的时候,哪个返回值是对应VT_HRESULT呢?
    我的声明改成DISP_FUNCTION_ID(DeskConsole, "createFolder", dispidcreateFolder, createFolder, VT_HRESULT, VTS_BSTR),怎么就直接执行报错了呢
      

  6.   

    js以前偶尔试过下 好像没法拿到自定义的IErrorInfo中返回的字符串描述
    后来是干脆不用HRESULT 把错误号和描述文本做一个retval参数返回了
      

  7.   

    我希望能够以try,catch的方式在JS上进行处理。从原理上来说,我们用一些ADO组件进行操作的时候,他里面的错误貌似是可以抛出来catch到的才是啊。现在我抛出_com_error,直接就红叉了,IE崩溃
      

  8.   

    CComQIPtr < IErrorInfo > spErrInfo = spCEI; 
    不要用智能指针,这样出了作用域话会被释放掉的,你这样试试看行不行.IErrorInfo* pIErrorInfo = NULL;
    spCEI->QueryInterface(IID_IErrorInfo, (void**)&pIErrorInfo);
    SetErrorInfo(hr, pIErrorInfo);
    throw _com_error(hr, pIErrorInfo);
    下面是我的代码,我没有在JS下测试过,不过在COM里是可以用的,你可以参考一下!
    //-----------------------------------------------------------
    // Name : _ComIssueError()
    // Desc : Issue COM error information
    //-----------------------------------------------------------
    void _ComIssueError(HRESULT hr, LPCTSTR pszSource, LPCTSTR pszDescrption, 
       REFGUID rguid, LPCTSTR pszHelpFile, DWORD dwHelpContext)
    {
    CComQIPtr<ICreateErrorInfo> pICreateErrorInfo;
    IErrorInfo* pIErrorInfo;
    if( SUCCEEDED(CreateErrorInfo(&pICreateErrorInfo)) )
    {
    USES_CONVERSION;
    pICreateErrorInfo->SetSource(T2OLE(pszSource));
    pICreateErrorInfo->SetDescription(T2OLE(pszDescrption));
    if( rguid != GUID_NULL )
    pICreateErrorInfo->SetGUID(rguid);
    if( pszHelpFile != NULL )
    pICreateErrorInfo->SetHelpFile(T2OLE(pszHelpFile));
    if( dwHelpContext != 0 )
    pICreateErrorInfo->SetHelpContext(dwHelpContext);
    if( SUCCEEDED(pICreateErrorInfo->QueryInterface(IID_IErrorInfo, (void**)&pIErrorInfo)) )
    {
    SetErrorInfo(hr, pIErrorInfo);
    throw _com_error(hr, pIErrorInfo);
    }
    }
    }
      

  9.   

    还是不行,现在奇怪的是为什么我声明如下DISP_FUNCTION_ID(DeskConsole, "createFolder", dispidcreateFolder, createFolder, VT_HRESULT, VTS_BSTR)
    函数实体HRESULT DeskConsole::createFolder(LPCSTR folderName )这样会不可以呢,把VT_HRESULT改成别的就可以
      

  10.   

    不是让你设置一个HRESULT类型的返回值参数,而是所有属性或方法的返回值(注意:COM组件的所有get/put/方法的返回值都是HRESULT)。
    有一些标准的错误类型,比如E_OUTOFMEMORY,脚本引擎都能识别并抛出对应的异常,如果需要自定义异常,函数返回值应该设置成DISP_E_EXCEPTION,同时在组件的Invoke方法的倒数第二个参数(EXCEPINFO指针指向的结构)中填充自己的内容。MFC有点麻烦,它做了一层封装,隐藏了HRESULT细节,我看看MFC中有没有解决办法。
      

  11.   

    我花了几个小时把MFC转化成了ATL,现在可以通过返回HRESULT为OLE_E_的常量,在JS上顺利catch,但没法设置自己的错误message,这个不知道有没办法解决
      

  12.   

    当然我也可以在JS的catch里再来调用类似COM.GetLastMessage的办法来获得出错信息,但最好是能在exception里抛出的时候带上
      

  13.   

    1、你的组件同时实现ISupportErrorInfo接口
    2、当需要抛出异常时,调用CreateErrorInfo创建一个IErrorInfo,再调用SetErrorInfo,最后返回E_开头的HRESULT。注意不能使用throw语句,这个是用于C++的,不是脚本。
    3、在ISupportErrorInfo::InterfaceSupportsErrorInfo实现里判断是否已经设置了错误信息,返回S_OK或者S_FALSE
      

  14.   

    在ATL里好像还是比较容易解决,用return CComCoClass::Error方法就可以了,但字符串好像还有长度限制
      

  15.   

    试试用js.net来写脚本 语法也基本一样但是功能强 反正2k3以上的机器都带了.net framework