本文是一个教程,引导您完成为UiPath RPA平台创建和发布新组件的过程 。 这在不同情况下非常方便,例如对于与公司系统的简单集成或公司希望帮助在编程方面没有特别知识的员工创建自己的机器人流程的情况。 但是,在我看来,这种技术在需要将产品集成到机器人生态系统中的情况下效果特别好,允许用户单击几下即可配置内部流程的集成。 一个示例是Abbyy为其Abbyy Flexicapture Distributed产品编写的连接器。 另一个例子是UiPath本身,它因此实现了与其新的ML模块的连接,用于计算机视觉(程序包管理器中的计算机视觉),使用PDF的操作等。
现在在UiPath Go应用商店中! 已经如火如荼地开始出现与诸如Salesforce或ServiceNow之类的流行解决方案的连接器,并且很可能这种趋势只会越来越流行。
那么,您如何开始制定自己的行动?
注意:用英语来说,一个动作就是一个活动,如果您需要搜索一些东西,请记住这一点
如果您不想进行所有设置,则可以尝试本教程中的步骤中使用的示例代码。 它位于GitLab上 。 本文中的代码经过简化和简化, 可以在Yandex Disk上找到

开始工作之前,我们需要什么:
- Visual Studio( VS Community Edition的免费版本是完美的。在安装过程中,必须选择.NET Desktop Development或手动指定以下软件包:
- Nuget软件包管理器
- .NET Framework 4.6.1目标包(需要4.6)
- C#和Visual Basic(动作可以用任何.NET语言编写,但传统上使用C#或VB.NET)。 本教程将使用C#。
- Windows工作流程基础
- UiPath Studio(这里同样是免费的CE,您只需要填写UiPath Community Edition应用程序表单)。
注意:对于行动本身的发展,我们并不需要它,但是,我当然想看看我们会做什么。
- NuGet软件包管理器(与VS 2017+捆绑在一起或从Nuget.org下载)
开始创造
在VS中创建项目
- 创建一个
C# Class Library (.NET Framework)
项目。 请注意,该主题的变体(例如C#类库(.NET标准) )不适合我们。

- 我们为其选择一个有意义的名称(常用格式<Developer> .UiPath.Activities。 <Project Name> ),并指示我们要使用
.NET Framework 4.6.1
。
NuGet软件包ID应包含单词Activity。 由于我们想从VS中获取所有内容,因此最好立即正确命名项目,以便以后在NuGet中进行选择。

- 在创建的项目中,我们创建以下子文件夹(这是一个可选步骤,但是如果您想一次为用户提供多个动作并且文件数量开始累积,使用动作包会更加方便):
- 活动(这里将有一个动作代码)
- 设计器(这里将以操作窗口的形式显示)
- 资源(这里我们将存储图片,图标和其他必要的东西)
- 根据第一个操作的名称,将在VS中为我们创建的Class1.cs文件重命名,然后将其移至“活动”文件夹。

简单的动作创建和发布
至此,我们有一个空项目编译为.dll
。 现在让我们继续创建动作本身。
注意:由于UiPath支持多种语言,因此最终我们需要添加本地化,并略微更改我们现在正在做的事情,但让我们从必要和充分的内容开始。
- 我们需要两个
using
:
using System; using System.Activities;
- 我们从
CodeActivity
我们的类:
public class TutorialForHabr: CodeActivity {}
- 我们设置输入和输出参数:
public class TutorialForHabr: CodeActivity { public InArgument<Int32> Row { get; set; } public InArgument<Int32> Column { get; set; } public OutArgument<String> Cell { get; set; } }
注意:操作参数是输入InArgument< >
,输出OutArgument< >
并混合的,从而允许接收和接收参数InOutArgument< >
- 还有
Execute
方法,这是我们必须明确设置的唯一方法:
protected override void Execute(CodeActivityContext context) { string colstr = "";
在此阶段,我们有一个针对UiPath的工作措施,它实现了简单但必要的功能。
我们将发布它,然后继续进行第二部分,并讨论一点“装饰”。
通过NuGet发布
您可以通过NuGet软件包管理器GUI或通过调用nuget.exe pack
的命令行来创建NuGet软件包。 pack
命令接受两个主要参数作为输入:项目文件.csproj的名称或包含包的元信息的文件.nuspec的名称。 第一个选项不允许我们在没有对.json文件进行额外手动修改的情况下设置一些对我们很重要的软件包属性,例如标签,许可证或存储库的URL,此外它不允许我们为在软件包管理器中可见的项目设置图标。
在第二个变体中,我们复制了程序包的某些属性,不过,这些属性可以从Visual Studio中自动获取。
因此,我们将沿着路径1.5进行操作,并在项目根目录中创建一个扩展名为.nuspec的文件(名称无关紧要,只有一个这样的文件),它将包含无法从.csproj获得的信息并将这两个数据源组合在一起。
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>$id$</id> <title>$title$</title> <version>$version$</version> <authors>$author$</authors> <owners>$author$</owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <licenseUrl>https://choosealicense.com/licenses/mit/</licenseUrl> <projectUrl>https://gitlab.com/ilyak/ilyak.uipath.activities</projectUrl> <iconUrl>http://www.uipath.com/hubfs/Logos/uipath-nuget-logo.png</iconUrl> <description>$description$</description> <copyright>$copyright$</copyright> <tags>UiPath,Activity,Excel</tags> </metadata> <files> <file src="bin\Debug\IlyaK.UiPath.Activities.TutorialForHabr.dll" target="lib\net461\IlyaK.UiPath.Activities.TutorialForHabr.dll" /> </files> </package>
如您所见,.nuspec的结构非常明显。 如果您不愿意使用XML,则可以通过可视编辑器NuGet Package Manager创建它,并将其保存在项目文件夹中以备将来使用。 诸如$copyright
类的变量是从.dll文件中包含的信息中获取的,即 从Visual Studio。
现在,我们要使用.nuspec,以便在每次构建时都得到一个新包。 为此,我们转到“属性”,然后转到“生成事件”选项卡。
在构建后事件命令行中写魔术字
IF EXIST "$(ProjectDir)$(OutDir)*.nupkg" del "$(ProjectDir)$(OutDir)*.nupkg" nuget.exe pack "$(ProjectPath)" IF EXIST "$(ProjectDir)$(OutDir)*.nupkg" xcopy /Y "$(ProjectDir)$(OutDir)*.nupkg" "C:\Program Files (x86)\UiPath\Studio\Packages\"
译成俄文的意思是
- 在创建版本的文件夹中删除旧软件包
- 使用.csproj和.nuspec文件创建一个新包
- 将其放在文件夹
C:\Program Files (x86)\UiPath\Studio\Packages\
这个文件夹是什么? 这是UiPath Studio使用的本地软件包存储库。 一旦出现新软件包,它将通过软件包管理器自动提供,并且可以将其添加到机械化过程中。

注意可以通过UiPath Studio设置更改本地存储库的路径,以便在权限存在问题时方便地将文件复制到本地存储库。

恭喜,仅此而已!
注意:请注意,smart Studio本身使用点作为嵌套级别为操作创建了一个类别,并在操作名称的大写字母前放置了空格。
本文的下一部分将涉及“简洁”:关于如何为操作创建可视界面,分配图标并本地化文本。
认真的
属性
为了使我们的行动奏效,第一部分已经足够。 但我希望我们能够选择类别,显示提示等。
为此,我们需要属性。 有一些属性适合于操作本身及其参数:
[Category (" , ")] [DisplayName (" ")] [Description (" ")]
还有那些只是必需的参数:
[RequiredArgument]
本地化
不幸的是,属性有一个微妙之处:在俄语版本的UiPath Studio中,操作类别的名称和其属性的类别也被翻译了。 因此,如果我们为输入参数设置[Category("Input")]
属性,它将在英语版本中正确显示,但是在俄语版本中,它将属于其自己单独的Input类别,而不是标准Input类别。 操作也是如此;在俄语版本中, App Integration成为Application Integration 。
因此,我们需要将文本常量移至与语言相关的资源,然后从那里使用它们。
为此,请创建一个魔术文件Localization.cs,其中包含用于对属性进行本地化的函数
本地化 using IlyaK.UiPath.Activities.TutorialForHabr.Properties; using System; using System.ComponentModel; namespace IlyaK.UiPath.Activities.TutorialForHabr { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Delegate | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter)] public class LocalizedCategoryAttribute : CategoryAttribute { public LocalizedCategoryAttribute(string category) : base(category) { } protected override string GetLocalizedString(string value) { return Resources.ResourceManager.GetString(value) ?? base.GetLocalizedString(value); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] public class LocalizedDisplayNameAttribute : DisplayNameAttribute { public LocalizedDisplayNameAttribute(string displayName) : base(displayName) { } public override string DisplayName { get { return Resources.ResourceManager.GetString(DisplayNameValue) ?? base.DisplayName; } } } public class LocalizedDescriptionAttribute : DescriptionAttribute { public LocalizedDescriptionAttribute(string displayName) : base(displayName) { } public override string Description { get { return Resources.ResourceManager.GetString(DescriptionValue) ?? base.Description; } } } }
他将允许我们替换设计
[Category("Name")
在
[LocalizedCategory(nameof(Resources.CategoryName))]
为了使该机制起作用,我们必须:
- 在
Resources
文件夹( 添加->新项目->资源文件 )中,为要翻译成的语言创建资源文件,在本例中为Resources.resx
和Resources.ru.resx
。 确保资源的“访问修饰符”值位于“ 公共”中 。 - 添加到集体诉讼文件
using IlyaK.UiPath.Activities.TutorialForHabr.Properties;
并使用适当的属性设置类和所有参数
[LocalizedCategory(nameof(Resources.AppIntegrationExcel))] [LocalizedDisplayName(nameof(Resources.TutorialForHabrName))] [LocalizedDescription(nameof(Resources.TutorialForHabrDescription))] public class TutorialForHabr : CodeActivity { [LocalizedCategory(nameof(Resources.Input))] [LocalizedDisplayName(nameof(Resources.RowName))] [LocalizedDescription(nameof(Resources.RowDescription))] public InArgument<Int32> Row { get; set; } [LocalizedCategory(nameof(Resources.Input))] [LocalizedDisplayName(nameof(Resources.ColumnName))] [LocalizedDescription(nameof(Resources.ColumnDescription))] public InArgument<Int32> Column { get; set; } [LocalizedCategory(nameof(Resources.Output))] [LocalizedDisplayName(nameof(Resources.CellName))] [LocalizedDescription(nameof(Resources.CellDescription))] }
- 为了使具有俄语资源的库属于NuGet包,您需要在.nuspec文件中的文件组中添加另一行
<files> <file src="bin\Debug\IlyaK.UiPath.Activities.TutorialForHabr.dll" target="lib\net461\IlyaK.UiPath.Activities.TutorialForHabr.dll" /> <file src="bin\Debug\ru\**" target="lib\net461\ru\" /> </files>
设计师
为了使我们的操作在过程中看起来漂亮,并允许用户输入数据而无需爬网到属性,我们需要添加一个UI。 这是通过XAML格式的文件完成的,该文件可以在Visual Studio的帮助下通过特殊的界面进行编辑,但是仍必须手动修复部分。 我将为您提供一个入门的模板,然后值得阅读Microsoft的文档 。
- 将操作的图标放在“
Resources
文件夹中。 在“构建操作”的属性中设置为“ 资源 (不是嵌入式资源 )” - 在
Designer
文件夹中创建一个新的Activity Designer( Add-> New Item-> Activity Designer ),并将其命名为TutorialForHabr
Habr.xaml教程 <sap:ActivityDesigner x:Class="IlyaK.UiPath.Activities.TutorialForHabr.Designer.TutorialForHabrDesigner" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:resource="clr-namespace:IlyaK.UiPath.Activities.TutorialForHabr.Properties" xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation" xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation" xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"> <sap:ActivityDesigner.Resources> <ResourceDictionary> <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" /> </ResourceDictionary> </sap:ActivityDesigner.Resources> <DockPanel Width="200"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="70"></ColumnDefinition> <ColumnDefinition Width="130"></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Text="{x:Static resource:Resources.RowName}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,0"></TextBlock> <sapv:ExpressionTextBox Grid.Row="0" Grid.Column="1" OwnerActivity="{Binding Path=ModelItem}" ExpressionType="{x:Type s:Int32}" HintText="{x:Static resource:Resources.RowDescription}" Expression="{Binding Path=ModelItem.Row, Converter={StaticResource ArgumentToExpressionConverter},ConverterParameter=In, Mode=TwoWay}"/> <TextBlock Grid.Row="1" Grid.Column="0" Text="{x:Static resource:Resources.ColumnName}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,0"></TextBlock> <sapv:ExpressionTextBox Grid.Row="1" Grid.Column="1" OwnerActivity="{Binding Path=ModelItem}" ExpressionType="{x:Type s:Int32}" HintText="{x:Static resource:Resources.ColumnDescription}" Expression="{Binding Path=ModelItem.Column, Converter={StaticResource ArgumentToExpressionConverter},ConverterParameter=In, Mode=TwoWay}"/> </Grid> </DockPanel> <sap:ActivityDesigner.Icon> <DrawingBrush> <DrawingBrush.Drawing> <ImageDrawing> <ImageDrawing.Rect> <Rect Location="0,0" Size="32,32" ></Rect> </ImageDrawing.Rect> <ImageDrawing.ImageSource> <BitmapImage UriSource="/IlyaK.UiPath.Activities.TutorialForHabr;component/Resources/Tutorial_32x32.png"></BitmapImage> </ImageDrawing.ImageSource> </ImageDrawing> </DrawingBrush.Drawing> </DrawingBrush> </sap:ActivityDesigner.Icon> </sap:ActivityDesigner>
这是我们设置本地化标签的方式:
<TextBlock Grid.Row="0" Grid.Column="0" Text="{x:Static resource:Resources.RowName}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,0" />
,这是输入字段。 ExpressionType
设置字段类型HintText
提示(灰色文本), Expression
将字段值与我们的操作相关联
<sapv:ExpressionTextBox OwnerActivity="{Binding Path=ModelItem}" Grid.Row="0" Grid.Column="1" ExpressionType="{x:Type s:Int32}" HintText="{x:Static resource:Resources.RowDescription}" Expression="{Binding Path=ModelItem.Row, Converter={StaticResource ArgumentToExpressionConverter},ConverterParameter=In, Mode=TwoWay}" />
注意请注意文件末尾的BitmapImage标签。 因此,我们为图标设置了带有资源文件链接的图片。 这是一个非常脆弱的功能,有时您必须对其进行修改。
根据结果,结果应该是这样的:

- 在“活动”文件夹中创建DesignerMetata类
DesignerMetata.cs using System.Activities.Presentation.Metadata; using System.ComponentModel; namespace IlyaK.UiPath.Activities.TutorialForHabr.Design { public class DesignerMetadata : IRegisterMetadata { public void Register() { AttributeTableBuilder attributeTableBuilder = new AttributeTableBuilder(); attributeTableBuilder.AddCustomAttributes(typeof(TutorialForHabr), new DesignerAttribute(typeof(Designer.TutorialForHabrDesigner))); MetadataStore.AddAttributeTable(attributeTableBuilder.CreateTable()); } } }
这是我们操作的最终视图,带有图标和输入字段:

结论
我希望我能够证明为UiPath创建甚至完全框架的动作不会太久。 我真的希望本文对您有所帮助,并为为UiPath编写新的精彩活动提供一个良好的开端。 而且,当您创建它时-不要忘记将其发布在UiPath Go上!
附加材料