admin 管理员组文章数量: 1184232
文章目录
- 前言
- 一、怎么激活?
- 二、软件编写
- 1.打开TcXaeShell 勾选你需要的授权,保存项目名为license
- 2.打开软件,定位软件窗口
- 3.定位主窗口上按钮的位置
- 4.点击按钮并试用ocr识别验证码
- 总结
前言
谢谢大家的关注,这是这个twincat3技术分享的第一篇文章,共同学习进步
目前不知道什么原因,Twincat3 还没有任何可以完全破解的方法;某鱼上有方法延长试用证书的方法,但也是治标不治本。
我有一计💡🤓👆
由于没有很复杂的激活步骤及联网的要求,所以使用python桌面自动化的方法每天都激活一次,就约等于无限激活了。
说干就干!
一、怎么激活?
如何生成试用证书,详细步骤参考 倍福虚拟学校
由以上官方文档可知激活的过程,只需要点击几下页面及识别验证码。
二、软件编写
1.打开TcXaeShell 勾选你需要的授权,保存项目名为license
2.打开软件,定位软件窗口
import uiautomation as auto
import time
import pygetwindow as gw
import pyautogui
import ctypes
import subprocess
import win32gui
import win32ui
import win32con
import win32api
import re
#查找指定的窗口
def find_windows_by_keywords(keyword1="license", keyword2="TcXaeShell", ignore_case=True):
"""
查找窗口标题中同时包含两个关键字的窗口
Args:
keyword1 (str): 第一个关键字,默认 "license"
keyword2 (str): 第二个关键字,默认 "TcXaeShell"
ignore_case (bool): 是否忽略大小写,默认 True
Returns:
list: 匹配的窗口标题列表
"""
windows = gw.getAllWindows()
# 构建正则表达式
flags = re.IGNORECASE if ignore_case else 0
pattern = re.compile(
rf'{re.escape(keyword1)}.*{re.escape(keyword2)}|{re.escape(keyword2)}.*{re.escape(keyword1)}',
flags
)
# 筛选匹配的窗口
filtered_windows = [
window.title for window in windows
if window.title and pattern.search(window.title)
]
return filtered_windows
# 打开指定软件(以记事本为例)
def open_software(path, args=None):
if args:
subprocess.Popen([path] + args)
else:
subprocess.Popen([path])
time.sleep(2) # 等待软件启动
open_software("C:\\Program Files (x86)\\Beckhoff\\TcXaeShell\\Common7\\IDE\\TcXaeShell.exe", ["license\\license.sln"])
time.sleep(30) # 等待软件加载完成
winname = find_windows_by_keywords("license", "TcXaeShell")
# 1. 定位到 SYSTEM 节点
top_window = auto.WindowControl(
searchDepth=1,
Name=winname[0]
)
solution_pane = top_window.PaneControl(
Name="解决方案资源管理器",
foundIndex=1
)
tree_view = solution_pane.TreeControl()
system_item = tree_view.TreeItemControl(
Name="SYSTEM",
searchDepth=3
)
# 2. 检查并确保 SYSTEM 节点已展开
try:
expand_pattern = system_item.GetExpandCollapsePattern()
if expand_pattern.ExpandCollapseState != auto.ExpandCollapseState.Expanded:
expand_pattern.Expand() # 展开节点
time.sleep(1) # 等待展开动画
except Exception as e:
print(f"无法获取展开状态,尝试强制展开: {e}")
system_item.DoubleClick() # 回退方案:双击展开
time.sleep(1)
# 3. 查找 License 节点(带重试机制)
max_retries = 3
license_item = None
for _ in range(max_retries):
try:
license_item = system_item.TreeItemControl(
Name="License",
searchDepth=1, # 只在直接子级搜索
timeout=2000 # 单个查找超时2秒
)
break
except LookupError:
print("未找到 License,尝试刷新展开状态...")
try:
expand_pattern.Collapse() # 先折叠
time.sleep(0.5)
expand_pattern.Expand() # 再展开
except:
system_item.DoubleClick() # 回退方案
time.sleep(1)
license_item.DoubleClick() # 双击 License 节点
3.定位主窗口上按钮的位置
winname = find_windows_by_keywords("license", "TcXaeShell")
# 1. 定位主窗口
print("定位主窗口...")
main_window = auto.WindowControl(
Name=winname[0],
searchDepth=1
)
main_window.SetFocus()
print(f"找到主窗口: {main_window.Name}")
# 2. 优化定位目标子窗口
print("定位目标子窗口...")
pane_names = [
"license.tsproj - TwinCAT XAE",
"license - TwinCAT XAE"
]
target_pane = None
for name in pane_names:
try:
target_pane = main_window.PaneControl(Name=name, Timeout=10)
print(f"尝试找到目标子窗口: {name}")
print(f"找到目标子窗口: {target_pane.Name}")
break
except LookupError:
print(f"未找到目标子窗口: {name}")
if target_pane is None:
raise LookupError("未能定位到任何目标子窗口,请检查窗口名称或加载状态。")
target_pane.SetFocus()
time.sleep(1)
# 3. 直接在该窗口下查找按钮并点击
print("查找并点击按钮...")
trial_button = target_pane.ButtonControl(
Name="7 Days Trial License...",
Timeout=10
)
print(f"找到按钮: {trial_button.Name}")
4.点击按钮并试用ocr识别验证码
import torchfree_ocr
# 获取窗口位置和大小
def get_window_rect(title_keyword):
windows = gw.getWindowsWithTitle(title_keyword)
if windows:
win = windows[0]
return win.left, win.top, win.width, win.height
else:
print(f"未找到窗口: {title_keyword}")
return None
def capture_popup_window(title_keyword, save_path="popup_capture.png"):
# 获取窗口句柄和尺寸信息
hwnd = win32gui.FindWindow(None, title_keyword)
if not hwnd:
print("未找到弹窗窗口,无法截图")
return False
# 确保窗口前置(可能需要短暂延迟)
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
win32gui.SetForegroundWindow(hwnd)
time.sleep(0.2) # 等待窗口激活
# 获取窗口尺寸
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
width = right - left
height = bottom - top
# 创建设备上下文
hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
# 创建位图对象
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)
# 选择位图到设备上下文
saveDC.SelectObject(saveBitMap)
# 复制窗口内容到内存DC
result = saveDC.BitBlt(
(0, 0),
(width, height),
mfcDC,
(0, 0),
win32con.SRCCOPY
)
if not result: # 如果复制成功
# 保存位图到文件
saveBitMap.SaveBitmapFile(saveDC, save_path)
print(f"已保存弹窗截图为 {save_path}")
else:
print("截图失败,错误代码:", result)
# 清理资源
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)
return not result
def get_current_keyboard_layout():
hwnd = ctypes.windll.user32.GetForegroundWindow()
thread_id = ctypes.windll.user32.GetWindowThreadProcessId(hwnd, 0)
layout_id = ctypes.windll.user32.GetKeyboardLayout(thread_id)
return hex(layout_id & (2**32 - 1))
def ensure_english_input():
# 英文美式输入法布局为 0x409
for _ in range(5): # 最多尝试5次
layout = get_current_keyboard_layout()
print(f"当前输入法布局: {layout}")
if layout == '0x4090409':
print("已是英文输入法")
return True
# 模拟 Win+Space 切换输入法
pyautogui.hotkey('win', 'space')
time.sleep(0.5)
print("未能自动切换到英文输入法,请手动检查")
return False
def close_popup(title_keyword):
windows = gw.getWindowsWithTitle(title_keyword)
if windows:
win = windows[0]
win.close()
print(f"已关闭弹窗: {title_keyword}")
else:
print(f"未找到弹窗: {title_keyword}")
reader = torchfree_ocr.Reader(["en"])
while True:
trial_button.Click()
time.sleep(5)
capture_popup_window("Enter Security Code")
ocr_result = reader.readtext('popup_capture.png')
print(ocr_result)
answer = [item[1] for item in ocr_result if isinstance(item[1], str) and len(item[1]) == 5] # 截取出有效长度的字符串
print(answer)
# 直接模拟键盘输入 answer[0],区分大小写
if answer:
if ensure_english_input():
pyautogui.typewrite(answer[0], interval=0.1)
print("已输入验证码")
for _ in range(3):
pyautogui.press('enter')
time.sleep(0.2)
else:
print("输入法切换失败,未自动输入验证码")
# 检查弹窗窗口是否存在
popup_rect = get_window_rect("Enter Security Code")
if not popup_rect:
print("弹窗窗口已关闭,自动退出循环")
break
else:
close_popup("Enter Security Code")
else:
close_popup("Enter Security Code")
print("=== 自动化操作完成 ===")
close_popup("TcXaeShell")
pyautogui.press('enter')
总结
使用了ocr技术及python桌面自动化的库;
ocr使用了开源的库,因为没有使用torch 的库并不会硬件的原因出现错误,使用onnx格式的模型优化了对cpu识别的速度。
窗口定位使用了元素的方式进行定位,无论窗口在那个位置,都能准确定位。
成果展示
学习用途只能!!
只能用于学习!!
不可以商业化!!
您可以使用以上代码用于其他项目,需署名作者。
最后 祝您运行成功 西海!! 🙋
版权声明:本文标题:倍福 TwinCAT 3 python自动化激活脚本 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/b/1765818542a3417691.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论