一、背景

之前写过的几个WPF小工具,每次发布都需要给它打安装包和升级包,涉及到一些系列繁琐的手工操作,有了Power Automate Desktop,于是便寻思着能不能做成一个自动化的流来使用。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

二、创建流任务

创建名为创建WPF程序安装包及升级包的流任务。

三、添加主流程

因为整个步骤比较长,为了更好的设计整个流,我们将这次流拆成几个子流程,然后通过主流程串起来。

3.1 设置WPF项目目录位置SettingProjectDir

1. 显示选择文件夹对话框,弹窗交互选择当前WPF项目所在的文件夹,我们用名为CurrentProjectDir变量来存储它,如果是常用位置,我们还可以设置默认值。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

3.2 设置WPF项目存档位置SettingArchiveDir

1. 显示选择文件夹对话框,弹窗交互选择安装包和升级包的存档位置,我们用名为CurrentArchiveDir变量来存储它,如果是常用位置,我们还可以设置默认值。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

3.3 设置变量,设置WPF项目起始子项目名称ProjectStartDir

1. 设置变量,变量名ProjectStartDir,用来存储WPF项目的起始子项目名称,方便我们后续找到正确的起始入口。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

大家都知道,一般来说我们在一个解决方案中会构建多个子项目,所以我们这里需要知道在CurrentProjectDir中入口子项目是哪个,也就是包括App.xaml的那个项目。

3.4 获取当前程序版本号GetAppVersion

0. 概览

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

1. 设置变量,变量名StartAssemblyFilePath,拼接出ProjectStartDirAssemblyInfo.cs文件位置。

%CurrentProjectDir%\%ProjectStartDir%\Properties\AssemblyInfo.cs

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

这个信息中,存储了程序版本号等基础信息。

2. 从文件读取文本,从StartAssemblyFilePath中读取文本到变量StartAssemblyContents中。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

3. 分析文本,从StartAssemblyContents中正则匹配出版本号信息,将结果存储到MatchAssemblyContents变量。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

"[0-9.]+"

但是遗憾的是,这里得到的结果是带了双引号的数据,比如: "1.0.0.0"

4. 拆分文本,从MatchAssemblyContents中我们通过拆分文本来提取最终我们要的版本号,通过自定义分隔符的模式,用分隔符"来进行分割,分割结果放在变量SplitAssemblyContents中。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

5. 设置变量,从SplitAssemblyContents结果中,提取第二个位置的数据,就是我们要的版本号,将版本号存在变量CurrentAppVersion中。

%SplitAssemblyContents[1]%

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

这样我们就可以得到我们要的最终数据1.0.0.0

3.5 获取当前环境模式GetEnvMode

0. 概览

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

1. 设置变量,变量名AppSettingsFilePath,拼接出ProjectStartDirAppSettings.json文件位置。

%CurrentProjectDir%\%ProjectStartDir%\appsettings.json

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

这个信息中,存储了程序本地应用配置信息。

2. 从文件读取文本,从AppSettingsFilePath中读取文本到变量AppSettingsContents中。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

这里留意AppSettingsContents的内容通常是JSON格式的。

{
  "ThirdHostConfig": {
    "HostAddress": "http://gateway.xxxxxxx.com",
    "CallModel": "GateWay"
  }
}

3. 将JSON转换为自定义对象,将AppSettingsContents内容以JSON对象的形式提取出来,存储到变量AppSettingsJsonObj

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

4. 设置变量,从AppSettingsJsonObj中提取网关地址,存储为变量CurrentGatewayUrl

%AppSettingsJsonObj.ThirdHostConfig.HostAddress%

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

JSON对象的数据,在Power Automate中可以直接用.来逐层获取值,非常方便。

5. 设置变量,变量名为CurrentEnvMode来存储,当前环境模式。

设置一个初始值为UnKnown

UnKnown

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

6. Switch-Case,根据CurrentGatewayUrl的特征,来识别对应的CurrentEnvMode值。

以其中一个Case为例,我们选择运算符为包含,把特征值写在要比较的值中,并且可以设置忽略大小写

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

最终,通过多个Case的组合我们得到一个完整的提取CurrentEnvMode值的流程。

运算符 要比较的值 结果值
包含 xxxx-dev DevC1
包含 gwkbs DevC1
包含 gxxdev Dev
包含 gwdev Dev
包含 gxxfat Fat
包含 gwfat Fat
包含 gxxuat Uat
包含 gwfat Uat
包含 gatewayxx Pro

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

3.5 创建WPF安装包CreatePackage

0. 概览

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

1. 设置变量,变量名VisualStudioEnvDir,设定当前系统安装的Visual Studio版本对应的IDE目录位置

C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\Common7\IDE

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

2. 设置变量,变量名InstallerProjectPath, 设定CurrentProjectDirVisual Studio Installer Project的相对位置。

Setup1\Setup1.vdproj

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

3. 运行PowerShell脚本,来执行调用devenv.com命令,进行对Visual Studio Installer Project编译,得到安装包,这一步我们命名为BuildInstallProject

cd '%VisualStudioEnvDir%'
.\devenv.com '%CurrentProjectDir%\%InstallerProjectPath%' /rebuild "Release|Any CPU"

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

  • 我们先切换到VisualStudioEnvDir这个目录,因为我们需要到当前系统安装的Visual Studio版本对应的IDE目录,去调用devenv.exe;
  • 这里使用.\devenv.com,而不是.\devenv.exe;
  • 随后跟的是指定的.vdproj文件的完整路径,也就是说指定是对这个Visual Studio Installer Project进行处理;
  • /rebuilddevenv的一个参数,代表先清理后编译生成指定的项目或者解决方案,如果不需要清理,使用/build命令也是可以的;
  • "Release|Any CPU"代表以Release模式进行生成,并且针对的设备平台是Any CPU;

如果顺利的话,最终根据这个命令可以得到.msi的安装包。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

上述命令,建议先在终端中验证一下,单独在终端中执行效果如下图:

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

如果遇到下面这个错误,继续看下面的解决办法。

ERROR: An error occurred while validating.  HRESULT = '8000000A'

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

官方给出了一个快捷的解决办法,只要是Visual Studio 2017+,都可以使用这个方法。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

找到当前系统安装的Visual Studio版本对应的DisableOutOfProcBuild目录。

C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\Common7\IDE\CommonExtensions\Microsoft\VSI\DisableOutOfProcBuild

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

在地址栏,输入cmd,以快速进入这个目录的当前终端上下文,然后执行如下命令即可。

DisableOutOfProcBuild.exe

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

这个执行之后,实际上是它为我们创建或者修改了已存在的一个注册表项,以便解决前面的那个报错。

4. 设置变量,变量名InstallerProductName, 设定安装包产品名称。

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

5. 设置变量,变量名InstallerPackagePath, 提取最终的.msi安装包路径。

%CurrentProjectDir%\Setup1\Release\%InstallerProductName%.msi

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

6. 设置变量,变量名InstallerVersionName,拼接出按版本号命名的文件名。

%CurrentEnvMode%-%InstallerProductName%-v%CurrentAppVersion%

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

最终得到的是比如是:Dev-xxxxx-v1.0.0.0

7. 重命名文件,将InstallerPackagePath文件重命名为InstallerVersionName,得到按版本号命名的新安装包,这个动作我们叫RenamePackageFile

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

8. 设置变量,变量名InstallerPackageFilePath, 拼接出按版本号命名的新文件名。

%CurrentProjectDir%\Setup1\Release\%InstallerVersionName%.msi

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

参考

Power Automate Desktop/RPA 爱好者交流群

流程自动化RPA,Power Automate Desktop系列 - 创建WPF程序安装包及升级包

相关文章: