在构建期间编写进程参数



我的TFS2012自定义构建工作流有许多自定义参数,这些参数在我的构建定义中定义。我想将它们全部传递给在构建期间运行的 exe(我知道自定义活动的选项,但我不能使用它,因为我不想每次都更改控制器的二进制文件)。

我设法拿buildDetail.ProcessParametersbuildDetail.buildDefinition.ProcessParameters,将它们写入文件并将它们传递给我的exe,它将解析它们(可能使用WorkflowHelpers.DeserializeProcessParameters.但是,这意味着 exe 将需要合并两个ProcessParameters,我想避免这种情况。

有没有办法从工作流程中获取生成的过程参数?我可以调用 WorkflowHelpers.GetProcessParameters(Activity),但是如何获取工作流的根活动?

我设法通过保持WorkflowInstanceProxy来做到这一点,如此处建议:

public class WriteProcessParameters : CodeActivity
{
    protected override void Execute(CodeActivityContext context)
    {
        WorkflowInstanceProxy proxy = context.GetExtension<WorkflowInstanceInfo>().GetProxy();
        Activity root = proxy.WorkflowDefinition;
        Dictionary<string, ProcessParameter> processParams = WorkflowHelpers.GetProcessParameters(root);
        // Serialize processParams somehow...
    }
    protected override void CacheMetadata(CodeActivityMetadata metadata)
    {
        base.CacheMetadata(metadata);
        metadata.AddDefaultExtensionProvider<WorkflowInstanceInfo>(() => new WorkflowInstanceInfo());
    }
    private class WorkflowInstanceInfo : IWorkflowInstanceExtension
    {
        private WorkflowInstanceProxy m_proxy;
        public IEnumerable<object> GetAdditionalExtensions() { yield break; }
        public void SetInstance(WorkflowInstanceProxy instance) { this.m_proxy = instance; }
        public WorkflowInstanceProxy GetProxy() { return m_proxy; }
    }
}

这在我的玩具测试中有效,但在实际的工作流程中无效(不知道为什么)。所以我最终阅读了属性,如下所示:

public InArgument<string> Filename { get; set; }
protected override void Execute(CodeActivityContext context)
{
    var propDescriptors = context.DataContext.GetProperties().Cast<PropertyDescriptor>();
    var props = new Dictionary<string, object>();
    foreach (var propDesc in propDescriptors.OrderBy(p => p.Name))
    {
        object value = propDesc.GetValue(context.DataContext);
        if (value == null)
        {
            var converter = TypeDescriptor.GetConverter(propDesc.PropertyType);
            if (converter.CanConvertTo(propDesc.PropertyType))
            {
                value = converter.ConvertTo(value, propDesc.PropertyType); // Known case: null string
            }
            else
            {
                continue;  // Known case: RunTestParameters
            }
        }
        else
        {
            if (!value.GetType().IsVisible || !value.GetType().IsSerializable)
            {
                continue;
            }
        }
        props.Add(propDesc.Name, value);
    }
    File.WriteAllText(Filename.Get(context), WorkflowHelpers.SerializeProcessParameters(props));
}

最新更新