Word 2010自动化:为什么我的应用程序崩溃,而excel显示错误462 我使用C++来实现微软Word 2010自动化。当用户关闭应用程序并且我的程序想要使用以前获得的IDispatch接口时,程序崩溃(未处理的异常)。Excel中的Simular VBA代码给出“错误462:远程服务器不存在”错误。如何检测应用程序已被用户以Excel的方式关闭 #ifdef __NO_PRECOMPILED_HEADERS__ #include "generic/platformdefs.h" #endif #include "test_word.h" /* * Include the right atlbase.h (depends on the compiler) */ #include "compat/which_atlbase.h" static OLECHAR FAR *VISIBLE = { OLESTR( "Visible" ) } ; static OLECHAR FAR *QUIT = { OLESTR( "quit" ) } ; static void VarSetBool( VARIANT *v , BOOL value ) { V_VT( v ) = VT_BOOL ; V_BOOL( v ) = value ? VARIANT_TRUE : VARIANT_FALSE ; } static void DispatchPropertyPut ( CComPtr<IDispatch> dispatch , OLECHAR FAR *property , VARIANT *value ) { HRESULT status ; DISPID dispid , propertyput ; DISPPARAMS parameters ; UINT n_argument_error; VARIANT result ; /* * Get the dispatch id of the method and arguments to invoke */ status = dispatch->GetIDsOfNames( IID_NULL , &property , 1 , LOCALE_USER_DEFAULT , &dispid ) ; if( !SUCCEEDED( status ) ) { throw( 1 ) ; } /* * Initialize result */ VariantInit( &result ) ; /* * need to be able to take the address of this */ propertyput = DISPID_PROPERTYPUT ; /* * Setup the parameters */ parameters.cNamedArgs = 1 ; parameters.rgdispidNamedArgs = &propertyput ; parameters.cArgs = 1 ; parameters.rgvarg = value ; /* * Get the object */ status = dispatch->Invoke( dispid , IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT , &parameters , &result , 0, &n_argument_error ) ; /* * Cleanup result if any */ VariantClear( &result ) ; /* * Success ? */ if( !SUCCEEDED( status ) ) { throw( 2 ) ; } } static void DispatchInvoke ( CComPtr<IDispatch> dispatch , OLECHAR FAR *method ) { DISPID dispid ; HRESULT status ; DISPPARAMS parameters ; status = dispatch->GetIDsOfNames( IID_NULL , &method , 1 , LOCALE_USER_DEFAULT , &dispid ) ; if( !SUCCEEDED( status ) ) { throw( 3 ) ; } parameters.cNamedArgs = 0 ; parameters.rgdispidNamedArgs = 0 ; parameters.cArgs = 0 ; parameters.rgvarg = 0 ; status = dispatch->Invoke( dispid , IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD , &parameters , 0 , 0 , 0 ) ; if( !SUCCEEDED( status ) ) { throw( 4 ) ; } } void test_word( int argc , char *argv[] , void *data ) { CComPtr<IDispatch> word ; VARIANT v ; HRESULT hr ; OleInitialize( NULL ) ; try { /* * The metrowerks compiler doesn't handle __uuidof() */ # ifdef __MWERKS__ hr = word.CoCreateInstance( OLESTR( "Word.Application" ) , IID_IDispatch , 0 , CLSCTX_SERVER ) ; # else hr = word.CoCreateInstance( OLESTR( "Word.Application" ) , 0 , CLSCTX_SERVER ) ; # endif if( !SUCCEEDED( hr ) ) { throw( 6 ) ; } VariantInit( &v ) ; VarSetBool( &v , TRUE ) ; DispatchPropertyPut( word , VISIBLE , &v ) ; DispatchInvoke( word , QUIT ) ; VarSetBool( &v , FALSE ) ; /* * This will crash the application */ DispatchPropertyPut( word , VISIBLE , &v ) ; } catch( int where ) { fprintf( stderr , "Exception caught %d\n" , where ) ; } word.Release() ; OleUninitialize() ; }

Word 2010自动化:为什么我的应用程序崩溃,而excel显示错误462 我使用C++来实现微软Word 2010自动化。当用户关闭应用程序并且我的程序想要使用以前获得的IDispatch接口时,程序崩溃(未处理的异常)。Excel中的Simular VBA代码给出“错误462:远程服务器不存在”错误。如何检测应用程序已被用户以Excel的方式关闭 #ifdef __NO_PRECOMPILED_HEADERS__ #include "generic/platformdefs.h" #endif #include "test_word.h" /* * Include the right atlbase.h (depends on the compiler) */ #include "compat/which_atlbase.h" static OLECHAR FAR *VISIBLE = { OLESTR( "Visible" ) } ; static OLECHAR FAR *QUIT = { OLESTR( "quit" ) } ; static void VarSetBool( VARIANT *v , BOOL value ) { V_VT( v ) = VT_BOOL ; V_BOOL( v ) = value ? VARIANT_TRUE : VARIANT_FALSE ; } static void DispatchPropertyPut ( CComPtr<IDispatch> dispatch , OLECHAR FAR *property , VARIANT *value ) { HRESULT status ; DISPID dispid , propertyput ; DISPPARAMS parameters ; UINT n_argument_error; VARIANT result ; /* * Get the dispatch id of the method and arguments to invoke */ status = dispatch->GetIDsOfNames( IID_NULL , &property , 1 , LOCALE_USER_DEFAULT , &dispid ) ; if( !SUCCEEDED( status ) ) { throw( 1 ) ; } /* * Initialize result */ VariantInit( &result ) ; /* * need to be able to take the address of this */ propertyput = DISPID_PROPERTYPUT ; /* * Setup the parameters */ parameters.cNamedArgs = 1 ; parameters.rgdispidNamedArgs = &propertyput ; parameters.cArgs = 1 ; parameters.rgvarg = value ; /* * Get the object */ status = dispatch->Invoke( dispid , IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT , &parameters , &result , 0, &n_argument_error ) ; /* * Cleanup result if any */ VariantClear( &result ) ; /* * Success ? */ if( !SUCCEEDED( status ) ) { throw( 2 ) ; } } static void DispatchInvoke ( CComPtr<IDispatch> dispatch , OLECHAR FAR *method ) { DISPID dispid ; HRESULT status ; DISPPARAMS parameters ; status = dispatch->GetIDsOfNames( IID_NULL , &method , 1 , LOCALE_USER_DEFAULT , &dispid ) ; if( !SUCCEEDED( status ) ) { throw( 3 ) ; } parameters.cNamedArgs = 0 ; parameters.rgdispidNamedArgs = 0 ; parameters.cArgs = 0 ; parameters.rgvarg = 0 ; status = dispatch->Invoke( dispid , IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD , &parameters , 0 , 0 , 0 ) ; if( !SUCCEEDED( status ) ) { throw( 4 ) ; } } void test_word( int argc , char *argv[] , void *data ) { CComPtr<IDispatch> word ; VARIANT v ; HRESULT hr ; OleInitialize( NULL ) ; try { /* * The metrowerks compiler doesn't handle __uuidof() */ # ifdef __MWERKS__ hr = word.CoCreateInstance( OLESTR( "Word.Application" ) , IID_IDispatch , 0 , CLSCTX_SERVER ) ; # else hr = word.CoCreateInstance( OLESTR( "Word.Application" ) , 0 , CLSCTX_SERVER ) ; # endif if( !SUCCEEDED( hr ) ) { throw( 6 ) ; } VariantInit( &v ) ; VarSetBool( &v , TRUE ) ; DispatchPropertyPut( word , VISIBLE , &v ) ; DispatchInvoke( word , QUIT ) ; VarSetBool( &v , FALSE ) ; /* * This will crash the application */ DispatchPropertyPut( word , VISIBLE , &v ) ; } catch( int where ) { fprintf( stderr , "Exception caught %d\n" , where ) ; } word.Release() ; OleUninitialize() ; },c++,vba,automation,ms-word,com,C++,Vba,Automation,Ms Word,Com,这更多的是一个评论,但评论是有限的…它可以作为一个解决方案 嗯,通常你不会做你正在做的事情。您必须在第二个属性put之前设置断点,并在该点手动关闭Word。通常,您将从Word捕获事件,然后当Word关闭时,您将收到通知,然后知道不再使用接口指针。为了防止捕捉不到事件,我建议首先创建应用程序以获取IUnknown指针。然后,当您想要调用IDispatch时,查询IDispatch,然后进行调用,然后释放IDispatch 当您首次使用IUnknown创建时,它将为您创建进程内处理程序IUnkno

这更多的是一个评论,但评论是有限的…它可以作为一个解决方案

嗯,通常你不会做你正在做的事情。您必须在第二个属性put之前设置断点,并在该点手动关闭Word。通常,您将从Word捕获事件,然后当Word关闭时,您将收到通知,然后知道不再使用接口指针。为了防止捕捉不到事件,我建议首先创建应用程序以获取IUnknown指针。然后,当您想要调用IDispatch时,查询IDispatch,然后进行调用,然后释放IDispatch

当您首次使用IUnknown创建时,它将为您创建进程内处理程序IUnknown。在第一次调用query for IDispatch时,它将在此时实际启动Word。在随后为IDispatch调用QI并进行调用时,如果Word已关闭,则处理程序可能足够聪明,可以优雅地失败,也可能不会。但是,如果你不想看比赛的话,我会从那里开始

从Word中获取事件并查找结束或结束事件的真正正确方法


哇。。。只看单词事件。看起来有退出事件,但没有关闭或关闭前事件或类似事件。因此,您希望捕获退出事件。之后,设置一个标志或释放IDispatch界面,再也不要使用它。

有趣。Word 2010全部修补好了吗?我针对Word 2016(我安装的)运行了以下命令。它还使用VisualStudio 2017,但应该在过去10年中在任何VisualC++中编译:

#include <comdef.h>
#include <atlbase.h>

class COleInitialize
{
    public:
    COleInitialize()
    {
        OleInitialize(NULL);
    }
    ~COleInitialize()
    {
        OleUninitialize();
    }
};

int main(int argc, char* argv[])
{
    COleInitialize _oleinit;

    IUnknownPtr lpUnk;

    lpUnk.CreateInstance(L"Word.Application");

    CComDispatchDriver disp(lpUnk);
    disp.PutPropertyByName(L"Visible", &_variant_t(VARIANT_TRUE));

    MessageBox(NULL, "Close Word", "Prompt", MB_OK);

    return 0;
}
#包括
#包括
类初始化
{
公众:
coleignize()
{
OleInitialize(NULL);
}
~coleignize()
{
OleUninitialize();
}
};
int main(int argc,char*argv[])
{
COleInitialize oleinit;
IUnknownPtr lpUnk;
lpUnk.CreateInstance(L“Word.Application”);
CCOMDISP河区(lpUnk);
显示PutPropertyByName(L“可见”和_variant_t(variant_TRUE));
消息框(空,“关闭单词”,“提示”,MB_OK);
返回0;
}

@JesperJuhl关于版本的评论与问题无关。COM接口在过去十年中没有改变。在C++的顶级代码中,为什么在OrutUnTialIIIe()之后调用Word.Relasee()?这应该是以前的事了。在取消初始化COM/OLE之前,您应该释放所有COM指针。@Joseph Willcoxson您当然是对的,但这并不能解决在给定位置崩溃的问题
throw没有意义。程序中止以提醒您代码是非法的,没有可重新调用的活动异常<代码>捕获(…)
也是一种非常糟糕的做法,关注正确的错误报告对于取得成功非常重要。@RamblinRose Yep-使用Codewarrior IDE已经超过20年了(自2000年以来的当前版本)。多亏了他们的插件设计,我创建了支持微软和GNU工具链的插件。我发现问题出在word上。如果我只是启动word然后退出,com对象的最终版本会使应用程序崩溃。当我对outlook或publisher执行同样的操作时,一切都很顺利。对我来说,实际的问题是,为什么Excel中的VBA可以知道服务器不再可用,并且可能导致应用程序崩溃。有没有一种方法可以像vba处理它一样处理它(COM异常0x800706BA)?您有没有一个示例(希望是没有MFC的C/C++)如何从word获取事件。我试图从打开的文档(IDocumentEvents)中获取事件,但从未收到任何事件。我了解IConnectionPointFactory和IConnectionPoint。
#include <comdef.h>
#include <atlbase.h>

class COleInitialize
{
    public:
    COleInitialize()
    {
        OleInitialize(NULL);
    }
    ~COleInitialize()
    {
        OleUninitialize();
    }
};

int main(int argc, char* argv[])
{
    COleInitialize _oleinit;

    IUnknownPtr lpUnk;

    lpUnk.CreateInstance(L"Word.Application");

    CComDispatchDriver disp(lpUnk);
    disp.PutPropertyByName(L"Visible", &_variant_t(VARIANT_TRUE));

    MessageBox(NULL, "Close Word", "Prompt", MB_OK);

    return 0;
}