以Windows服务方式运行Excel自动化程序遇到的问题与解决方法¶
发布于:2019-09-14 | 分类:process automation
参考前文关于win32com
模块的示例代码可以进行Excel的自动化操作,例如Excel VBA的自动化测试;将其作为Windows服务运行,则可以方便为网络中的其他机器调用。本文正是记录配置Excel自动化服务过程中遇到的问题与相应解决措施。
概述¶
最近有个需求是对启用宏的Excel 2010文件的自动化测试,需要配置在服务器上以供GitLab-Runner
调用。于是,按照读入测试数据、执行测试VBA、验证计算结果的逻辑写好Python脚本,调试通过后在本地运行一切正常。然而,通过Commit提交触发CI/CD流程,即GitLab-Runner
以Windows服务的方式执行相同的脚本时,却出现了各种各样的问题。
根本原因显然是 本地账户 和 系统服务 执行Excel自动化操作上的差异,以下逐一记录遇到的问题。除了部分与Python相关的问题外,其余应该具备通用性,可作为Windows服务方式执行Excel、Word、Outlook等自动化程序出现问题时的参考。
注意
当前登陆账户应具备管理员权限。
Open method of Workbooks class failed¶
(-2147352567, 'Exception occurred.',
(0, 'Microsoft Excel', 'Open method of Workbooks class failed', 'xlmain11.chm', 0, -2146827284), None)
在Stackoverflow搜索到了这个问题的解决方法 1,根据Windows位数在目标目录创建一个Desktop
文件夹:
- 64位系统:
C:\Windows\SysWOW64\config\systemprofile\
- 32位系统:
C:\Windows\System32\config\systemprofile\
虽然暂时解决了问题,却也不知是何缘由。经历后续问题才明白:Excel需要有Interactive User
登陆才能正常运行,上面的步骤正是为其提供了用户“桌面”;然而一旦需要更多用户账户相关的设置时,就会有新的问题出现了。
Programmatic access to Visual Basic Project is not trusted¶
(-2147352567, 'Exception occurred.',
(0, 'Microsoft Excel', 'Programmatic access to Visual Basic Project is not trusted\n', 'xlmain11.chm', 0, -2146827284), None)
这个问题很明显,一旦代码需要访问VBA工程对象,例如访问module
对象、Python动态执行VBA代码,则需要相应的许可(Excel软件信任区设置中有该选项)。
解决方法可以是利用Python动态修改相应注册表项和值来允许访问VB工程,或者参考 2 手工永久设置。
执行VBA代码超时¶
这一般是因为VBA代码中存在错误。因为本文的自动化过程是由Python驱动的,一旦VBA代码出错而被挂起,Python就无法得到响应了。
针对本文应用场景的解决方案是在VBA测试代码的开头加上一句On Error Resume Nest
,即忽略VBA代码中的错误,以便Python可以正常执行后续流程。并且无需担心此举造成的错误,VBA代码存在错误必将导致后续验证输出的失败,也就表明了这个测试案例必将失败。
无法正确加载VBA中调用的C++动态链接库¶
VBA代码中直接通过文件名引用DLL,而DLL所在路径已经添加到了PATH
环境变量中。由此看来,以系统服务方式启动的Excel并不能正确获取到环境变量。
Declare Function xxx Lib "sample_dll_name.dll" ( arguments_list_xxx ) As xxx
解决方法为通过DCOMConfig
设置启动Excel的用户 3 4:
Windows+R
->dcomcnfg
,打开Component Service
Console Root
->Component Services
->My Computer
->DCOM Config
- 从
DCOM Config
中找到Microsoft Excel Application
,右键选择Properties
- 选择
Identity
选项卡,选择the launching user
,表示以登陆用户来启动Excel(这里可能会出现新的问题,参见问题5) - 选择
Security
选项卡,为指定的账户自定义Launch and Activation Permissions
和Access Permissions
- 选择
如果上述DCOM Config
列表中并不存在Microsoft Excel Application
,则参考下面步骤 4。
以64位Windows系统上的32位Excel为例,
Windows+R
->mmc -32
打开Microsoft Managemant Console
File
->Add Remove Snap-in
->Component Services
->Add
->OK
添加Component Services
- 按
DCOMConfig
步骤2,3进行设置
The configured identity is incorrect¶
(-2147467238, 'The server process could not be started because the configured identity is incorrect.
Check the username and password.', None, None)
到目前为止一切正常,可一旦服务器进入待机状态,就出现了上述错误。原因也很明确,因为之前问题时设置了以当前账户来运行Excel,于是当前用户退出时系统尝试再次登陆,但我们并没有设置任何登陆口令。
解决方法为DCOMConfig
设置Identity
为The launching user
或者This User
,然后输入用户名和密码(注意域内用户需要带上域名称,例如domain\user
) 5。
Module has no attribute 'CLSIDToClassMap'¶
module 'win32com.gen_py.00020813-0000-0000-C000-000000000046x0x1x7' has no attribute 'CLSIDToClassMap'
这是win32com
以EnsureDispatch()
方式启动Excel会产生临时文件夹,出现此问题后只要删除相应文件夹即可,即本例中的00020813-0000-0000-C000-000000000046x0x1x7
。
import win32com.client
app = win32com.client.gencache.EnsureDispatch('Excel.Application')
那么如何找到该目录呢?如下代码将打印目标位置 6:
import win32com
print(win32com.__gen_path__)
- 对于本地账户执行的代码:
C:\Users\<my username>\AppData\Local\Temp\gen_py
- 对于系统服务执行的代码:
C:\Windows\Temp\gen_py
注意
如果GitLab-runner
是系统服务以本地账户形式运行的,则同样对应本地账户目录而非系统目录。
This COM object can not automate the makepy process - please run makepy manually for this object¶
与上一个问题删除缓存的做法相反,这个错误表明无法自动产生gen_py
文件夹,而这正是win32com
以EnsureDispatch()
方式启动Excel所必须的。所以按照提示,手动运行makepy.py
即可。
- 在
Lib\site-packages\win32com\client
目录下执行python makepy.py -d
- 在弹出的
select library
对话框中选择Excel相关的项目即可,例如Microsoft Excel 16.0 Object Library (1.9)
- 用户
Temp
文件夹下即可产生gen_py
文件夹
Cannot use object linking and embedding¶
在正常工作了几天后,突然出现了此问题,具体原因尚不明确。实际上,这是本地账户打开Excel时的错误提示,在GitLab-Runner
上执行Excel自动化脚本时表现为失去响应直至超时,即卡在打开Excel工作簿上。
解决方法:
-
通过
DCOMConfig
设置系统登陆Identity
为The launching user
7 -
同时为
GitLab-Runner
设置登陆账户:将其从默认的Local System
切换到This account
,然后设置domain\user
及其登陆密码。Windows+R
->services.msc
->gitlab-runner
->properties
Log On
->This account
-> 填写Password
和Confirm Password
另外,MSDN上也有人给出了保持DCOMConfig
中This account
不变而修改本地Excel文件Security
属性的解决方法 8,本文尚未是测试。