影刀上不止可以使用python轮子库了,还可以使用.NET的轮子库一起用起来,.NET语言好多库比python优秀
评论
收藏

影刀上不止可以使用python轮子库了,还可以使用.NET的轮子库一起用起来,.NET语言好多库比python优秀

经验分享
E
Excel催化剂
2024-06-06 17:54·浏览量:1486
E
Excel催化剂
影刀中级开发者
发布于 2024-06-06 17:04更新于 2024-06-06 17:541486浏览

今天认真尝试了一下在python上调用.NET库的实现,多谢gpt时代,学习成本很低,问了几轮gpt,终于打通了。

可喜的是,在影刀上,也是可以无障碍使用的。


为什么要有这个需求?

因为每种语言都有它的优点擅长的东西,python语言很优秀,爬虫玩得飞起。但是论到桌面自动化,还是.NET语言老道,毕竟桌面自动化几乎等同于windows自动化,.NET是微软亲儿子,能不好吗?.NET社区,过往可是桌面开发工具的标配,包括影刀windows版本也是.NET技术开发的。

当下我想到有价值的应用点是:

桌面UI自动化

.NET里的flaui库,据我的认知,应该比pywinauto要强,可以有xpath使用,还有很多特性,文档也全,也容易学习。

Excel的操作

.NET里有一个不依赖于COM组件的实现轮子叫EPPLUS,对标的是python的openpyxl。这个轮子虽说是新版要商业授权,但自己内部使用,应该很安全的,旧版的功能也足够丰富。新版功能很屌炸,实现了全套OFFICE的公式引擎,连最新的动态数组公式溢出都有。影刀在使用openpyxl里,是拿不到公式计算的结果的,但在EPPLUS是可以的,并且在内存里新写的公式一样能计算。还有很多很多,甩openpyxl几条街。

在.NET里,调用OFFICE的COM接口自动化操作,也是最完整的,和VBA接口一致,比起python的wincom32、xlwings要强大完整得多。

熟悉.NET语言的程序员群体

曾经的我,是不想用影刀的,因为python不是我的主要语言,我更倾向于uibot、PAD、uipath这些类VB和VB语言,对我更熟悉。但gpt时代,代码已经不是障碍,也因影刀实在是优秀,所以全面拥抱影刀了,相信能够打通.NET的轮子库,很多熟悉.NET语言的群体,也会更喜欢用影刀,将.NET库的实现改造成python,gpt很能胜任,哈哈。

最后,附上源代码,供爱好者尝试下:

能够实现这种能力的跨越,只在python上需要安装一个pythonnet的包就可以。

# 使用提醒:
# 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能
# 2. package包提供访问当前应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能
# 3. 当此模块作为流程独立运行时执行main函数
# 4. 可视化流程中可以通过"调用模块"的指令使用此模块

import xbot
from xbot import print, sleep
from .import package
from .package import variables as glv
import clr
from pathlib import Path
import sys

def main(args):

    app_path=Path(__file__).parent
    dll_dir=app_path / 'resources'
    for file in dll_dir.iterdir():
        clr.AddReference(str(file))

    # 导入 .NET 命名空间
    from FlaUI.UIA3 import UIA3Automation, UIA3PropertyLibrary
    from FlaUI.Core.Conditions import ConditionFactory
    from FlaUI.Core.Definitions import WindowVisualState
    # 使用 UIA3Automation 获取桌面元素
    automation = UIA3Automation()

    # 获取桌面作为根元素
    desktop = automation.GetDesktop()

    # 创建 ConditionFactory 实例
    property_library = UIA3PropertyLibrary()
    condition_factory = ConditionFactory(property_library)

    # 查找微信窗口
    wd_wechat = desktop.FindFirstChild(condition_factory.ByClassName("WeChatMainWndForPC"))
    if wd_wechat is None:
        print("未能找到微信窗口")
        sys.exit()

    if wd_wechat.Patterns.Window.Pattern.WindowVisualState == WindowVisualState.Minimized:
        wd_wechat.Patterns.Window.Pattern.SetWindowVisualState(WindowVisualState.Normal)

    # 查找朋友圈按钮
    btn_friend = wd_wechat.FindFirstByXPath("//Button[@Name='朋友圈']")
    if btn_friend is None:
        print("未能找到朋友圈按钮")
        sys.exit()

    # 点击朋友圈按钮
    btn_friend.Click()

    print("成功点击朋友圈按钮")

    # 保持控制台窗口打开
    input("按任意键退出...")

使用COM组件调用Excel,有些麻烦,但能用是最关键,背后写代码辛苦点是小事,没有某个接口,实现不出来,那才要命。

import clr
import sys
from datetime import datetime

# 添加对 COM 库的引用
clr.AddReference('System.Runtime.InteropServices')

# 导入必要的命名空间
from System import Type, Activator
from System.Runtime.InteropServices import Marshal, COMException
from System.Reflection import BindingFlags

# 添加对 Excel COM 对象的引用
clr.AddReference(r'C:\Program Files (x86)\Microsoft Visual Studio\Shared\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.Excel.dll')

# 导入 Excel 命名空间
import Microsoft.Office.Interop.Excel as Excel

# 尝试获取当前正在运行的 Excel 实例
try:
    excel_app = Marshal.GetActiveObject('Excel.Application')
    workbook = excel_app.GetType().InvokeMember("ActiveWorkbook", BindingFlags.GetProperty, None, excel_app, None)
except COMException:
    excel_app_type = Type.GetTypeFromProgID("Excel.Application")
    excel_app = Activator.CreateInstance(excel_app_type)
    workbooks = excel_app.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, None, excel_app, None)
    workbook = workbooks.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, None, workbooks, None)
    
# 确认获取到 Excel 应用实例
if excel_app:
    # 设置 Excel 可见
    excel_app.GetType().InvokeMember("Visible", BindingFlags.SetProperty, None, excel_app, [True])
    # 获取 Excel 版本
    excel_version = excel_app.GetType().InvokeMember("Version", BindingFlags.GetProperty, None, excel_app, None)
    print(f"Excel版本: {excel_version}")

    # 确认获取到工作簿
    if workbook:
        # 获取活动工作表
        worksheet = workbook.GetType().InvokeMember("ActiveSheet", BindingFlags.GetProperty, None, workbook, None)

        # 确认获取到工作表
        if worksheet:
            # 写入数据到单元格
            worksheet.GetType().InvokeMember("Cells", BindingFlags.SetProperty, None, worksheet, [1, 1, "Hello, Excel!"])
            worksheet.GetType().InvokeMember("Cells", BindingFlags.SetProperty, None, worksheet, [2, 1, datetime.now().strftime("%Y-%m-%d %H:%M:%S")])

            # 保存工作簿
            # workbook.GetType().InvokeMember("Save", BindingFlags.InvokeMethod, None, workbook, None)
            print("数据已写入并保存到活动工作簿。")
        else:
            print("没有找到活动工作表。")
    else:
        print("没有找到活动工作簿。")

input("按任意键退出...")


收藏4
全部评论(1)
最新
发布评论
评论