关于GetActiveObject失败的灵异现象的解决
来源:互联网 发布:python tempfile 删除 编辑:程序博客网 时间:2024/06/13 07:37
最近做一个WORD AUTOMATION的程序,封装成DLL来实现WORD的自动化。开始进行的很顺利,在中文系统下没有任何问题,可是当拿到俄文系统时,问题出现了。而且出现得很是灵异。现象是,当把程序做成EXE时,没有任何问题,封装成DLL时,GetActiveObject就取不到活动的WORD文档了。反复测试发现了非常非常灵异的情况,就是当打开两个以上的文档时,GetActiveObject就可用。这个问题困扰了我好几天,真是百思不解呀。GOOGLE,百度,CSDN,MSDN,国内外的资料翻了个遍,也没找到原因。受了几天的折磨,就在快要放弃的时候,突然峰回路转,在MS support网站上找到了原因。苍天呀,原来是被微软给玩了一把。不过也怪自己,这遍文章之前找资料的时候也曾经见到过,只是当时看的不是特别认真,以为自己遇到的问题不是一回事,结果在这个问题上浪费了很多的时间。
这个故事告诉我们,一定要坚持,更一定要认真~~~~~~
我的代码:
CLSID clsid;
HRESULT hr;
hr=::CLSIDFromProgID(L"Word.Application",&clsid);
if(FAILED(hr))
{
AfxMessageBox(_T("NO OFFICE"));
return;
}
IUnknown *pUnknown=NULL;
IDispatch *pDispatch=NULL;
_Application app=NULL;
Selection sel=NULL;
hr=::GetActiveObject(clsid,NULL,&pUnknown); //在俄文系统不可用
if(FAILED(hr))
{
AfxMessageBox(_T("NO WORD"));
return;
}
下面是微软给出的原因:Although the Office application is running, it might not be registered in the Running Object Table (ROT). A running instance of an Office application must be registered in the ROT before it can be attached to using GetObject (Visual Basic) or GetActiveObject (Visual C++).
When an Office application starts, it does not immediately register its running objects. This optimizes the application's startup process. Instead of registering at startup, an Office application registers its running objects in the ROT once it loses focus. Therefore, if you attempt to use GetObject or GetActiveObject to attach to a running instance of an Office application before the application has lost focus, you might receive one of the errors above.
简单的说就是,MS对OFFICE的启动进行了优化以提高OFFICE的启动速度(不过不知道为什么没有对中文OFFICE进行优化),即不是OFFICE一启动就在ROT表进行注册,而是在OFFICE失去一次焦点之后,才进行注册。这就是我遇到的为什么只有在打开两个以上的WORD文档时GetActiveObject才能取到。实际情况不是非要打开两个以上的文档,只要使打开的WORD文档失去一次焦点就可以了,即不让它激活,也就是WORD文档窗变成灰的,或是说让WORD不在最前面(我也不知道严格讲应该怎样表达),就相当于你打开一个WORD文档,然后用鼠标点一下其他的窗口。不知道这么说够不够通俗易懂。这样,OFFICE就会去ROT进行注册,你的GetActiveObject也就能取到了。就可以进行下面的工作了。呵呵。
MS给出的解决方案:
Workaround for C++
If you are programming in C++, the following code sample demonstrates a similar workaround to that shown in the above Visual Basic sample. Notice that SetForegroundWindow is used to move focus away from Excel, allowing it to register its running objects.
//Store the handle of the currently active window...
HWND hwndCurrent = ::GetForegroundWindow();
//Launch Excel and wait until it is waiting for
//user input...
STARTUPINFO Start;
PROCESS_INFORMATION ProcInfo;
ZeroMemory(&Start,sizeof(STARTUPINFO));
Start.cb=sizeof(Start);
Start.dwFlags = STARTF_USESHOWWINDOW;
Start.wShowWindow = SW_SHOWMINIMIZED;
//Change the path to Excel as needed...
LPSTR pszExcelPath =
"c:\\program files\\microsoft office\\office\\excel.exe";
::CreateProcess(NULL, pszExcelPath, 0, 0, 1,
NORMAL_PRIORITY_CLASS, 0, NULL, &Start, &ProcInfo);
if((::WaitForInputIdle(ProcInfo.hProcess, 10000))==WAIT_TIMEOUT)
{
::MessageBox(NULL, "Timed out waiting for Excel.", NULL,
MB_OK);
}
//Restore the active window to the foreground...
// NOTE: If you comment out this line, the code will fail!
::SetForegroundWindow(hwndCurrent);
//Initialize COM library...
::CoInitialize(NULL);
//Attach to the running instance...
CLSID clsid;
CLSIDFromProgID(L"Excel.Application", &clsid);
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;
for(int i=1;i<=5;i++) //try attaching for up to 5 attempts
{
HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
if(SUCCEEDED(hr))
{
hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);
break;
}
::Sleep(1000);
}
if (!pDisp) {
::MessageBox(NULL, "Failed to find instance!!", "Error",
MB_ICONHAND);
}
else {
::MessageBox(NULL, "Got instance of Excel!", "Success", MB_OK);
}
//Release the no-longer-needed IUnknown...
if (pUnk)
pUnk->Release();
//... Add your automation code for Excel here ...
//Release pDisp when no longer needed...
if (pDisp)
pDisp->Release();
//Cleanup COM...
CoUninitialize();
具体原因就看下面吧:
http://support.microsoft.com/kb/238610/en-us/
- 关于GetActiveObject失败的灵异现象的解决
- 关于Windows cmd的灵异现象
- 关于idea不能输入的灵异现象
- 疑为灵异现象不可思议的透明液晶揭秘
- 今日登陆sourceforge后发现的灵异现象
- 在Firefox下浏览博客发生的灵异现象
- Python循环中的变量作用域的灵异现象
- 解决4.19号灵异事件的方法
- 关于GetActiveObject,如何判断所取得对象的类型、、、可以用来检测某个程序是否运行
- VMWARE虚拟机开机失败的一些现象与解决汇总
- 关于一起kvm的“灵异”事件
- 科学难以解释的10大灵异神秘现象?(转载)
- ios开发中init()方法重复执行,以及实例变量错乱的灵异现象
- 灵异现象(一):为什么POM文件一样,只有我的架包出错
- Eclipse的灵异事件
- 灵异的shell
- SVN的灵异事件
- 官方教程survivalshooter 关于animator的灵异性bug
- hdu 3415 Max Sum of Max-K-sub-sequence【单调队列】
- Lua脚本语言参考一
- Google App Engine 免费空间试用心得
- webview将网页显示在屏幕区域内
- BackTrack5(BT5)硬盘安装完美教程
- 关于GetActiveObject失败的灵异现象的解决
- Lua脚本语言参考二
- 实验2-8 调试窗口之Memory(*****)
- Lua脚本语言参考三
- google更新了最新的SDK
- Lua脚本语言参考四
- digester实例续
- Mac平台工具介绍-虚拟机篇
- VB.NET DataGridView中的数据导入到Excel