接上一篇博文python办公自动化系列之金蝶K3自动登录(一),我们接着聊聊利用python脚本实现金蝶K3 Wise客户端自动登录这一需求。

  如上图所示,自动选择【组织机构】后,我们还需要驱动【当前账套】、【命名用户身份登录】、【用户名】、【密码】、【确定】这几个控件,才算是完成了K3 UI自动化的第一步:自动登录。

一、设置【当前账套】控件

  【当前账套】Label右边对应的同样是一个ThunderRT6ComboBox 类,我们选择comboBox某个下拉项时,只有基于索引Index,但是由于集团公司随着业务不断变化,账套数可能存在变化,每个公司账套对应的索引值也会变化。因此,我们最好想办法实现基于账套名称来实现驱动某个comboBox控件。比较通俗易懂的做法是,我们先设法拿到这个组件的所有listItem,将每个Item对应的value(文本值)和listIndex(索引)存入一个字典,那么当用户端随便抛给我们一个账套名时,我们便能基于该字典迅速知道listIndex,再基于它来选择这个comboBox控件。这里面涉及到comboBox一些属性和方法的应用,具体示例代码如下:

 1 import win32gui,win32con
2 def getAccountDic(currentAccountHwnd):
3 '''根据【当前账套】的句柄,得到该comboBox所有下拉选项,将选项值ItemText和对应的ItemIndex存入字典 accountDic,最终返回'''
4 accountDic={}
5 accountCnt=win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETCOUNT, 0, 0)
6 for i in range(accountCnt):
7 textLen= win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXTLEN, i,0)*2 # 创建一个比combobox 文本长度两倍的buffer,确保数据都能存进去
8 buffer = win32gui.PyMakeBuffer(textLen)
9 win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXT, i, buffer)
10 address,length=win32gui.PyGetBufferAddressAndLen(buffer[:-1])
11 length=int((length+1)/2)
12 itemText=win32gui.PyGetString(address,length).strip() # 从内存中取出combobox的当前项内容
13 accountDic[itemText]=i
14 return accountDic
15
16 def setCurrentAccount(currentAccountHwnd,currentAccountName,accountDic):
17 '''根据【当前账套】的句柄,,需要选择的账套名称,和账套字典,选择特定账套为当前账套'''
18 accountIndex=accountDic[currentAccountName]
19 win32gui.SendMessage(currentAccountHwnd, win32con.CB_SETCURSEL, accountIndex, 0)

二、选择【登录方式】为【以命名用户身份登录(D)】

  根据实际需要,小爬这里演示下以命名用户身份登录(D),其它登录方式,手段同理。spy++观察到它其实是一个optionButton。我们可以这样设置:

1 def setOptionBtn(parentHwnd,optionName):
2 # optionName="以命名用户身份登录(D)"
3 '''通过spy++得到这些optionButton的父元素句柄,在基于文本optionName找到并选择特定的optionButton'''
4 optionBtnHandle=win32gui.FindWindowEx(parentHwnd,0,None, optionName) # 以命名用户身份登录(D) optionButton
5 win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONDOWN, 0, 0) # 设置登录方式为【以命名用户身份登录(D)】
6 time.sleep(0.01)
7 win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONUP, 0, 0)

三、设置【用户名】、【密码】控件

  通过spy++观察到这两个控件的类名为ThunderRT6TextBox,也算是textBox的子类。我们可以大胆使用SendMessage的WM_SETTEXT来实现这一点,唯一的难度在于基于类名来定位这两个控件时稍微有些麻烦,其中【密码框】控件可以通过定位父元素,然后利用findwindowEx方法,基于ThunderRT6TextBox找到第一个元素即可,而【用户名框】可以通过【当前账套】控件来找下一个控件得到。这里比较让人混淆的是:后台的所有控件【用户名】在下,【密码】在上,与肉眼观察到的物理位置刚好相反。具体代码示例如下:

1 def setUserInfo(userName,passWord,parentHwnd,currentAccountHwnd):
2 passwordHwnd=win32gui.FindWindowEx(parentHwnd,0,"ThunderRT6TextBox", None) # 密码框,基于父元素和其类名找到的第一个即可
3 time.sleep(0.1)
4 userNameHwnd=win32gui.FindWindowEx(parentHwnd,currentAccountHwnd,None, None) # 用户名框,基于【当前账套】控件句柄找到下一个即可
5 time.sleep(0.1)
6 win32gui.SendMessage(userNameHwnd, win32con.WM_SETTEXT, None,userName)
7 time.sleep(0.1)
8 win32gui.SendMessage(passwordHwnd, win32con.WM_SETTEXT, None,passWord)

四、发送【回车】实现登录

  小爬通过模拟给登陆界面发送【回车键】来实现登录,示例代码如下:

1     '''根据登陆界面句柄sysLoginWnd,发送回车键实现登录'''
2 win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
3 time.sleep(0.01)
4 win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0)

  结合上一篇博文,我们基本就完成了K3登录需要的各个方法,我们只需要依次调用,就可以实现K3自动登录某个账套啦。希望小爬的分享对你们的日常工作有所帮助,完整代码如下,供参考,:

 1 # 需要使用管理员权限运行VScode或者Pycharm,否则无法正常使用
2 import win32gui,win32api,win32con,subprocess,time,os
3 def getK3LoginHwnd():
4 sysLoginWnd=win32gui.FindWindow('ThunderRT6Form',"金蝶K/3系统登录") # K3系统登录窗
5 if sysLoginWnd==0:
6 subprocess.Popen(r'C:\Program Files (x86)\Kingdee\K3ERP\K3MainNet.exe')
7
8 # subprocess发送指令启动后需要等K3登录窗彻底可见后,再进行后续操作
9 while sysLoginWnd==0:
10 time.sleep(0.3)
11 sysLoginWnd=win32gui.FindWindow('ThunderRT6Form',"金蝶K/3系统登录") # K3系统登录窗
12 isSysLoginWndVisible=0
13 while isSysLoginWndVisible==0:
14 time.sleep(0.3)
15 sysLoginWnd=win32gui.FindWindow('ThunderRT6Form',"金蝶K/3系统登录") # K3系统登录窗
16 isSysLoginWndVisible=win32gui.IsWindowVisible(sysLoginWnd) # 判断窗口是否已经对用户可见
17 return sysLoginWnd
18
19 def setOrganization(sysLoginWnd,organizationIndex):
20 '''根据K3登录窗的句柄sysLoginWnd和下拉框索引值organizationIndex,选择特定的组织机构'''
21 mainHwnd1=win32gui.FindWindowEx(sysLoginWnd,0,None, '') # ThunderRT6PictureBoxDC
22 mainHwnd2=win32gui.FindWindowEx(sysLoginWnd,mainHwnd1,None, '') # ThunderRT6PictureBoxDC
23 organizationHwnd=win32gui.FindWindowEx(mainHwnd2,0,"ThunderRT6ComboBox", '') # 组织机构
24 currentOrgIndex=win32gui.SendMessage(organizationHwnd, win32con.CB_GETCURSEL) # 当前combobox选中的index
25 if currentOrgIndex!=organizationIndex:
26 win32gui.SendMessage(organizationHwnd, win32con.CB_SETCURSEL, organizationIndex, 0)
27
28 '''模拟鼠标左键点击元素,激活它'''
29 win32gui.SendMessage(organizationHwnd, win32con.WM_LBUTTONDOWN, 0, 0)
30 time.sleep(0.01)
31 win32gui.SendMessage(organizationHwnd, win32con.WM_LBUTTONUP, 0, 0)
32
33 '''小爬此处的场景中,【组织机构】有6个下拉项,那么最大的index就是5'''
34 if organizationIndex<5: # 模拟键盘↓+键盘↑
35 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_DOWN, 0)
36 time.sleep(0.01)
37 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_DOWN, 0)
38 time.sleep(0.1)
39 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_UP, 0)
40 time.sleep(0.01)
41 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_UP, 0)
42 else: # 模拟键盘↑+键盘↓
43 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_UP, 0)
44 time.sleep(0.01)
45 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_UP, 0)
46 time.sleep(0.1)
47 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYDOWN, win32con.VK_DOWN, 0)
48 time.sleep(0.01)
49 win32gui.PostMessage(organizationHwnd, win32con.WM_KEYUP, win32con.VK_DOWN, 0)
50 time.sleep(0.1)
51
52 def getAccountDic(currentAccountHwnd):
53 '''根据【当前账套】的句柄,得到该comboBox所有下拉选项,将选项值ItemText和对应的ItemIndex存入字典 accountDic,最终返回'''
54 accountDic={}
55 accountCnt=win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETCOUNT, 0, 0)
56 for i in range(accountCnt):
57 textLen= win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXTLEN, i,0)*2 # 创建一个比combobox 文本长度两倍的buffer,确保数据都能存进去
58 buffer = win32gui.PyMakeBuffer(textLen)
59 win32gui.SendMessage(currentAccountHwnd, win32con.CB_GETLBTEXT, i, buffer)
60 address,length=win32gui.PyGetBufferAddressAndLen(buffer[:-1])
61 length=int((length+1)/2)
62 itemText=win32gui.PyGetString(address,length).strip() # 从内存中取出combobox的当前项内容
63 accountDic[itemText]=i
64 return accountDic
65
66 def setCurrentAccount(currentAccountHwnd,currentAccountName,accountDic):
67 '''根据【当前账套】的句柄,,需要选择的账套名称,和账套字典,选择特定账套为当前账套'''
68 accountIndex=accountDic[currentAccountName]
69 win32gui.SendMessage(currentAccountHwnd, win32con.CB_SETCURSEL, accountIndex, 0)
70
71 def setOptionBtn(parentHwnd,optionName):
72 # optionName="以命名用户身份登录(D)"
73 '''通过spy++得到这些optionButton的父元素句柄,在基于文本optionName找到并选择特定的optionButton'''
74 optionBtnHandle=win32gui.FindWindowEx(parentHwnd,0,None, optionName) # 以命名用户身份登录(D) optionButton
75 win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONDOWN, 0, 0) # 设置登录方式为【以命名用户身份登录(D)】
76 time.sleep(0.01)
77 win32gui.SendMessage(optionBtnHandle, win32con.WM_LBUTTONUP, 0, 0)
78
79 def setUserInfo(userName,passWord,parentHwnd,currentAccountHwnd):
80 passwordHwnd=win32gui.FindWindowEx(parentHwnd,0,"ThunderRT6TextBox", None) # 密码框,基于父元素和其类名找到的第一个即可
81 time.sleep(0.1)
82 userNameHwnd=win32gui.FindWindowEx(parentHwnd,currentAccountHwnd,None, None) # 用户名框,基于【当前账套】控件句柄找到下一个即可
83 time.sleep(0.1)
84 win32gui.SendMessage(userNameHwnd, win32con.WM_SETTEXT, None,userName)
85 time.sleep(0.1)
86 win32gui.SendMessage(passwordHwnd, win32con.WM_SETTEXT, None,passWord)
87
88 def sendReturn(sysLoginWnd):
89 '''根据登陆界面句柄sysLoginWnd,发送回车键实现登录'''
90 win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
91 time.sleep(0.01)
92 win32gui.PostMessage(sysLoginWnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0)

欢迎扫码关注我的公众号 获取更多爬虫、数据分析的知识!

python办公自动化系列之金蝶K3自动登录(二)的更多相关文章

  1. python办公自动化系列之金蝶K3自动登录(一)

    做办公自动化的小伙伴都知道,驱动SAP GUI我们有SAP原生提供的[脚本录制与回放]以及SAP Scripting API可参考:驱动Office Excel等,我们有微软提供的[录制宏]功能:驱动 ...

  2. python办公自动化系列之金蝶K3(三)

    小爬在之前的两篇文章 [python办公自动化系列之金蝶K3自动登录(一)].[python办公自动化系列之金蝶K3自动登录(二)]带大家系统搞定了K3客户端的自动登录难题,但是搞定[自动登录]只是我 ...

  3. 金蝶K3 wise 插件二次开发与配置

    金蝶K3 wise 插件二次开发与配置 开发环境:K/3 Wise 13.0.K/3 Bos开发平台.Visual Basic 6.0 目录 一.二次开发插件编程二.代码演示三.配置插件四.测试插件五 ...

  4. python网络爬虫之使用scrapy自动登录网站

    前面曾经介绍过requests实现自动登录的方法.这里介绍下使用scrapy如何实现自动登录.还是以csdn网站为例. Scrapy使用FormRequest来登录并递交数据给服务器.只是带有额外的f ...

  5. python带cookie提交表单自动登录(转)

    今天突然把博客给申请了,以前也想过的,奈于自己觉得水平还太低有点不好意思写博客,但是后来一想,自己的记录所学,加深印象,主要还是为了学习进步,不怕丢人!今天就稍微回顾一下这两天写的一段用python模 ...

  6. 使用Python定时执行一任务,自动登录某web系统,生成报表,然后发送邮件给指定人员

    一.项目需求 每周从A系统生成一张Excel报表,发送此报表给指定人员,相关人员依据此报表去完成后续的工作. 项目限制: 1.无法通过EDI系统交互的方式从后台读取数据 2.由于公司网络环境限制,不能 ...

  7. python带cookie提交表单自动登录

    import urllib import urllib2 import cookielib login_url = "xxxxxxxxxxxxx" cj = cookielib.C ...

  8. Appium python自动化测试系列之appium环境搭建(二)

    ​2.1 基础环境搭建 当我们学习新的一项技术开始基本都是从环境搭建开始,本书除了第一章节也是的,如果你连最基础的环境都没有那么我们也没必要去说太多,大概介绍一下: 1.因为appium是支持andr ...

  9. Appium python自动化测试系列之日志的收集(十二)

    ​13.1 日志的定义 13.1.1 日志的定义 听到日志这个东西可能有的人莫名其妙,第一次接触就会觉得我们为什么要收集日志,即使要收集日志那么我们需要收集哪些日志,日志的作用是什么等等. 其实日志无 ...

随机推荐

  1. Windows下SQL Server数据库的安装

    由于工作需要出一版教程,记录一下安装过程,用到的数据库是SQL Server2014版本 下载地址为:SQL Server2014下载 提取码:6666 下载好安装包,首先右键,装载 装载完, 会有这 ...

  2. Java Springboot webSocket简单实现,调接口推送消息到客户端socket

    Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...

  3. Docker_简介(1)

    Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 ...

  4. 解决spring boot 无法访问静态文件夹的附件或图片

    1.需要在配置文件重新执行静态文件夹位置即可 # 指定静态文件位置 resources: static-locations: classpath:/static/,classpath:/static/ ...

  5. 日志收集系统系列(四)之LogAgent优化

    实现功能 logagent根据etcd的配置创建多个tailtask logagent实现watch新配置 logagent实现新增收集任务 logagent删除新配置中没有的那个任务 logagen ...

  6. SpringCloud的Config应用

    一.简介 ***应用程序先注册到注册中心,在注册中心根据guli-config服务的名字找到配置中心,然后在配置中心根据配置从github加载基本配置. 二.配置中心(服务端,可以部署集群) 1.依赖 ...

  7. 使用altium designer 21极坐标绘制异形焊盘 比如焊接螺母的 环绕焊盘

    先看一张图 在回流焊时,不能直接做一个大圆圈焊盘来焊接螺母,这样焊锡膏因为流动问题,可能会导致螺母歪斜 厂家推荐的焊盘形状右上角 所以 需要绘制异形焊盘 首先进入ad的封装库工作界面 在库中点右下角P ...

  8. 转雅虎web前端网站优化 34条军规

    雅虎给出了优化网站加载速度的34条法则(包括Yslow规则22条) 详细说明,下载转发 ponytail 的译文 1.Minimize HTTP Requests 减少HTTP请求 图片.css.sc ...

  9. 【Maven】maven 插件开发实战

    前言 众所周知,maven 实质上是一个插件执行框架,所有的工作都是通过插件完成的.包括我们日常使用到的类似 install.clean.deploy.compiler...这些命令,其实底层都是一个 ...

  10. fluem读取文件并写入到hadoop的hdfs

    接上一章,本章介绍使用 crontab 像指定文件定时写入,使用fluem 读取并写入到hadoop的hdfs 前提准备已安装好fluem ,和hadoop(推荐单机即可毕竟做实验) 一.进入终端执行 ...