[Work Automation] Create Game Console App (VSCode + PowerShell + Qt for Python)
Windows work automation development history :
- Windows PowerShell (Windows PowerShell 5.1, .NET Framework)
- PowerShell Core (PowerShell 7, .NET Core 3.1)
The following is an introduction to using PowerShell and Qt in VSCode :
Environment Build
- Install Qt 5.15.0 (download link)
- Install Qt Creator IDE
- Install Qt Design Studio
- Install Python 3.8.5 (download link)
- Install PySide2 5.15.0 (download link)
- Install PyInstaller 4.0 (download link)
- Install Visual Studio Code (download link)
- Install PsTools (download link)
Windows Environment Settings
setup.ps1
setup.ps1
# following power shell script must be run on administrator
# enable administrator and set password
net user administrator [password] /active:yes
# ------------------------------
# after loging administrator account
# set execution policy for run *.ps1 using Invoke-Command
Set-ExecutionPolicy RemoteSigned
# setup WinRM
winrm quickconfig -Force
Enable-PSRemoting -Force -SkipNetworkProfileCheck
Set-Item wsman:localhost\client\trustedhosts -Force -Value *
Deploy
deploy.ps1
deploy.ps1
param([String]$ip="")
$username = "administrator"
$password = "*********"
$source = "C:\DStudio\GameConsole\"
$destination = "C:\DStudio\GameConsole\"
$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object PSCredential -ArgumentList $username,$secureStringPwd
$Session = New-PSSession -ComputerName $ip -Credential $creds
Invoke-Command -Session $Session -ScriptBlock {Remove-Item -Path $args[0] -Recurse} -ArgumentList $destination
Copy-Item -Path $source -Destination $destination -ToSession $Session -Recurse
Create a Game Console App
- Design User Interface
Qt Creator
New project > Application (Qt for Python) > Qt for Python - Window (UI file)
> Location > Details > Define Class > Base class = "QWidget"
// Do NOT select "QDialog" or "QMainWindow" to base class, else *.ui will load failed by default code.
Done. Like this. - User Interface Control
Visual Studio Code
Buttons event binding :
main.py# Buttons Event widget.pushButton_StartVideo.clicked.connect(lambda:buttonEvent("StartVideo")) widget.pushButton_StopVideo.clicked.connect(lambda:buttonEvent("StopVideo")) widget.pushButton_StartGame.clicked.connect(lambda:buttonEvent(widget.comboBox_GameName.currentIndex())) widget.pushButton_StopGame.clicked.connect(lambda:buttonEvent("StopGame"))
Run powershell script :
main.pydef buttonEvent(name): def getPsCode(var): return{ "StartVideo": "StartVideo.ps1", "StopVideo": "StopVideo.ps1", 0: "StartGame.ps1", #GameNameA 1: "StartGame.ps1", #GameNameB 2: "StartGame.ps1", #GameNameC "StopGame": "StopGame.ps1", }.get(var,"error") #'error' default return def getGameName(var): return{ 0: "GameNameA", 1: "GameNameB", 2: "GameNameC", }.get(var,"error") #'error' default return print(getGameName(name)) path = os.path.join(os.path.dirname(__file__), getPsCode(name)) cmd = ["powershell.exe", "-ExecutionPolicy", "RemoteSigned", "-File", path, "-playerNum", widget.comboBox_PlayerNum.currentText(), "-gameName", getGameName(name)] subprocess.Popen(cmd)
All : main.py
# This Python file uses the following encoding: utf-8 import sys import os import subprocess from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton from PySide2.QtCore import QFile from PySide2.QtUiTools import QUiLoader import PySide2.QtXml def buttonEvent(name): def getPsCode(var): return{ "StartVideo": "StartVideo.ps1", "StopVideo": "StopVideo.ps1", 0: "StartGame.ps1", #GameNameA 1: "StartGame.ps1", #GameNameB 2: "StartGame.ps1", #GameNameC "StopGame": "StopGame.ps1", }.get(var,"error") #'error' default return def getGameName(var): return{ 0: "GameNameA", 1: "GameNameB", 2: "GameNameC", }.get(var,"error") #'error' default return print(getGameName(name)) path = os.path.join(os.path.dirname(__file__), getPsCode(name)) cmd = ["powershell.exe", "-ExecutionPolicy", "RemoteSigned", "-File", path, "-playerNum", widget.comboBox_PlayerNum.currentText(), "-gameName", getGameName(name)] subprocess.Popen(cmd) if __name__ == "__main__": app = QApplication([]) # Load UI ui_file_name = "form.ui" path = os.path.join(os.path.dirname(__file__), ui_file_name) ui_file = QFile(path) if not ui_file.open(QFile.ReadOnly): print("Cannot open {}: {}".format(ui_file_name, ui_file.errorString())) sys.exit(-1) loader = QUiLoader() window = loader.load(ui_file) ui_file.close() window.show() # Buttons Event window.startVideo.clicked.connect(lambda:buttonEvent("StartVideo")) window.stopVideo.clicked.connect(lambda:buttonEvent("StopVideo")) window.pushButton_StartGame.clicked.connect(lambda:buttonEvent(window.comboBox_GameName.currentIndex())) window.pushButton_StopGame.clicked.connect(lambda:buttonEvent("StopGame")) sys.exit(app.exec_())
- Task Automation
computers.txt192.168.1.101 192.168.1.102 192.168.1.103
startGame.ps1
// GUI program doesn't work, use psexec instead of Invoke-Command.param([Int32]$playerNum, [String]$gameName) function SelectPlayer { param ( $_playerNum ) if ($_playerNum -eq 1) { return $computers[0] } elseif ($_playerNum -eq 2) { return $computers[0] + "," + $computers[1] } elseif ($_playerNum -eq 3) { return $computers[0] + "," + $computers[1] + "," + $computers[2] } return "" } function SelectGame { param ( $_gameName ) if ($_gameName -eq "GameNameA") { return $filePathA } elseif ($_gameName -eq "GameNameB") { return $filePathB } elseif ($_gameName -eq "GameNameC") { return $filePathC } return "" } $username = "administrator" $password = "*********" $computers = Get-Content -Path "C:\DStudio\GameConsole\computers.txt" $players = SelectPlayer $playerNum $filePathA = "C:\DStudio\GameConsole\GameNameA.exe" $filePathB = "C:\DStudio\GameConsole\GameNameB.exe" $filePathC = "C:\DStudio\GameConsole\GameNameC.exe" $filePath = SelectGame $gameName & psexec.exe \\$players -u administrator -p $password -i -d -accepteula cmd /c start $filePath
Detail : PsExec v2.2
stopGame.ps1
// Before executing Video.UI.exe (Movie & TV) through the remote command for the first time, it must be executed manually once.$username = "administrator" $password = "*********" $computers = Get-Content -Path "C:\DStudio\GameConsole\computers.txt" $processA = "GameNameA" $processB = "GameNameB" $processC = "GameNameC" $dirPath = "C:\PumpkinStudio\GameConsole" $filePath = "Video.mp4" $secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force $creds = New-Object PSCredential -ArgumentList $username,$secureStringPwd $Session = New-PSSession -ComputerName $computers -Credential $creds Invoke-Command -Session $Session -ScriptBlock {Stop-Process -Name $args[0] -Force} -ArgumentList $processA Invoke-Command -Session $Session -ScriptBlock {Stop-Process -Name $args[0] -Force} -ArgumentList $processB Invoke-Command -Session $Session -ScriptBlock {Stop-Process -Name $args[0] -Force} -ArgumentList $processC Invoke-Command -Session $Session -ScriptBlock {Start-Process -FilePath $args[0] -WorkingDirectory $args[1]} -ArgumentList $filePath,$dirPath
// Use Video.UI to open the video remotely. To maximize it, manually press the maximize button on the upper right - Freeze Program
// Console window invisiblepyinstaller -w .\main.py
// Python Log : ./build/[ProjectName]/warn-main.txt
Complete! But don't forget to copy form.ui to the same directory as the executable file.
Detail : Using PyInstaller
More