您的位置:首页 > 其它

使用批处理来注册OCX文件的若干问题

2015-05-19 09:26 295 查看
把每次遇到并解决了的问题记录下来,形成文档,这便是一种财富。--沉森心

问题描述:

客户投诉说,安装完软件包后,打开某个业务模块,点击打印预览按钮时,没反应,不能打印。

原因描述:

对于打印这个功能,PC客户端是通过调用OCX控件来进行打印的,我们采用了批处理脚本的方式来进行OCX文件的注册和反注册。每次程序第一次被安装启动时,系统会自动调用执行一个批处理脚本,从而完成任务。但由于Windows系统环境的复杂,导致了批处理文件执行偶尔会失败。现根据不同的系统环境来分析一下:

批处理脚本:

@echo off
if "%processor_architecture%"=="x86" goto REG32
if "%processor_architecture%"=="AMD64" goto REG64
:REG32
if not exist %systemroot%\system32\Print.OCX COPY MSCHRT20.OCX  %systemroot%\system32
%systemroot%\system32\regsvr32.exe -u -s %systemroot%\system32\Print.ocx
%systemroot%\system32\regsvr32.exe -s %systemroot%\system32\Print.ocx
......
goto exit
:REG64
if not exist %systemroot%\syswow64\Print.OCX COPY MSCHRT20.OCX  %systemroot%\syswow64
%systemroot%\syswow64\regsvr32.exe -u -s %systemroot%\system32\Print.ocx
%systemroot%\syswow64\regsvr32.exe -s %systemroot%\system32\Print.ocx
......
goto exit
:exit
exit


备注:win7系统分为32位和64位,应该根据它的处理器类型来判断,而regsvr32.exe分别位于system32和syswow64文件夹中。

VC代码:

采用ShellExecute函数来执行该批处理脚本Print.bat。

ShellExecute(NULL,_T(“open”),strBatFilePath,NULL,SW_SHOW);


运行结果:

Win7:

对于没有管理员权限的用户,直接双击bat文件,会提示复制文件失败,拒绝访问。

XP:

弹出Dos命令行窗口,复制并注册文件成功,但是对某些XP系统偶尔会失败。

解决办法1:

既然需要管理员权限,那我能否在程序中使用管理员权限运行这个bat文件呢?修改如下:

VC代码:

SHELLEXECUTEINFO sei={sizeof(SHELLEXECUTEINFO)};
sei.lpVerb = TEXT("runas");
sei.lpFile = strBatFilePath;
sei.nShow = SW_HIDE;
sei.lpDirectory=NULL;
sei.lpParameters=_T(“”);
if (!ShellExecuteEx(&sei))
{
DWORD dwStatus = GetLastError();
if (dwStatus == ERROR_CANCELLED)
{
printf("没有以管理员权限运行");
}
else
if(dwStatus == ERROR_FILE_NOT_FOUND)
{
printf("没有找到该文件");
}
}

结果:复制并注册文件成功,但是对于某些XP系统,偶尔会失败。

解决办法2:

查看bat脚本,发现每次都要把OCX和相关的依赖动态库拷贝到系统目录下的system32\sysWow64文件夹中,然后再进行注册,太麻烦了,能否直接在安装目录下调用批处理文件进行注册呢?修改如下:

@echo off
cd /d %~dp0
if "%processor_architecture%"=="x86" goto REG32
if "%processor_architecture%"=="AMD64" goto REG64
:REG32
%systemroot%\system32\regsvr32.exe -u -s %cd%\Print.ocx
%systemroot%\system32\regsvr32.exe -s %cd%\Print.ocx
goto exit
:REG64
%systemroot%\syswow64\regsvr32.exe -u -s %cd%\Print.ocx
%systemroot%\syswow64\regsvr32.exe -s %cd%\Print.ocx
goto exit
:exit
exit


结果:复制并注册文件成功,但是对于某些特殊情况,还是偶尔会失败。

解决办法3:

为什么一定要用批处理来执行呢?这对于XP系统来说,每次运行这个文件都要弹出一个dos命令行窗口,用户体验不好。所以,干脆把批处理去掉,直接用ShellExecute函数调用regsvr32.exe来进行ocx文件的注册,写死在客户端代码里。代码如下:

ShellExecute(NULL,NULL,_T(“regsvr32.exe”),strOCXFilePath,NULL,SW_HIDE);


结果:复制并注册文件成功,目前暂时没有遇到失败案例。

注意:ocx文件路径不能包含空格,应该把文件路径用双引号括起来,这样路径中就可以包含空格了。

strOCXFilePath.Format(_T("/s \"%s\""),strOCXFilePath);  // /s参数会隐藏cmd注册控件是否成功的对话框
ShellExecute(NULL,NULL,_T(“regsvr32.exe”),strOCXFilePath,NULL,SW_HIDE);


ps:

判断OCX文件是否已经注册?

要判断是否已经注册,只要判断注册表是否存在该OCX键值就行了。但是我们客户端存在很多版本,又可以同时运行,故不能判断注册表,于是选择了判断OCX某个接口的返回值的办法。但是无论怎样测试,只要没注册的,接口就不往下跑或者返回值异常。正当搔头弄脑之际,我们发现调试程序时,只要打印OCX文件注册不成功的话,程序是不能进入到打印类CPrintDlg的OnInitDialog函数里的。所以我们马上改变了思路和角度,在OnInitDialog函数里设置了一个返回标识,只要打印窗口不返回成功标识,则说明OCX文件注册不成功,搞定。

通过这个例子,我明白了,有时候转换一个角度来思考问题,反而会找到更多的思路和方法。打破思维定式,你我都能做到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐