SDK
最新
False
横幅背景图像
开发者指南
上次更新日期 2024年3月23日

构建工作流分析器规则

工作流分析器工具用于确保项目遵循最佳实践,以及可维护性、可读性、性能、可重用性、可靠性和安全性要求。

若要确保获取简洁、可靠的工作流以概述大型自动化项目,这些概念非常重要。

注意: 要构建自定义规则,您需要从 官方 订阅 源获取 UiPath.Activities.Api 包。SDK 包必须用作自定义项目中的开发依赖项。 阅读有关开发依赖项的更多信息。

观看下面的视频,获取有关如何构建自定义规则以及如何使用“ 使用 Activity Creator” 扩展程序创建自定义活动的分步说明。

在其现用形式中,工作流分析器已集成到 Studio 中,并包含验证和分析器功能。如果验证返回错误,则无法完成分析。

工作流分析器概念

要为您的项目构建自定义规则,请定义一系列概念,以便更好地理解工作流分析器的工作原理。

备注:

When building custom rules, target the .NET version depending on the version of Studio and the project compatibility:

  • Studio 2021.4 及更早版本:.NET Framework 4.6.1。
  • Studio 2021.10.6 and later: .NET Framework 4.6.1 for Windows-legacy projects, .NET 6 for Windows and cross-platform projects.

规则和计数器

工作流分析器利用特定标准来确保满足项目的可靠性要求。它会使用精心定义的规则和计数器执行这些检查。

规则代表必须满足的要求。您可设置规则,以按照规则定义对检查对象执行检查。

计数器表示为确定特定事件或条件的发生次数而进行的检查。

对于每个未满足的规则,“错误列表”面板中将会以 warning、error、info 或 verbose 形式列出相应消息。这些列表中还包含用于确保满足规则的更改建议。

注意:创建自定义规则和计数器时,建议您遵循 “关于工作流分析器”页面中详述的命名约定。

检查对象

工作流分析器能对预定义对象执行深度分析。对象代表要进行分析的作用域,亦即强制执行规则或计数器的区域。

创建规则

From the Official feed (https://pkgs.dev.azure.com/uipath/Public.Feeds/_packaging/UiPath-Official/nuget/v3/index.json), install the UiPath.Activities.Api package.

为了帮助您创建自定义规则,让我们来看看工作流分析器中当前预定义的规则,即“变量长度超出限制”。 此规则用于检查项目中定义的变量长度是否少于 20 个字符。 此规则的检查对象是活动。

此规则的工作原理如下:

// This static class is not mandatory. It just helps organizining the code.
internal static class VariableLengthRule
    {
  // This should be as unique as possible, and should follow the naming convention.
        private const string RuleId = "ST-NMG-008";
        internal static Rule<IActivityModel> Get()
        {
            var rule = new Rule<IActivityModel>("Variable Length Rule", RuleId, Inspect)
            {
                RecommendationMessage = Recommendation,
              /// Off and Verbose are not supported.
                ErrorLevel = System.Diagnostics.TraceLevel.Warning
            };
            return rule;
        }
  
              // This is the function that executes for each activity in all the files. Might impact performance.
        // The rule instance is the rule provided above which also contains the user-configured data.
                  private static InspectionResult Inspect(IActivityModel activityModel, Rule ruleInstance)
        {
            var messageList = new List<string>();
            foreach(var activityModelVariable in activityModel.Variables)
            {
                if (activityModelVariable.DisplayName.Length > 20)
                {
                    messageList.Add($"The variable {activityModelVariable.DisplayName} has a length longer than 20");
                }
            }
            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    ErrorLevel = ruleInstance.ErrorLevel,
                    HasErrors = true,
                    RecommendationMessage = ruleInstance.RecommendationMessage,
                  // When inspecting a model, a rule can generate more than one message.
                    Messages = messageList
                };
            }
            else
            {
                return new InspectionResult() { HasErrors = false };
            }
        }
    }// This static class is not mandatory. It just helps organizining the code.
internal static class VariableLengthRule
    {
  // This should be as unique as possible, and should follow the naming convention.
        private const string RuleId = "ST-NMG-008";
        internal static Rule<IActivityModel> Get()
        {
            var rule = new Rule<IActivityModel>("Variable Length Rule", RuleId, Inspect)
            {
                RecommendationMessage = Recommendation,
              /// Off and Verbose are not supported.
                ErrorLevel = System.Diagnostics.TraceLevel.Warning
            };
            return rule;
        }
  
              // This is the function that executes for each activity in all the files. Might impact performance.
        // The rule instance is the rule provided above which also contains the user-configured data.
                  private static InspectionResult Inspect(IActivityModel activityModel, Rule ruleInstance)
        {
            var messageList = new List<string>();
            foreach(var activityModelVariable in activityModel.Variables)
            {
                if (activityModelVariable.DisplayName.Length > 20)
                {
                    messageList.Add($"The variable {activityModelVariable.DisplayName} has a length longer than 20");
                }
            }
            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    ErrorLevel = ruleInstance.ErrorLevel,
                    HasErrors = true,
                    RecommendationMessage = ruleInstance.RecommendationMessage,
                  // When inspecting a model, a rule can generate more than one message.
                    Messages = messageList
                };
            }
            else
            {
                return new InspectionResult() { HasErrors = false };
            }
        }
    }
RuleId参数需要您提供规则名称。 在此示例中,“变量名称长度超出限制”规则的 ID 为ST-NMG-008 ,并遵循“规则命名惯例” 。 请注意,Studio 中默认可用的规则使用的命名约定不是强制性的。
RecommendationMessage 参数需要显示一条建议消息,以帮助用户解决完成分析后发现的任何不一致问题。消息内容应简洁明了,并要提供明确步骤。
ErrorLevel 参数声明当未满足条件时将采取的默认操作。在本示例中,此规则引发了警告。默认操作可以是 error、warning、info 或 verbose。

构建包含参数的规则

当我们要构建包含可自定义参数的规则时,情况略有不同。 其中一个规则是变量命名惯例。 其检查元素是活动,并具有默认的正则表达式,该表达式可以更改。

此规则的工作原理如下:

internal static class VariableNamingRule
    {
        private const string RuleId = "ST-NMG-001";
        private const string RegexKey = "Regex";
        private const string DefaultRegex = @"^([A-Z]|[a-z])+([0-9])*$";
        internal static Rule<IActivityModel> Get()
        {
            var rule = new Rule<IActivityModel>(Strings.ST_NMG_001_Name, RuleId, Inspect)
            {
                RecommendationMessage = Recommendation,
                ErrorLevel = System.Diagnostics.TraceLevel.Warning
            };
            rule.Parameters.Add(RegexKey, new Parameter()
        }
                                
       private static InspectionResult Inspect(IActivityModel activityModel, Rule ruleInstance) 
        {
          // This retrieves the parameter value from the rule instance as configured by the user, if not, the default value.
            var setRegexValue = ruleInstance.Parameters[RegexKey]?.Value;
          
            var regex = new Regex(setRegexValue);
            var messageList = new List<string>();
            foreach (var activityModelVariable in activityModel.Variables)
            {
                if(!regex.IsMatch(activityModelVariable.DisplayName))
                {
                    messageList.Add(string.Format(Strings.ST_NMG_001_ErrorFormat, activityModelVariable.DisplayName, setRegexValue));
                }
            }
            if(messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    ErrorLevel = ruleInstance.ErrorLevel,
                    HasErrors = true,
                    RecommendationMessage = ruleInstance.RecommendationMessage,
                    Messages = messageList
                };
            }
            else
            {
                return new InspectionResult() { HasErrors = false };
            }
        }
    }internal static class VariableNamingRule
    {
        private const string RuleId = "ST-NMG-001";
        private const string RegexKey = "Regex";
        private const string DefaultRegex = @"^([A-Z]|[a-z])+([0-9])*$";
        internal static Rule<IActivityModel> Get()
        {
            var rule = new Rule<IActivityModel>(Strings.ST_NMG_001_Name, RuleId, Inspect)
            {
                RecommendationMessage = Recommendation,
                ErrorLevel = System.Diagnostics.TraceLevel.Warning
            };
            rule.Parameters.Add(RegexKey, new Parameter()
        }
                                
       private static InspectionResult Inspect(IActivityModel activityModel, Rule ruleInstance) 
        {
          // This retrieves the parameter value from the rule instance as configured by the user, if not, the default value.
            var setRegexValue = ruleInstance.Parameters[RegexKey]?.Value;
          
            var regex = new Regex(setRegexValue);
            var messageList = new List<string>();
            foreach (var activityModelVariable in activityModel.Variables)
            {
                if(!regex.IsMatch(activityModelVariable.DisplayName))
                {
                    messageList.Add(string.Format(Strings.ST_NMG_001_ErrorFormat, activityModelVariable.DisplayName, setRegexValue));
                }
            }
            if(messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    ErrorLevel = ruleInstance.ErrorLevel,
                    HasErrors = true,
                    RecommendationMessage = ruleInstance.RecommendationMessage,
                    Messages = messageList
                };
            }
            else
            {
                return new InspectionResult() { HasErrors = false };
            }
        }
    }
请注意,它调用了 RuleIdRegexKey 以及与此规则关联的默认正则表达式 DefaultRegex
RecommendationMessageErrorLevel 参数与前述规则相同。

构建计数器

计数器表示为确定特定事件或条件的发生次数而进行的检查。

其结构与规则略微不同,主要体现在:计数器唯一可用的 ErrorLevel 参数为 Info。因此,为计数器定义错误级别的表达式应如下所示:ErrorLevel = System.Diagnostics.TraceLevel.Info

我们以文件活动统计数据为例,来说明计数器规则的工作原理:

internal static class NumberOfActivitiesInFile
    {
        private const string RuleId = "ST-ANA-009";
        internal static Counter<IActivityModel> Get()
        {
            return new Counter<IActivityModel>(Strings.ST_ANA_009_Name, RuleId, Inspect);
        }
  
  // A Counter<T> receives the entire collection of T objects in the parent structure. e.g. activities in workflow, workflows in project.
  private static InspectionResult Inspect(IReadOnlyCollection<IActivityModel> activities, Counter ruleInstance)
        {
            return new InspectionResult()
            {
              // For a counter, the error level is always info, even if not set here.
                ErrorLevel = System.Diagnostics.TraceLevel.Info,
              // For a counter, the Has Errors field is always ignored.
                HasErrors = false,
                Messages = new List<string>() { string.Format(Strings.ST_ANA_009_ErrorFormat,  activities.Count) }
            };
        }internal static class NumberOfActivitiesInFile
    {
        private const string RuleId = "ST-ANA-009";
        internal static Counter<IActivityModel> Get()
        {
            return new Counter<IActivityModel>(Strings.ST_ANA_009_Name, RuleId, Inspect);
        }
  
  // A Counter<T> receives the entire collection of T objects in the parent structure. e.g. activities in workflow, workflows in project.
  private static InspectionResult Inspect(IReadOnlyCollection<IActivityModel> activities, Counter ruleInstance)
        {
            return new InspectionResult()
            {
              // For a counter, the error level is always info, even if not set here.
                ErrorLevel = System.Diagnostics.TraceLevel.Info,
              // For a counter, the Has Errors field is always ignored.
                HasErrors = false,
                Messages = new List<string>() { string.Format(Strings.ST_ANA_009_ErrorFormat,  activities.Count) }
            };
        }

StudioX 的构建规则

默认情况下,规则仅适用于 Studio 配置文件。若要使规则也显示在 StudioX 配置文件中,请添加 ApplicableScopes 属性并将其配置为包括 BusinessRule。例如,您可以按照以下方式添加属性:
var rule = new Rule<IActivityModel>(Strings.ORG_USG_001_Name, RuleId, Inspect)
            {
                RecommendationMessage = Strings.ORG_USG_001_Recommendation,
                ErrorLevel = TraceLevel.Error,
                //Must contain "BusinessRule" to appear in StudioX, rules always appear in Studio
                ApplicableScopes = new List<string> { RuleConstants.BusinessRule }
            };var rule = new Rule<IActivityModel>(Strings.ORG_USG_001_Name, RuleId, Inspect)
            {
                RecommendationMessage = Strings.ORG_USG_001_Recommendation,
                ErrorLevel = TraceLevel.Error,
                //Must contain "BusinessRule" to appear in StudioX, rules always appear in Studio
                ApplicableScopes = new List<string> { RuleConstants.BusinessRule }
            };

规则注册

注册接口方法

请注意,如果使用此方法,您的包将仅能兼容 Studio 2019.10 版或更高版本。

使用如下方法实现 IRegisterAnalyzerConfiguration 接口:Initialize(IAnalyzerConfigurationService workflowAnalyzerConfigService)
using UiPath.Studio.Activities.Api;
using UiPath.Studio.Activities.Api.Analyzer;
using UiPath.Studio.RulesLibrary.Rules.Naming;
namespace UiPath.Studio.RulesLibrary
{
    public class RegisterAnalyzerConfiguration : IRegisterAnalyzerConfiguration
    {
        public void Initialize(IAnalyzerConfigurationService workflowAnalyzerConfigService)
        {
            // Naming
            workflowAnalyzerConfigService.AddRule(VariableNamingRule.Get());
            workflowAnalyzerConfigService.AddRule(DisplayNameDuplicationRule.Get());
            workflowAnalyzerConfigService.AddRule(VariableNameDuplicationRule.Get());
            workflowAnalyzerConfigService.AddRule(ArgumentNamingRule.Get());
            workflowAnalyzerConfigService.AddRule(VariableLengthRule.Get());
        }
    }
}using UiPath.Studio.Activities.Api;
using UiPath.Studio.Activities.Api.Analyzer;
using UiPath.Studio.RulesLibrary.Rules.Naming;
namespace UiPath.Studio.RulesLibrary
{
    public class RegisterAnalyzerConfiguration : IRegisterAnalyzerConfiguration
    {
        public void Initialize(IAnalyzerConfigurationService workflowAnalyzerConfigService)
        {
            // Naming
            workflowAnalyzerConfigService.AddRule(VariableNamingRule.Get());
            workflowAnalyzerConfigService.AddRule(DisplayNameDuplicationRule.Get());
            workflowAnalyzerConfigService.AddRule(VariableNameDuplicationRule.Get());
            workflowAnalyzerConfigService.AddRule(ArgumentNamingRule.Get());
            workflowAnalyzerConfigService.AddRule(VariableLengthRule.Get());
        }
    }
}
注意:IAnalyzerConfigurationService 调用 HasFeature 方法以注册特定 Studio 版本的规则。

IRegisterMetadata 方法

请注意,此方法仅适用于 Studio 2019.6 以上版本,且与注册接口方法相比较为逊色。

  • 在您的 IRegisterMetadata 实现中添加 void 方法 Initialize(object api)
  • Initialize 实现中,将 object 参数转换为 WorkflowDesignApi,然后将所有内容添加到“异常处理”活动下,以确保妥善解决任何异常。
  • 解析 WorkflowDesignApi 后,即可获得 WorkflowAnalyzerConfigService 属性。
  • 此时,您可以访问上一部分中详述的 IAnalyzerConfigurationService

在 Studio 中添加规则

您可通过以下两种方法将自定义工作流分析器规则集成到 Studio 中:

  • 全局级别:在 Studio 的安装位置添加外部程序集 (.dll)
  • 项目级别:安装自定义活动包。

全局级别

要在 Studio 实例中创建的所有项目中使用自定义规则,您必须将外部程序集 (.dll) 包添加到 Studio 从中加载自定义规则的特定文件夹中。默认情况下,文件夹路径为:

  • 在 2021.10 之前的 Studio 版本中:

    • For per-machine installations: %ProgramFiles%\UiPath\Studio\Rules
    • 对于基于用户的安装: %LocalAppData%\Programs\UiPath\Studio\Rules
  • 在 Studio 2021.10.6 及更高版本中:

    • 对于每台计算机安装:%ProgramFiles%\UiPath\Studio\Rules\net6.0(适用于针对 Windows 和跨平台项目的规则)和 %ProgramFiles%\UiPath\Studio\net461\Rules(适用于针对 Windows 旧版项目的规则)
    • 对于每个用户安装:%LocalAppData%\Programs\UiPath\Studio\Rules\net6.0(适用于针对 Windows 和跨平台项目的规则)和 %LocalAppData%\Programs\UiPath\Studio\net461\Rules(适用于针对 Windows 旧版项目的规则)

(可选)您可以更改 Studio 加载自定义规则的文件夹,方法是转到“主页” (Studio 后台视图)> “设置” >“位置”,然后定义“自定义工作流分析器规则位置”。 Studio v2020.10 中提供了此功能。 及更高版本。

按照创建自定义活动页面中列出的详细步骤,以 .dll 文件形式导出代码。

项目级别

要使自定义规则仅可用于某个项目,请创建一个 NuGet 包 ( .nupkg ),并将其作为依赖项安装在 Studio 项目中。

此页面是否有帮助?

获取您需要的帮助
了解 RPA - 自动化课程
UiPath Community 论坛
Uipath 白色徽标
信任与安全
© 2005-2024 UiPath. All rights reserved.