如何在UiPath类库活动与独立WinForms项目间实现数据交互
问题解答:UiPath活动与独立WinForms项目的通信及程序集引用
一、手动在WinForms项目中引用System.Activities和System.ComponentModel
按以下步骤操作:
- 右键WinForms项目 → 选择添加 → 引用
- 在弹出的引用管理器中切换到程序集 → 框架标签
- 在列表中找到
System.Activities和System.ComponentModel,勾选后点击确定 - 若列表中找不到,可通过浏览选项卡手动定位到.NET Framework安装目录(通常为
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\vX.X\,X.X对应你的.NET版本),选择对应DLL添加引用
二、两个独立DLL项目间的通信(传递DataTable)
针对你的场景,推荐以下三种方案,可根据数据量和交互需求选择:
方案1:命令行参数传递序列化数据(小数据量场景)
将DataTable序列化为XML字符串,作为命令行参数传递给WinForms程序,再反序列化还原。
类库(UiPath活动)代码修改:
using System; using System.Activities; using System.ComponentModel; using System.Data; using System.IO; using System.Xml.Serialization; using System.Diagnostics; namespace Datatable_Visualizer_Activity { public class DatatableVisualizer : CodeActivity { [DisplayName("Datatable")] public InArgument<DataTable> Datatable { get; set; } protected override void Execute(CodeActivityContext context) { DataTable dt = Datatable.Get(context); // 序列化DataTable为XML string xmlData; using (StringWriter sw = new StringWriter()) { XmlSerializer serializer = new XmlSerializer(typeof(DataTable)); serializer.Serialize(sw, dt); xmlData = sw.ToString(); } // 启动WinForms程序并传递参数 ProcessStartInfo psi = new ProcessStartInfo { FileName = "Data_Table_Visualizer___Editor.exe", Arguments = $"\"{xmlData}\"" // 用引号包裹避免特殊字符截断 }; Process.Start(psi); } } }
WinForms项目代码修改:
首先修改Program.cs接收命令行参数:
using System; using System.Windows.Forms; namespace Data_Table_Visualizer___Editor { static class Program { [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm(args)); } } }
然后修改MainForm.cs:
using MaterialSkin; using MaterialSkin.Controls; using System.Data; using System.Drawing.Drawing2D; using System.Reflection; using System.Windows.Forms; using System.IO; using System.Xml.Serialization; namespace Data_Table_Visualizer___Editor { public partial class MainForm : Form { private DataTable dataTable; public MainForm(string[] args) { this.DoubleBuffered = true; InitializeComponent(); dataGridView.Visible = false; ShowLoading(true); // 解析命令行参数还原DataTable if (args.Length > 0) { string xmlData = args[0]; using (StringReader sr = new StringReader(xmlData)) { XmlSerializer serializer = new XmlSerializer(typeof(DataTable)); dataTable = (DataTable)serializer.Deserialize(sr); } } InitializeDataGridViewAsync(); } private void ShowLoading(bool show) { progressBar.Visible = show; } private async void InitializeDataGridViewAsync() { await Task.Run(() => { Invoke(new Action(() => { if (dataTable != null) { dataGridView.DataSource = dataTable; dataGridView.DoubleBuffered(true); dataGridView.AutoResizeColumns(); label_TotalNoColumns.Text = $"Total No Of Columns = {dataTable.Columns.Count}"; label_TotalNoRows.Text = $"Total No Of Rows = {dataTable.Rows.Count}"; } ShowLoading(false); dataGridView.Visible = true; })); }); } private void dataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e) { e.Column.FillWeight = 10; } } public static class ExtensionMethods { public static void DoubleBuffered(this DataGridView dgv, bool setting) { Type dgvType = dgv.GetType(); PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); pi.SetValue(dgv, setting, null); } } }
方案2:内存映射文件(大数据量场景)
当DataTable数据量较大时,命令行参数长度受限,可使用内存映射文件共享数据:
类库端核心代码:
using System.IO.MemoryMappedFiles; using System.Runtime.Serialization.Formatters.Binary; // ... 其他引用 protected override void Execute(CodeActivityContext context) { DataTable dt = Datatable.Get(context); // 序列化为字节数组 byte[] data; using (MemoryStream ms = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, dt); data = ms.ToArray(); } // 创建内存映射文件 using (var mmf = MemoryMappedFile.CreateNew("DataTableMMF", data.Length)) { using (var stream = mmf.CreateViewStream()) { stream.Write(data, 0, data.Length); } // 启动WinForms程序并传递映射文件名 Process.Start("Data_Table_Visualizer___Editor.exe", "DataTableMMF"); } }
WinForms端核心代码:
// 在MainForm构造函数中添加 if (args.Length > 0) { string mmfName = args[0]; using (var mmf = MemoryMappedFile.OpenExisting(mmfName)) { using (var stream = mmf.CreateViewStream()) { BinaryFormatter formatter = new BinaryFormatter(); dataTable = (DataTable)formatter.Deserialize(stream); } } }
方案3:WCF本地命名管道(双向交互场景)
若需要WinForms向UiPath活动返回修改后的DataTable,可使用WCF的NetNamedPipeBinding:
- 定义共享契约接口(单独创建类库供两个项目引用)
- UiPath活动作为服务端发布数据,WinForms作为客户端连接获取数据
- 完成交互后可通过回调机制将修改后的数据返回
此方案复杂度较高,适合有双向通信需求的场景。
三、NuGet打包注意事项
- 在NuSpec文件中通过
<files>节点配置,将WinForms的EXE和类库DLL一起打包 - UiPath活动中需通过NuGet安装路径动态定位WinForms EXE的位置,避免硬编码路径
内容的提问来源于stack exchange,提问作者Vasant Raval
相关产品推荐
相关产品推荐

