Python学习(六) 史上最全Pywinauto模块自动化操作软件

1本文设计内容较多,但是都不难,都是干货。耐心看下文。

工作中资源更新需要重复行操作软件,这不符合程序的一贯作风,所以使用pywinauto 这个python 模块,实现自动化操作软件。只需鼠标一点,就可以不用管了。是不是很方便。
1当前的需求: 技术人员在每次资源更新的时候,需要重复操作软件来进行版本号的制作,安装包的制作,希望减少这种工作量。
2 用到的工具 pycharm + Unity

2 流程

1使用Unity编辑器模式和Pycharm

1我需要在Unity中 将更新的资源按照选定的项目 复制到 指定的文件夹中
2使用exe制作版本号及资源列表。
3使用SUFDesign 软件进行安装包制作。

2复制

复制这部分直接跳过,个人需要注意的点

GUIStyle st = GUI.skin.FindStyle ("flow node 2");
st.fontSize = 15;
st.alignment = TextAnchor.UpperCenter;
GUILayout.Space (10);
if (GUILayout.Button ("制作版本号\n(慎点!)",st, GUILayout.Height (50), GUILayout.Width (150)))
 {
   CallBuildTool ();
 }

使用GUI内置的风格
在这里插入图片描述

3 Unity执行python脚本制作版本号

Unity并不能执行python脚本,C#是编译型语言,需要先编译,python是解释型语言,直接就可以运行 但是需要解释器,我使用的就是python3.7,安装pycharm 还有Anaconda
Unity开启一个线程 调用解释器 然后解释器执行py 脚本,py脚本进行自动化操作,这就是整个流程。

  #region 调用打包工具
    private static string FilePath = @"F:\workspace\PythonTest\PythonCallHardware\venv\Scripts\python.exe";
    // [MenuItem("PublishTools/制作版本号",false,2)]
    private static void CallBuildTool ()
    {
    
    
        string file = @"F:/workspace/PythonTest/PythonCallHardware/Scripts/CallBuildTools.py";
        ProcessStartInfo start = new ProcessStartInfo ();
        start.FileName = FilePath;
        start.Arguments = file + " " + currentItemType;
        start.UseShellExecute = false;
        //参数用空格分隔
        //start.Arguments = path + " " + type + " " + mode;
        start.RedirectStandardOutput = true;
        start.RedirectStandardInput = true;
        start.RedirectStandardError = true;
        start.CreateNoWindow = false;
        Process process = Process.Start (start);
    }
    #endregion

和我们使用CMD一样 使用某一软件执行文件,
start.FileName = FilePath;参数是解释器的位置
start.Arguments = file + " " + currentItemType;第一个参数是文件位置 ,第二个是我选择的项目类型
注意参数之间是用空格隔开

4Unity执行python脚本制作安装包

调用方法同理参考上方
在这里插入图片描述

5接下来重头戏 使用pywinauto模块自动化操作

我在使用的时候 我一般使用conda 来下载模块包 但是这个模块使用conda 是不能下载的 我是用的pip下载的 当然最后我使用的不是conda安装时的编译器。

1我们如何在脚本中获取 传递过来的参数
我们使用 sys 模块 sys.argv[1]是第一个参数 一次类推

	self.CurrentType = int(sys.argv[1]))
	self.CurrentModel = int(sys.argv[2])

2 如果判断类型呢
我们使用enum枚举

class ProjectType(enum.Enum):
	'''
	项目类别
	'''
	CeLiang = 1
	GongYi = 2
	GCLX = 3
	AnZhuangShiTu = 4
	ZhuangPeiShi = 5
	PingFa = 6
	JingZhuangXiu = 7
	GouZhao = 8
	AnQuanWenMingGongDi = 9
	JiLiangJiJia = 10
	DaoLuGongCheng = 11
	QiangLiangGongCheng = 12
	ShouGongSuanLiang = 13
	GangJieGou = 14,
	# 建筑电气施工
	JianZhuDianQiShiGong = 15,
	DaqQiaoShiTu = 16,
	SuiDaoGongCheng = 17,
	# 不确定
	GongChengShiTu = 18,

我们在使用的时候 可以 吧数字对应成 项目名 使用

self.modelType = ModelType(self.CurrentModel)

3 最重要的来了 pywinauto模块
我们需要判断当前软件窗口的类型 uia 还是win32
链接:https://pan.baidu.com/s/1VQv_SKGGCHwVZIqxa5iyMQ
提取码:x5nt
确定之后 使用模块调用软件创建联系

	app = Application(backend='uia').start(r"F:\work\SetupFactory\SUFDesign.exe", timeout=10)
		# 把进程和当前获得句柄联系起来
	app = Application().connect(path=r"F:\work\SetupFactory\SUFDesign.exe", timeout=10)

都可以通过app.window()获取子空间和窗体

		# 获取 当前的窗 通过标题
		dlg_new = app.window(title="Start a New Project")
		dlg_new.wait("ready", timeout=5)  # 等待窗体响应  有很多状态 可以看方法内部的介绍
		dlg_new.print_control_identifiers()# 打印出 窗体的结构  你可以查找对应的控件
		# 标识一下
		dlg_new.draw_outline() 在窗体的周边划线 

找到按钮进行点击

		btn_cancle = dlg_new[r'Cancle']
		btn_cancle.click()

使用快捷键

		dlg_Open = app.window(title=r"Untitled - Setup Factory")
		dlg_Open.wait("exists enabled visible ready", timeout=5)
		dlg_Open.draw_outline()

		# dlg_Open.print_control_identifiers()
		# 使用快捷键 打开suf
		dlg_Open.type_keys("^O")

对应快捷键的写法
在这里插入图片描述我遇到的问题 就是选择combobox里面的选项

		# 选择组合框中的
		dlg_Mul.ComboBoxWrapper.select("Always overwrite existing file")

4 在使用pywinauto 的时候 报错 坑了很久 是程序是32的 而我使用的是64位python.exe

# 解决不能运行自己做的exe的问题
import os
os.environ.update({
    
    "__COMPAT_LAYER":"RUnAsInvoker"})
# 解决报错 是32位程序需要 使用32位python.exe
import warnings
warnings.simplefilter('ignore', category=UserWarning)

在使用过程中 需要不断的试错 适当的时候让程序sleep 因为没有程序没有完全打开 脚本就不能进行下去
我们可以获取当前焦点

		dlg_Pro.get_active()
		dlg_Pro.get_focus()

SUFDesign 就是这样
在这里插入图片描述
下附全部脚本
Unity C#

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
using System.Diagnostics;

/// <summary>
/// 将I盘下的各个工程的资源和播放器移动到H盘下  方便制作安装包
/// </summary>
enum itemType
{
    
    
    测量 = 1,
    工艺 = 2,
    工程力学 = 3,
    安装识图 = 4,
    装配式 = 5,
    平法 = 6,
    精装修 = 7,
    构造 = 8,
    安全文明工地 = 9,
    计量计价 = 10,
    道路工程 = 11,
    桥梁工程 = 12,
    手工算量 = 13,

    钢结构 = 14,
    建筑电气施工 = 15,
    道桥识图 = 16,
    隧道工程 = 17,

    工程识图 = 18,
    造价识图 = 20

}
public class PublishEditorWindow : EditorWindow
{
    
    
    #region 复制文件


    private static itemType currentItemType = itemType.安装识图;
    private static float Window_height = 400;
    private static float Window_width = 1000;
    private static float LeftArea_width;
    private static float RightArea_height;
    private GUIStyle fontStyle;

    //private static string Source_DirvePath = @"H:/PatchTool/RGZSoft/";
    private static string Source_DirvePath = @"D:/工作安装包/PatchTool/RGZSoft";
    //private static string Target_DirvePath = @"I:/rgzsoft/RGZSoft/";
    private static string Target_DirvePath = @"D:/工作安装包/网页版本打包项";
    /// <summary>
    /// 目的资源路径
    /// </summary>
    private static string Source_player_module = "module";
    private static string Source_weike = @"WeiKe/WKPlayerResources/WKAssets";


    /// <summary>
    /// 当前资源路径
    /// </summary>
    private static string Target_player_module = "module";
    private static string Target_weike = @"WeiKe/WKPlayerResources/WKAssets";

    private static string sourceAssetsPath;
    private static string sourcePlayerPath;
    private static List<string> sourceWkPath;
    private static string TargetAssetsPath;
    private static string TargetPlayerPath;
    private static string TargetWkPath;

    private static bool IsAssetCopy = true;
    private static bool IsPlayerCopy = true;
    private static bool IsWkCopy = true;
    private static bool IsWkPlayer = true;
    private static string str;

    private string towkBg;
    private string fromwkBg;
    private string fromwkXml;
    private string towkXml;

    private string fromWkPlayerPath;
    private string toWkPlayerPath;

    [MenuItem ("PublishTools/移动各项目资源", false, 1)]
    private static void PublishWebglTool ()
    {
    
    
        PublishEditorWindow publish = GetWindowWithRect<PublishEditorWindow> (new Rect (0, 0, Window_width, Window_height), false, "移动项目资源");
        publish.ShowPopup ();
        LeftArea_width = Window_width / 3 * 2;
        RightArea_height = Window_width - LeftArea_width;
        sourceWkPath = new List<string> ();
    }

    private void DrawLabel ( string content, GUIStyle style = null )
    {
    
    
        EditorGUILayout.BeginHorizontal ();
        GUILayout.Label ("已选择的源播放器路径:", style);
        GUILayout.TextField (sourcePlayerPath);
        EditorGUILayout.EndHorizontal ();
    }
    private void OnGUI ()
    {
    
    
        fontStyle = GUI.skin.FindStyle ("flow node 0");
        //fontStyle.normal.textColor = Color.white;
        fontStyle.fontSize = 12;
        GUIStyle style = new GUIStyle ();
        style.fixedWidth = 130;
        style.normal.textColor = Color.red;
        GUILayout.BeginArea (new Rect (LeftArea_width, 0, RightArea_height, Window_height), "", "box");
        EditorGUILayout.BeginVertical ();
        EditorGUILayout.LabelField ("请选择要移动的项目:");
        EditorGUILayout.LabelField ("项目名称");

        currentItemType = (itemType)EditorGUILayout.EnumPopup (currentItemType, GUILayout.Height (25));
        if (GUILayout.Button ("确定"))
        {
    
    
            CompactStringPath ();
        }
        EditorGUILayout.LabelField ("如果你选择复制选择的项目,请按下方按钮:");
        if (GUILayout.Button ("复制已选的项目"))
        {
    
    
            CopySelectItem ();
        }
        EditorGUILayout.LabelField ("如果你选择复制全部的项目,请按下方按钮:");
        if (GUILayout.Button ("复制全部项目"))
        {
    
    
            CopyMultipleDirectory ();
        }
        EditorGUILayout.EndVertical ();


        GUILayout.Space (50);
        if (GUILayout.Button ("清理缓存"))
        {
    
    
            EditorUtility.UnloadUnusedAssets ();
        }
        GUILayout.EndArea ();

        //绘制左边
        GUILayout.BeginArea (new Rect (0, 0, LeftArea_width, Window_height), "", "box");
        EditorGUILayout.BeginVertical ();
        GUILayout.Space (5);
        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("已选择的源文件路径",CurrentPath);     
        GUILayout.Label ("已选择的源文件路径:", style);
        GUILayout.TextField (sourceAssetsPath);
        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (2);
        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("已选择的源文件路径",CurrentPath);
        GUILayout.Label ("已选择的源播放器路径:", style);
        GUILayout.TextField (sourcePlayerPath);
        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (2);
        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("已选择的源文件路径",CurrentPath);
        GUILayout.Label ("已选择的源微课资源路径:", style);
        GUILayout.TextField (GetStrByList (sourceWkPath));
        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (2);
        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("已选择的源文件路径",CurrentPath);
        GUILayout.Label ("已选择的微课播放器路径:", style);
        GUILayout.TextField (fromWkPlayerPath);
        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (5);

        EditorGUILayout.BeginHorizontal ();
        GUILayout.Label ("目标互动资源路径:", style);
        GUILayout.TextField (TargetAssetsPath);
        EditorGUILayout.EndHorizontal ();

        GUILayout.Space (2);
        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("要复制的目标路径:",TargetPath);
        GUILayout.Label ("目标播放器路径:", style);
        GUILayout.TextField (TargetPlayerPath);
        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (2);
        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("要复制的目标路径:",TargetPath);
        GUILayout.Label ("目标微课资源路径:", style);
        GUILayout.TextField (TargetWkPath);
        EditorGUILayout.EndHorizontal ();

        EditorGUILayout.BeginHorizontal ();
        //EditorGUILayout.LabelField ("已选择的源文件路径",CurrentPath);
        GUILayout.Label ("目标微课播放器路径:", style);
        GUILayout.TextField (toWkPlayerPath);
        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (5);

        IsAssetCopy = EditorGUILayout.Toggle ("互动资源", IsAssetCopy);
        IsPlayerCopy = EditorGUILayout.Toggle ("播放器资源", IsPlayerCopy);
        IsWkCopy = EditorGUILayout.Toggle ("微课资源(全部)", IsWkCopy);
        IsWkPlayer = EditorGUILayout.Toggle ("微课播放器", IsWkPlayer);
        EditorGUILayout.EndVertical ();

        GUILayout.Space (20);
        GUIStyle button_style;
        button_style =/* GUI.skin.FindStyle ("flow node 1");*/new GUIStyle ();
        button_style.fontSize = 17;
        button_style.fontStyle = FontStyle.Bold;
        //button_style.margin = new RectOffset (0,0,0,0);
        button_style.alignment = TextAnchor.MiddleLeft;
        button_style.normal.textColor = Color.red;
        EditorGUILayout.BeginHorizontal ();
        GUILayout.Label ("当前已选项目是: ", GUILayout.Width (100));
        button_style.normal.textColor = Color.green;
        GUILayout.Label (currentItemType.ToString (), button_style, GUILayout.Width (200));

        EditorGUILayout.EndHorizontal ();
        GUIStyle st = GUI.skin.FindStyle ("flow node 2");
        st.fontSize = 15;
        st.alignment = TextAnchor.UpperCenter;
        GUILayout.Space (10);
        if (GUILayout.Button ("制作版本号\n(慎点!)",st, GUILayout.Height (50), GUILayout.Width (150)))
        {
    
    
            CallBuildTool ();
        }
        GUILayout.EndArea ();

        //绘制右边

    }


    private void CompactStringPath ()
    {
    
    
        Resources.UnloadUnusedAssets ();

        //源资源
        sourceAssetsPath = PathTool.CombinePath (Source_DirvePath, GetDirNameByType (currentItemType));
        sourcePlayerPath = PathTool.CombinePath (Source_DirvePath, Target_player_module, GetDirNameByType (currentItemType));

        fromWkPlayerPath = PathTool.CombinePath (Source_DirvePath, Source_player_module, "WeiKe");
        toWkPlayerPath = PathTool.CombinePath (Target_DirvePath, currentItemType.ToString (), currentItemType.ToString () + "微课", Target_player_module, "WeiKe");
        str = GetWkNameByType (currentItemType);
        if (str.Contains ("+"))
        {
    
    
            string[] sourceWkPath_Arr = str.Split ('+');
            sourceWkPath.Clear ();
            foreach (var i in sourceWkPath_Arr)
            {
    
    
                if (!sourceWkPath.Contains (i))
                    sourceWkPath.Add (PathTool.CombinePath (Source_DirvePath, Target_weike, i));
            }
        }
        else
        {
    
    
            sourceWkPath.Clear ();
            sourceWkPath.Add (PathTool.CombinePath (Source_DirvePath, Target_weike, GetWkNameByType (currentItemType)));
        }
        TargetAssetsPath = PathTool.CombinePath (Target_DirvePath, currentItemType.ToString (), currentItemType.ToString () + "互动", GetDirNameByType (currentItemType));
        TargetPlayerPath = PathTool.CombinePath (Target_DirvePath, currentItemType.ToString (), currentItemType.ToString () + "互动", Target_player_module, GetDirNameByType (currentItemType));
        TargetWkPath = PathTool.CombinePath (Target_DirvePath, currentItemType.ToString (), currentItemType + "微课", Target_weike, GetWkNameByType (currentItemType));

        towkBg = PathTool.CombinePath (Target_DirvePath, currentItemType.ToString (), currentItemType + "微课", Target_weike, "WKLoadBG");

        fromwkBg = PathTool.CombinePath (Source_DirvePath, Source_weike, "WKLoadBG");
        towkXml = PathTool.CombinePath (Target_DirvePath, currentItemType.ToString (), currentItemType + "微课", Target_weike, "WK_ID对照表.xml");
        fromwkXml = PathTool.CombinePath (Source_DirvePath, Source_weike, "WK_ID对照表.xml");


        UnityEngine.Debug.Log ("源文件互动路径sourceAssetsPath" + sourceAssetsPath);
        UnityEngine.Debug.Log ("源文件互动播放器路径sourcePlayerPath" + sourcePlayerPath);
        UnityEngine.Debug.Log ("源文件微课资源路径sourceWkPath" + string.Join (" ", sourceWkPath.ToArray ()));
        UnityEngine.Debug.Log ("源文件WK_ID对照表 " + fromwkXml);
        UnityEngine.Debug.Log ("源文件微课背景图路径 " + fromwkBg);
        UnityEngine.Debug.Log ("源文件微课播放路径 " + fromWkPlayerPath);

        UnityEngine.Debug.Log ("目标互动路径TargetAssetsPath" + TargetAssetsPath);
        UnityEngine.Debug.Log ("目标互动播放器路径TargetPlayerPath" + TargetPlayerPath);
        UnityEngine.Debug.Log ("目标微课资源路径TargetWkPath" + TargetWkPath);
        UnityEngine.Debug.Log ("目标微课背景图路径 towkBg" + towkBg);
        UnityEngine.Debug.Log ("目标WK_ID对照表 " + towkXml);
        UnityEngine.Debug.Log ("目标文件微课播放器 " + toWkPlayerPath);
    }
    private string GetStrByList ( List<string> str_list )
    {
    
    
        StringBuilder sb = new StringBuilder ();
        foreach (string s in str_list)
        {
    
    
            sb.Append (s);
            if (s != str_list[str_list.Count - 1])
                sb.Append ("\n");
        }
        return sb.ToString ();
    }

    private void CopySelectItem ()
    {
    
    
        //互动资源
        if (IsAssetCopy)
            CopySelectDirectory (sourceAssetsPath, TargetAssetsPath);
        //互动播放器
        if (IsPlayerCopy)
            CopySelectDirectory (sourcePlayerPath, TargetPlayerPath);
        //微课资源
        if (IsWkCopy)
        {
    
    
            foreach (var i in sourceWkPath)
            {
    
    
                CopySelectDirectory (i, TargetWkPath);
            }
            //背景图
            CopySelectDirectory (fromwkBg, towkBg);
            //wk对照表
            File.Copy (fromwkXml, towkXml, true);
        }
        //微课播放器
        if (IsWkPlayer)
            CopySelectDirectory (fromWkPlayerPath, toWkPlayerPath);

        UnityEngine.Debug.Log (string.Format ("<color=red>复制完成{0}</color>", currentItemType));
    }
    /// <summary>
    /// 复制选择的文件夹
    /// </summary>
    /// <param name="sourcePath">源文件路径</param>
    /// <param name="targetPath">目标文件路径</param>
    private static void CopySelectDirectory ( string sourcePath, string targetPath )
    {
    
    
        if (!Directory.Exists (targetPath))
        {
    
    
            Directory.CreateDirectory (targetPath);
        }
        DirectoryInfo dirInfo = new DirectoryInfo (sourcePath);
        List<FileInfo> fileList = new List<FileInfo> (dirInfo.GetFiles ());
        fileList.ForEach (c =>
        {
    
    
            EditorUtility.DisplayProgressBar ("正在复制", c.FullName, (int)(fileList.IndexOf (c) + 1 / fileList.Count));
            string destPath = PathTool.CombinePath (targetPath, c.Name);
            File.Copy (c.FullName, destPath, true);
            UnityEngine.Debug.Log (c.FullName + "复制到to" + destPath + "成功");
        });

        List<DirectoryInfo> folders = new List<DirectoryInfo> (dirInfo.GetDirectories ());
        folders.ForEach (c =>
        {
    
    
            string targetpath = PathTool.CombinePath (targetPath, c.Name);
            UnityEngine.Debug.Log (string.Format ("文件夹中 源文件{0},目标文件{1}", c.FullName, targetpath));
            CopySelectDirectory (c.FullName, targetpath);
        });
        EditorUtility.ClearProgressBar ();
    }
    /// <summary>
    /// 复制全部的文件夹
    /// </summary>
    /// <param name="sourcePath"></param>
    /// <param name="targetPaht"></param>
    private static void CopyMultipleDirectory ()
    {
    
    

    }
    /// <summary>
    /// 获得互动名称
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    private static string GetDirNameByType ( itemType type )
    {
    
    
        string dirname = string.Empty;
        switch (type)
        {
    
    
            case itemType.安装识图:
                dirname = "AnZhuangShiTu";
                break;
            case itemType.测量:
                dirname = "CeLiang";
                break;
            case itemType.钢结构:
                dirname = "GangJieGou";
                break;
            case itemType.工程识图:
                dirname = "GongChengShiTu";
                break;
            case itemType.工艺:
                dirname = "GongYi";
                break;
            case itemType.构造:
                dirname = "Struct";
                break;
            case itemType.计量计价:
                dirname = "JiLiangJiJia";
                break;
            case itemType.精装修:
                dirname = "jingzhuangxiu";
                break;
            case itemType.工程力学:
                dirname = "GCLX";
                break;
            case itemType.平法:
                dirname = "PingFa";
                break;
            case itemType.造价识图:
                dirname = "CostKnowledge";
                break;
            case itemType.装配式:
                dirname = "ZhuangPeiShi";
                break;
            case itemType.建筑电气施工:
                dirname = "InstallProject";
                break;
            case itemType.桥梁工程:
                dirname = "BridgeProject";
                break;
            case itemType.道桥识图:
                dirname = "BridgeFigure";
                break;
            case itemType.隧道工程:
                dirname = "SuiDaoProject";
                break;
            default:
                break;
        }
        return dirname;
    }
    /// <summary>
    /// 获得wk名称
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    private static string GetWkNameByType ( itemType type )
    {
    
    
        string wkName = string.Empty;
        switch (type)
        {
    
    
            case itemType.安装识图:
                wkName = "AZST";
                break;
            case itemType.测量:
                wkName = "CL";
                break;
            case itemType.钢结构:
                wkName = "GJG";
                break;
            case itemType.工程识图:
                wkName = "GZst";
                break;
            case itemType.工艺:
                wkName = "GRgy";
                break;
            case itemType.构造:
                wkName = "GRgz";
                break;
            case itemType.计量计价:
                wkName = "GRjljj";
                break;
            case itemType.精装修:
                wkName = "ZSzx";
                break;
            case itemType.工程力学:
                wkName = "GCLX";
                break;
            case itemType.平法:
                wkName = "";
                break;
            case itemType.造价识图:
                wkName = "GZst";
                break;
            case itemType.装配式:
                wkName = "ZPS";
                break;
            case itemType.建筑电气施工:
                wkName = "GRaz";
                break;
            case itemType.桥梁工程:
                wkName = "QLGC";
                break;
            case itemType.道桥识图:
                wkName = "";
                break;
            case itemType.隧道工程:
                wkName = "SGGY+GZRZ+WYFJ";
                break;
            default:
                break;
        }
        return wkName;
    }

    #endregion

    #region 调用打包工具
    private static string FilePath = @"F:\workspace\PythonTest\PythonCallHardware\venv\Scripts\python.exe";
    // [MenuItem("PublishTools/制作版本号",false,2)]
    private static void CallBuildTool ()
    {
    
    
        string file = @"F:/workspace/PythonTest/PythonCallHardware/Scripts/CallBuildTools.py";
        ProcessStartInfo start = new ProcessStartInfo ();
        start.FileName = FilePath;
        start.Arguments = file + " " + currentItemType;
        start.UseShellExecute = false;
        //参数用空格分隔
        //start.Arguments = path + " " + type + " " + mode;
        start.RedirectStandardOutput = true;
        start.RedirectStandardInput = true;
        start.RedirectStandardError = true;
        start.CreateNoWindow = false;
        Process process = Process.Start (start);
    }
    #endregion
}

public class PythonCallBuild : EditorWindow
{
    
    
    #region 调用python自动化打包
    static PythonCallBuild window;
    private static itemType CurrentType = itemType.测量;
    private static bool ISWEIKE = false;
    private static bool ISHUDONG = false;
    [MenuItem ("PublishTools/调用Python自动化打包", false, 3)]
    private static void CallBuild ()
    {
    
    
        window = GetWindow<PythonCallBuild> ();
        window.autoRepaintOnSceneChange = false;
        window.maxSize = new Vector2 (430, 305);
        window.Show ();
    }


    //互动2 微课是1
    static string CurrentModeType = "1";
    private void OnGUI ()
    {
    
    
        EditorGUILayout.BeginHorizontal ();
        CurrentType = (itemType)EditorGUILayout.EnumPopup ("选择项目:", CurrentType, GUILayout.Width (300));
        EditorGUILayout.EndHorizontal ();
        GUILayout.Label ("------------------------------------------------------------------------------------------------------------------------------");
        EditorGUILayout.BeginHorizontal ();
        using (var posGroup = new EditorGUILayout.ToggleGroupScope ("类别(只能选一个)", true))
        {
    
    
            ISWEIKE = EditorGUILayout.ToggleLeft ("微课", ISWEIKE);
            ISHUDONG = EditorGUILayout.ToggleLeft ("互动", ISHUDONG);

        }

        EditorGUILayout.EndHorizontal ();
        GUILayout.Space (10);
        GUILayout.BeginHorizontal ();
        GUILayout.Label ("------------------------------------------------------------------------------------------------------------------------------");

        GUILayout.Label ("当前选择项目:");
        GUILayout.Label (CurrentType.ToString ());
        GUILayout.EndVertical ();
        if (GUILayout.Button ("开始调用", GUILayout.Width (100), GUILayout.Height (40)))
        {
    
    
            if (ISWEIKE)
                CurrentModeType = "1";
            else if (ISHUDONG)
                CurrentModeType = "2";
            else
                return;
            CallPythonExe (((int)CurrentType).ToString (), CurrentModeType);
        }
    }
    private static void CallPythonExe ( string type, string mode )
    {
    
    

        ProcessStartInfo StartInfo = new ProcessStartInfo ();
        //python脚本的路径
        string path = @"F:/workspace/PythonTest/PythonCallHardware/Scripts/CallHarware.py";
        //(注意:用的话需要换成自己的)没有配环境变量的话,可以像我这样写python.exe的绝对路径
        //(用的话需要换成自己的)。如果配了,直接写"python.exe"即可
        StartInfo.FileName = @"F:\workspace\PythonTest\PythonCallHardware\venv\Scripts\python.exe";
        //p.StartInfo.FileName = @"C:\Program Files\Python35\python.exe";

        // sArguments为python脚本的路径   python值的传递路线strArr[]->teps->sigstr->sArguments 
        //传递参数时 每个参数需要用空格 隔开
        //在python中用sys.argv[ ]使用该参数
        StartInfo.UseShellExecute = false;
        StartInfo.Arguments = path + " " + type + " " + mode;
        StartInfo.RedirectStandardOutput = true;
        StartInfo.RedirectStandardInput = true;
        StartInfo.RedirectStandardError = true;
        StartInfo.CreateNoWindow = false;
        Process process = Process.Start (StartInfo);
        //process.OutputDataReceived += new DataReceivedEventHandler (Out_RecvData);
        StreamReader reader = process.StandardOutput;
        string result = "";
        while (result != null)
        {
    
    
            result = reader.ReadLine ();
            if (string.IsNullOrEmpty (result))
                break;
            UnityEngine.Debug.Log (result.ToString ());
        }
    }

    //class ProjectType(enum.Enum):
    //'''
    //项目类别
    //'''
    //CeLiang = 1
    //GongYi = 2
    //GCLX = 3
    //AnZhuangShiTu = 4
    //ZhuangPeiShi = 5
    //PingFa = 6
    //JingZhuangXiu = 7
    //GouZhao = 8
    //AnQuanWenMingGongDi = 9
    //JiLiangJiJia = 10
    //DaoLuGongCheng = 11
    //QiangLiangGongCheng = 12
    //ShouGongSuanLiang = 13
    //GangJieGou=14,
    //# 建筑电气施工
    //JianZhuDianQiShiGong=15,
    //DaqQiaoShiTu=16,
    //SuiDaoGongCheng=17,
    //# 不确定
    //GongChengShiTu=18,
    #endregion

    static void Out_RecvData ( object sender, DataReceivedEventArgs e )
    {
    
    
        if (!string.IsNullOrEmpty (e.Data))
        {
    
    
            UnityEngine.Debug.Log (e.Data);
        }
    }



}
/// <summary>
/// 工具类
/// </summary>
public class PathTool
{
    
    
    public static string CombinePath ( params string[] str )
    {
    
    
        string TmpPath = str[0];
        for (int i = 0; i < str.Length; i++)
        {
    
    
            if (i != 0)
                TmpPath = Path.Combine (TmpPath, str[i]);
        }
        TmpPath = TmpPath.Replace ("\\", "/");
        return TmpPath;
    }

    public static void CreatDirectory ( string path )
    {
    
    
        if (!string.IsNullOrEmpty (path))
        {
    
    
            bool isExist = Directory.Exists (path);
            if (isExist == false)
                Directory.CreateDirectory (path);
        }
    }
}


这是python脚本

# coding=utf-8
import os
import sys
from pywinauto.application import Application

import time
import enum
# 解决报错
import warnings
warnings.simplefilter('ignore', category=UserWarning)
class AutoBuild(object):

	def __init__(self):
		self.sufFileName = ""
		self.open_SufPath = ""
		# suf 盘符位置
		self.Drive_path = "D:\工作安装包\网页版本suf"
		# 资源位置
		self.ProjectFile = 'D:\工作安装包\网页版本打包项'
		# self.CurrentType=sys.argv[1]
		self.CurrentType = 1
		self.CurrentModel = 1

	def run(self):
		self.CurrentType = int(sys.argv[1])
		self.CurrentModel = int(sys.argv[2])
		self.ProjecttypeEnum = ProjectType(self.CurrentType)
		self.modelType = ModelType(self.CurrentModel)
		print(self.ProjecttypeEnum)
		print(self.modelType)
		# 获取suf路径
		print('*' * 10)
		self.open_SufPath = self.GetSufByProject(self.ProjecttypeEnum)
		print(self.open_SufPath)
		# 打开sufdesign

		app = Application(backend='uia').start(r"F:\work\SetupFactory\SUFDesign.exe", timeout=10)
		# 把进程和当前获得句柄联系起来
		app = Application().connect(path=r"F:\work\SetupFactory\SUFDesign.exe", timeout=10)
		time.sleep(1)
		# 获取 当前的窗 通过标题
		dlg_new = app.window(title="Start a New Project")
		dlg_new.wait("ready", timeout=5)
		# dlg_spec.menu_select("File->Open")
		# 标识一下
		dlg_new.draw_outline()

		btn_cancle = dlg_new[r'Cancle']
		btn_cancle.click()
		dlg_Open = app.window(title=r"Untitled - Setup Factory")
		dlg_Open.wait("exists enabled visible ready", timeout=5)
		dlg_Open.draw_outline()

		# dlg_Open.print_control_identifiers()
		# 使用快捷键 打开suf
		dlg_Open.type_keys("^O")
		dlg_ReOpen = app.window(title="Open")
		# 找到要打开路劲的文本框
		edit = dlg_ReOpen["Edit"]
		edit.set_text(self.open_SufPath)
		time.sleep(1)
		# 快捷键 打开
		# print(dlg_ReOpen.print_control_identifiers())
		# dlg_ReOpen.type_keys("%o")
		btn_open = dlg_ReOpen.child_window(title="打开(&O)", class_name="Button")
		btn_open.click()
		dlg_Pro = app.window(title=self.sufFileName + " - Setup Factory")
		dlg_Pro.wait("ready", timeout=10)
		time.sleep(2)
		# dlg_Pro=app.window(title="Project")
		dlg_Pro.draw_outline()
		dlg_Pro.type_keys("{INS} ")
		dlg_addFile = app.window(title="Add Files to Project")
		time.sleep(2)
		dlg_addFile.draw_outline()
		dlg_addFile.child_window(title="All files in this folder and all sub folders", class_name="Button").click()
		# print(dlg_addFile.print_control_identifiers())
		# TODO  地址 获取元件 设置值  获取不到 卡在这了
		dlg_addFile.child_window(title="All Files in Tree", class_name="Edit").set_text(
			self.GetProjectSource(self.ProjecttypeEnum) + "\All file in tree")
		# dlg_addFile.child_window(title="地址",class_name="Edit").set_text(self.GetProjectSource(self.ProjecttypeEnum)+"All file in tree")
		time.sleep(2)
		btn_open = dlg_addFile.child_window(title="打开(&O)", class_name="Button")
		btn_open.click()
		time.sleep(2)
		dlg_Pro = app.window(title=self.sufFileName + " - Setup Factory")
		dlg_Pro.wait("exists enabled visible ready", timeout=10)
		# ctrl ^   enter {ENTER}或者~ ALT %
		time.sleep(1)
		dlg_Pro.get_active()
		dlg_Pro.get_focus()
		dlg_Pro.type_keys("^a")
		dlg_Pro.type_keys("^{ENTER}")
		dlg_Mul = app.window(title="Multiple File Properties", class_name="#32770")
		# dlg_Mul.wait("ready",timeout=10)

		# dlg_Mul.child_window(title="Overwrite if existing file is older", class_name="ComboBox").click()
		# print(dlg_Mul.print_control_identifiers())
		# 选择组合框中的
		dlg_Mul.ComboBoxWrapper.select("Always overwrite existing file")
		time.sleep(1)
		dlg_Mul.child_window(title="确定", class_name="Button").click()
		dlg_Pro = app.window(title=self.sufFileName + " - Setup Factory")
		dlg_Pro.draw_outline()
		time.sleep(1)
		dlg_Pro.type_keys("{F7}")
		dlg_pub = app.window(title="Publish Wizard - Select Distribution Media", class_name="#32770")
		# print(dlg_pub.print_control_identifiers())
		dlg_pub.child_window(title="&Next >", class_name='Button').click()
		dlg_pub = app.window(title="Publish Wizard - Select Output Location", class_name="#32770")
		dlg_pub.child_window(title="&Next >", class_name='Button').click()

	def GetProjectSource(self, project):
		'''
		获取要打包的资源路径
		:param project:
		:return:
		'''
		ProjectSource = self.GetProject(self.ProjectFile, project)
		if self.modelType == ModelType.WeiKe:
			ProjectSource = os.path.join(ProjectSource, self.GetProject("", project) + "微课")
		if self.modelType == ModelType.HuDong:
			ProjectSource = os.path.join(ProjectSource, self.GetProject("", project) + "互动")
		print("准备打包的资源路径%s" % ProjectSource)
		return ProjectSource

	def GetSufByProject(self, project):
		"""
		获取项目的最终suf路径
		:param project:
		:return:
		"""
		path = os.path.join(self.GetProject(self.Drive_path, project), self.GetProjectSufName(project))
		print("suf的最终路径%s" % path)
		return path

	def GetProject(self, Drive_path, project):
		'''
		获取盘符和项目路径
		:param project:
		:return:
		'''
		if project == ProjectType.CeLiang:
			return os.path.join(Drive_path, "测量")
		if project == ProjectType.GongYi:
			return os.path.join(Drive_path, "工艺")
		if project == ProjectType.GCLX:
			return os.path.join(Drive_path, "工程力学")
		if project == ProjectType.AnZhuangShiTu:
			return os.path.join(Drive_path, "安装识图")
		if project == ProjectType.ZhuangPeiShi:
			return os.path.join(Drive_path, "装配式")
		if project == ProjectType.PingFa:
			return os.path.join(Drive_path, "平法")
		if project == ProjectType.JingZhuangXiu:
			return os.path.join(Drive_path, "精装修")
		if project == ProjectType.GouZhao:
			return os.path.join(Drive_path, "构造")
		if project == ProjectType.AnQuanWenMingGongDi:
			return os.path.join(Drive_path, "安全文明工地")
		if project == ProjectType.JiLiangJiJia:
			return os.path.join(Drive_path, "计量计价")
		if project == ProjectType.DaoLuGongCheng:
			return os.path.join(Drive_path, "道路工程")
		if project == ProjectType.QiangLiangGongCheng:
			return os.path.join(Drive_path, "桥梁工程")
		if project == ProjectType.ShouGongSuanLiang:
			return os.path.join(Drive_path, "手工算量")
		if project == ProjectType.GangJieGou:
			return os.path.join(Drive_path, "钢结构")
		if project == ProjectType.JianZhuDianQiShiGong:
			return os.path.join(Drive_path, "建筑电气施工")
		if project == ProjectType.SuiDaoGongCheng:
			return os.path.join(Drive_path, "隧道工程")
		if project == ProjectType.DaqQiaoShiTu:
			return os.path.join(Drive_path, "道桥识图")
		if project == ProjectType.GongChengShiTu:
			return os.path.join(Drive_path, "工程识图")

	def GetProjectSufName(self, project):
		'''
		获取suf名称
		:param project:
		:return:
		'''
		filename = ""
		if self.modelType == ModelType.HuDong:

			if project == ProjectType.CeLiang:
				filename = "3.5hd资源.suf"
			if project == ProjectType.GongYi:
				filename = "工艺互动加速包.suf"
			if project == ProjectType.GCLX:
				filename = "工程力学互动加速包.suf"
			if project == ProjectType.AnZhuangShiTu:
				filename = "安装识图互动加速包.suf"
			if project == ProjectType.ZhuangPeiShi:
				filename = "装配式互动/Untitled.suf"
			if project == ProjectType.PingFa:
				filename = "平法互动.suf"
			if project == ProjectType.JingZhuangXiu:
				filename = "精装修互动/精装修互动.suf"
			if project == ProjectType.GouZhao:
				filename = "构造互动.suf"
			if project == ProjectType.AnQuanWenMingGongDi:
				filename = "安全文明工地.suf"
			if project == ProjectType.JiLiangJiJia:
				filename = "计量计价互动加速包.suf"
			if project == ProjectType.DaoLuGongCheng:
				filename = ""
			if project == ProjectType.QiangLiangGongCheng:
				filename = ""
			if project == ProjectType.ShouGongSuanLiang:
				filename = ""
			if project == ProjectType.GangJieGou:
				filename = "3.5WK资源.suf"
			if project == ProjectType.JianZhuDianQiShiGong:
				filename = ""
			if project == ProjectType.DaqQiaoShiTu:
				filename = ""
			if project == ProjectType.SuiDaoGongCheng:
				filename = ""
			if project == ProjectType.GongChengShiTu:
				filename = ""
		if self.modelType == ModelType.WeiKe:
			if project == project.CeLiang:
				filename = "3.5资源.suf"
			if project == ProjectType.GongYi:
				filename = "工艺微课加速包.suf"
			if project == ProjectType.GCLX:
				filename = "工程力学微课加速包.suf"
			if project == ProjectType.AnZhuangShiTu:
				filename = "安装识图微课加速包.suf"
			if project == ProjectType.ZhuangPeiShi:
				filename = "装配式微课/Untitled.suf"
			if project == ProjectType.PingFa:
				filename = ""
			if project == ProjectType.JingZhuangXiu:
				filename = "精装修微课/精装修微课.suf"
			if project == ProjectType.GouZhao:
				filename = "构造微课.suf"
			if project == ProjectType.AnQuanWenMingGongDi:
				filename = ""
			if project == ProjectType.JiLiangJiJia:
				filename = "计量计价微课加速包.suf"
			if project == ProjectType.DaoLuGongCheng:
				filename = ""
			if project == ProjectType.QiangLiangGongCheng:
				filename = ""
			if project == ProjectType.ShouGongSuanLiang:
				filename = ""
			if project == ProjectType.GangJieGou:
				filename = "3.5hd资源.suf"
			if project == ProjectType.JianZhuDianQiShiGong:
				filename = ""
			if project == ProjectType.DaqQiaoShiTu:
				filename = ""
			if project == ProjectType.SuiDaoGongCheng:
				filename = ""
			if project == ProjectType.GongChengShiTu:
				filename = ""
		self.sufFileName = filename
		return filename


class ProjectType(enum.Enum):
	'''
	项目类别
	'''
	CeLiang = 1
	GongYi = 2
	GCLX = 3
	AnZhuangShiTu = 4
	ZhuangPeiShi = 5
	PingFa = 6
	JingZhuangXiu = 7
	GouZhao = 8
	AnQuanWenMingGongDi = 9
	JiLiangJiJia = 10
	DaoLuGongCheng = 11
	QiangLiangGongCheng = 12
	ShouGongSuanLiang = 13
	GangJieGou = 14,
	# 建筑电气施工
	JianZhuDianQiShiGong = 15,
	DaqQiaoShiTu = 16,
	SuiDaoGongCheng = 17,
	# 不确定
	GongChengShiTu = 18,


class ModelType(enum.Enum):
	'''
	模式 互动还是微课
	'''
	WeiKe = 1
	HuDong = 2


if __name__ == '__main__':
	ab = AutoBuild()
	ab.run()

另一个python脚本

# coding=utf-8

import sys
import enum
import time
from pywinauto.application import Application
import winerror

# 解决不能运行自己做的exe的问题
import os
os.environ.update({
    
    "__COMPAT_LAYER":"RUnAsInvoker"})
# 解决报错 是32位程序需要 使用32位python.exe
import warnings
warnings.simplefilter('ignore', category=UserWarning)
class BuildVersion(object):


	def run(self):
		"""
		使用该方式用来自动化制作安装包
		:return:
		"""
		#exePath=r'L:\rgzsoft\PatchTool.exe'
		exePath = r'D:\WorkBuild\PatchTool\PatchTool.exe'
		# 选择的项目
		currentType= self.GetNameByInt(sys.argv[1])
		#currentType=self.GetNameByInt(3)
		try:
			app = Application(backend='win32').start(exePath,timeout=10)
			app=Application().connect(path=exePath,timeout=10)
			diolg = app.window(title="PatchTool")
			diolg.draw_outline()
			diolg.ComboBox.select(currentType)
			time.sleep(1)
			# diolg.child_window(title="发布版本", auto_id="release", control_type="System.Windows.Forms.Button").click()
		except BaseException as error :

			raise error

	def GetNameByInt(sefl,index):
		'''
		项目类别
		'''
		str_type=r"测量= 1," \
			r"工艺 = 2," \
			r"工程力学= 3," \
			r"安装识图 = 4," \
			r"装配式 = 5," \
			r"平法 = 6," \
			r"精装修 = 7," \
			r"构造 = 8," \
			r"安全文明工地 = 9," \
			r"计量计价 = 10," \
			r"道路工程 = 11," \
			r"桥梁工程 = 12," \
			r"手工算量 = 13," \
			r"钢结构 = 14," \
			r"建筑电气施工 = 15," \
			r"道桥识图 = 16,"\
			r"SuiDaoGongCheng = 17," \
			r"工程识图 = 18"
		index=str(index)
		pro_dic={
    
    i.split('=')[1].strip(): i.split('=')[0].strip() for i in str_type.split(',')}
		for k in pro_dic.keys():
			if k.strip() == index.strip():
				print(pro_dic[k])
				return pro_dic[k]


if __name__ == '__main__':
	buildVersion = BuildVersion()
	buildVersion.run()

如果有哪里写的不对 欢迎指出来。完了!

猜你喜欢

转载自blog.csdn.net/m_cainiaokuaifei/article/details/103768297
今日推荐