Python的自动操作(挂机)脚本相关1

之前用了数个月VBS,受不了啦。听闻.py好使就试试看。 
这是用Py的第五天。 
爱搬码,非coder。 
工具:Python3.4.0 + PyCharm2016 3.2 + PyQt5.4.1 
工具:Notepad++ 
环境:Win7 
注:Notepad++写VBS时,防止代码中的中文乱码,必须设置“格式”—“以XXXX Little Endian 格式编码”。

1. 鼠标/键盘操作

从VBS过来的,先说用过的思路: 
——————————————.VBS 
请参考Demon的: 
用VBS控制鼠标(获取鼠标坐标、鼠标移动、鼠标单击、鼠标双击、鼠标右击) 
创建Excel对象,在VBA模块中调用WIN的API: 
SetCursorPos / GetCursorPos / mouse_event / keybd_event 
若要修改VBA模块中的代码,不够方便(人懒) 
——————————————.Py 
Python这边,安装对应版本的pywin32,就可调用win32api: 
(对应Python3.4.0,windows要先安装Python3.4 pywin32-2XX) 本机219 
pywin32 下载列表

# -*- coding: UTF-8 -*-
# Python version: 3.4.0
import win32api

def LeftClick(x, y):    # 鼠标左键点击屏幕上的坐标(x, y)
    win32api.SetCursorPos((x, y))    # 鼠标定位到坐标(x, y)
    # 注意:不同的屏幕分辨率会影响到鼠标的定位,有需求的请用百分比换算
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0)    # 鼠标左键按下
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)    # 鼠标左键弹起
    # win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN + win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)    # 测试

def PressOnce(x):    # 模拟键盘输入一个按键的值,键码: x
    win32api.keybd_event(x, 0, 0, 0)

# 测试
LeftClick(30, 30)  # 我的电脑?
PressOnce(13)  # Enter
PressOnce(9)   # TAB
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

keycode/组合键等:keybd_event使用方法

附:Python获取屏幕分辨率

import win32api
from win32api import GetSystemMetrics
def DisplaySize():
    return GetSystemMetrics(0), GetSystemMetrics(1)

a, b = DisplaySize()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

———————————————PyUserInput 
搜到PyUserInput,好家伙,GitHub: 
PyUserInput 
(安装PyUserInput之前必须先安装对应版本的pywin32和pyHook)

2. 屏蔽鼠标键盘输入

知道了能在VBS里调用api,于是听说BlockInput可以弄到死机。 
依样画葫芦,把这句塞到VBA模块代码里去,注意换行符: 
——————————————.VBS

"Public Declare Function BlockInput Lib ""user32""  (Byval fBlock As Long) As Long " & vbCrLf & _
  • 1

也该注意到了,用了user32.dll,哦也就是win的api这样。在VBS中使用:

oExcel.Run "BlockInput", True  '屏蔽鼠标键盘
wscript.Sleep 1000    '你-1s
oExcel.Run "BlockInput", False '记得解除锁定
  • 1
  • 2
  • 3

——————————————.Py 
Python3.4用user32.dll,就是windll,直接在ctypes里

from ctypes import *
user32 = windll.LoadLibrary('user32.dll')    # 加载动态链接库
user32.BlockInput(True)   # 锁
time.sleep(1)             # 你-1s
user32.BlockInput(False)  # 该解锁啦
  • 1
  • 2
  • 3
  • 4
  • 5

3. 检测/结束进程

——————————————.VBS

On Error Resume Next  
    for each ps in getobject("winmgmts:\\.\root\cimv2:win32_process").instances_
    if Ucase(ps.name)=Ucase("123.exe") then  
        ps.terminate  ' kill
        WScript.Echo "死了没"
    end if
    next 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

——————————————.Py

import os
# process_name:进程名 ;返回进程个数
def process_exit(process_name):
    p_checkresp = os.popen('tasklist /fo csv | find "' + process_name + '"').readlines()
    return len(p_checkresp)


if process_exit(123.exe) == 0:    # 未检测到
    print("=0")
elif process_exit(123.exe) >= 1:    # 检测到
    command = 'taskkill /F /IM 123.exe'  # kill
    os.popen(command)    # 执行cmd命令
    # os.system(command)    # 听说用popen更好
    print("=1")
else:
    win32api.MessageBox(0, "用api弹出窗口消息")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4. 启动外部程序

Py和VBS都有几种方式启动外部的程序(.exe等)这里不列出了。 
VBS中运行应用程序的两种方式及WshShell对像浅析

而某些软件启动的时候会挂上其他东西… 
(非CS专业,不知道啊。是否环境变量不对、起始目录不对之类) 
wshell普通的run启动后登陆报错,用Exec也登陆后报错,各种改参数没有效果。

最后搜到个命令行用start,微软界面How to redirect command-Line output 
——————————————.VBS 
如:C:\Program Files\12345\我是中文名的程序来砍我吖.exe

WshShell.run("%comspec% /k c: & cd \Program Files\12345 & start 我是中文名的程序来砍我吖.exe&")   '稳
  • 1

命令行:”%comspec% /k 
切换到程序所在盘(c:); 
打开所在目录(cd \Program Files\12345),最后start,登陆再也没有报错! 
注意用“&”连接每条命令,也用“&”结束。 
——————————————.Py 
CreateProcess等方法不提,本例不适用。使用CreateProcess函数运行其他程序 
Python的cmd不认cd \Program Files\12345 里边的单个反斜杠换成转义“\\\\”(四条杠)也不行。 
路径有中英文符号等等,要对字符进行判断。python利用utf-8编码判断中文英文字符(转)

# alphabet or not 是否英文字母
def is_alphabet(uchar):
        if (uchar >= u'\u0041' and uchar<=u'\u005a') or (uchar >= u'\u0061' and uchar<=u'\u007a'):
            return True
        else:
            return False


# num or not 是否数字
def is_number(uchar):
        if uchar >= u'\u0030' and uchar<=u'\u0039':
            return True
        else:
            return False


# chinese or not 是否中文
def is_chinese(uchar):
        if uchar >= u'\u4e00' and uchar<=u'\u9fa5':
            return True
        else:
            return False


# 是否非中文非英文非数字
def is_other(uchar):
        if not (is_chinese(uchar) or is_number(uchar) or is_alphabet(uchar)):
            return True
        else:
            return False
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

根据以上弄了个拆文件路径的玩意:

# get each dir 获得路径里每个文件夹的名字
# 传入path:文件的完整路径名+程序名
def part_path(path):
    if len(path) > 0:
        gang_arr = []       # 反斜杠位置数组
        gang_num = 0            # 反斜杠总数
        point = 0           # 点号位置
        for i in range(0, len(path)):
            if is_other(path[i]):       # 点号和反斜杠
                if path[i] == "/":      # 反斜杠
                    gang_arr.append(i)      # 每个反斜杠的位置
                    gang_num += 1
                elif path[i] == ".":
                    point = i  # 点号的位置
        # if is_alphabet(path[0]):
        #   print("disk: %s :" % path[0])
        # else:
        #   print("error disk!")
        # 每个反斜杠的位置
        # print("how many gangs = %d" % gang_num)
        # print("gang arr = %s" % str(gang_arr[0:path.count("/")]))
        # 获得每个子目录
        sub_arr = []
        for j in range(0, gang_num-1):
            sub_arr.append(path[gang_arr[j] + 1: gang_arr[j+1]])
        exe_name = path[gang_arr[gang_num-1] + 1:]
        # print("exe name: " + exe_name )   # exe name
        return path[0], exe_name, sub_arr
    else:
        win32api.MessageBox(0, "请选择文件!")

# 调用
disk_name, exe_name, dir_arr = part_path("C:\Program Files\12345\砍吖.exe")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

(path不是随便输入的,用了PyQt中的QFileDialog获得文件路径。后面会讲) 
学着VBS用start:

# 根据反斜杠数量,多次拼接cmd命令
cmd = "cd/ & " + disk_name + ": &"
        for i in range(0, len(dir_arr)):
            cmd += "cd " + dir_arr[i] + " & "
        cmd += "start " + exe_name
        # print(cmd)
        os.popen(cmd)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5. 补充

哦,用pyInstaller3.0打包成EXE(-w -F)调试的时候,发现前面有关检测/结束/启动进程用的所有os.popen(cmd)均没反应,不执行动作,搞不清原因,于是换subprocess.Popen(),顺带发现了”cwd=”这玩意,可以指定子进程工作路径了。参考: 
Python执行系统命令:使用subprocess的Popen函数 
先用个QPushbutton挂着QFileDialog来获取文件完整路径+文件名,内容放到LineEdit(类似文本框TextBox)里:

# 首先有一个文本框(LineEdit)的名字(objectName)为tb_line1
self.tb_line1 = QLineEdit()

# 按钮的内容、信号连接
self.btn_fileDiaLog = self.createButton("选择客户端文件", self.showDialog)

# 绑定的事件
def showDialog(self):
    filename = QFileDialog.getOpenFileName(self, "选取文件","F:/","EXE Files (*.exe);;All Files (*)")
    self.tb_line1.setText(filename[0])  # content 

# 创建按钮用的函数
def createButton(self, text, member):
    button = QPushButton(text)
    button.clicked.connect(member)
    return button
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
# 从文本框获得文件的工作路径
exe_dir = os.path.dirname(os.path.abspath(self.tb_line1.displayText()))         

# 启动命令
cmd = 'start '+ exe_name
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,cwd = exe_dir)
proc.stdin.write(cmd.encode())
proc.stdin.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

os.path.dirname(os.path.abspath(“文件名”)): 表示获取当前文件夹的所在的目录。 
Python中的绝对路径和相对路径 
比如完整文件路径:C:\Program Files\12345\砍吖.exe 
abs_path就得到:C:\Program Files\12345 
这样就不会报错啦,不用去拆文件路径的各个文件夹名。

作者:andyliulin 发表于 2017/10/26 16:27:24  原文链接 https://blog.csdn.net/andyliulin/article/details/78355448
阅读:351

猜你喜欢

转载自blog.csdn.net/ww2890chen/article/details/80236424