1. 程式人生 > >Python的自動操作(掛機)指令碼相關(一)

Python的自動操作(掛機)指令碼相關(一)

之前用了數個月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

附:VBScript獲取滑鼠游標當前位置座標(當前螢幕解析度下的)
新建該*.vbs檔案放桌面上,單擊選中,然後滑鼠游標放在要獲得座標的位置,再回車該檔案即可,就會彈出對應位置座標

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") 
Set colItems = objWMIService.ExecQuery("Select * from Win32_DesktopMonitor",,48) 

For Each objItem in colItems 
WScript.Echo "ScreenHeight: " & objItem.ScreenHeight 
WScript.Echo "ScreenWidth: " & objItem.ScreenWidth 
Next 

附:Python獲取螢幕解析度

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

a, b = DisplaySize()

———————————————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 & _

也該注意到了,用了user32.dll,哦也就是win的api這樣。在VBS中使用:

oExcel.Run "BlockInput", True  '遮蔽滑鼠鍵盤
wscript.Sleep 1000    '你-1s
oExcel.Run "BlockInput", False '記得解除鎖定

——————————————.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)  # 該解鎖啦

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 

——————————————.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彈出視窗訊息")

4. 啟動外部程式

而某些軟體啟動的時候會掛上其他東西…
(非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&")   '穩

命令列:”%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

根據以上弄了個拆檔案路徑的玩意:

# 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")

(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)

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
# 從文字框獲得檔案的工作路徑
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()

os.path.dirname(os.path.abspath(“檔名”)): 表示獲取當前資料夾的所在的目錄。
Python中的絕對路徑和相對路徑
比如完整檔案路徑:C:\Program Files\12345\砍吖.exe
abs_path就得到:C:\Program Files\12345
這樣就不會報錯啦,不用去拆檔案路徑的各個資料夾名。

18.05.31

更新:VBS獲取滑鼠游標當前位置的座標
待更新:在Win下面獨立程式弄簡單操作的指令碼用什麼Python?直接C#完事,節約時間和程式大小佔用空間,有空再放C#指令碼過來,C#打包完才幾百K大小的.EXE,Python庫太多打包EXE大到幾十M