TIA Openness 应用的多版本支持
当使用西门子TIA Portal Openness API开发应用程序时,引用特定版本的DLL会创建硬依赖,将您的应用程序限制为单个TIA Portal版本。
本文档介绍了两种方法,用于创建单个编译后的应用程序,该应用程序可根据安装的TIA Portal版本动态解析并加载正确的Siemens.Engineering.dll和Siemens.Engineering.Hmi.dll。
1、问题陈述
在Visual Studio项目中直接引用特定TIA Portal版本(例如V15.1或V16)的DLL时,如果目标系统安装了不同的TIA Portal版本,会导致FileNotFoundException或BadImageFormatException。应用程序无法找到它编译时所依据的特定DLL版本。
2、根本原因
.NET的程序集绑定机制尝试在运行时加载所引用程序集的精确版本。当编译器引用版本为15.1.0.0的Siemens.Engineering.dll时,运行时会搜索该精确版本。如果只安装了TIA Portal V16,绑定将失败。
注意: TIA Portal Openness DLL位于C:\Program Files\Siemens\Automation\Portal V15_1\PublicAPI\V15.1\和C:\Program Files\Siemens\Automation\Portal V16\PublicAPI\V16\。每个版本都有自己的一组程序集,具有匹配的版本号。
3、解决方案1:App.Config CodeBase绑定
app.config文件可以为同一程序集标识符指定多个codeBase条目,允许运行时定位已安装的版本。此方法需要在更改TIA Portal版本后重新启动应用程序。
3.1 配置步骤
- 如果项目中没有
app.config文件,请添加一个 - 使用每个TIA Portal版本的
codeBase条目配置<assemblyBinding>部分 - 确保项目中引用的DLL版本与配置中的条目匹配
3.2 App.Config示例
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Siemens.Engineering"
culture="neutral"
publicKeyToken="d29ec89bac048f84"/>
<codeBase version="15.1.0.0"
href="file:///C:\Program%20Files\Siemens\Automation\Portal%20V15_1\PublicAPI\V15.1\Siemens.Engineering.dll"/>
<codeBase version="16.0.0.0"
href="file:///C:\Program%20Files\Siemens\Automation\Portal%20V16\PublicAPI\V16\Siemens.Engineering.dll"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Siemens.Engineering.Hmi"
culture="neutral"
publicKeyToken="37b6e3a80df0900f"/>
<codeBase version="15.1.0.0"
href="file:///C:\Program%20Files\Siemens\Automation\Portal%20V15_1\PublicAPI\V15.1\Siemens.Engineering.Hmi.dll"/>
<codeBase version="16.0.0.0"
href="file:///C:\Program%20Files\Siemens\Automation\Portal%20V16\PublicAPI\V16\Siemens.Engineering.Hmi.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
3.3 支持的程序集
| 程序集名称 | PublicKeyToken | V15.1路径 | V16路径 |
|---|---|---|---|
| Siemens.Engineering | d29ec89bac048f84 | \PublicAPI\V15.1\ | \PublicAPI\V16\ |
| Siemens.Engineering.Hmi | 37b6e3a80df0900f | \PublicAPI\V15.1\ | \PublicAPI\V16\ |
| Siemens.Engineering.Platform | 57f3cc8d4f4d1d9a | \PublicAPI\V15.1\ | \PublicAPI\V16\ |
4、解决方案2:AssemblyResolve事件处理程序
要在不重启应用程序的情况下进行运行时版本切换,请实现AppDomain.CurrentDomain.AssemblyResolve事件。这提供了对程序集加载的完全控制,并允许从Windows注册表读取TIA Portal安装。
4.1 C#实现
using System;
using System.IO;
using System.Reflection;
using Microsoft.Win32;
public class TiaPortalResolver
{
private static readonly string[] TiaAssemblyNames =
{
"Siemens.Engineering",
"Siemens.Engineering.Hmi",
"Siemens.Engineering.Platform"
};
public static void RegisterResolver()
{
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
}
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
var requestedAssembly = new AssemblyName(args.Name);
if (Array.IndexOf(TiaAssemblyNames, requestedAssembly.Name) == -1)
return null;
var dllPath = FindTiaAssemblyPath(requestedAssembly.Name, requestedAssembly.Version?.ToString());
if (!string.IsNullOrEmpty(dllPath) && File.Exists(dllPath))
{
return Assembly.LoadFrom(dllPath);
}
return null;
}
private static string FindTiaAssemblyPath(string assemblyName, string version)
{
var tiaPaths = GetTiaInstallationPaths();
foreach (var basePath in tiaPaths)
{
var searchPattern = Path.Combine(basePath, "PublicAPI", "*", $"{assemblyName}.dll");
if (!string.IsNullOrEmpty(version))
{
var versionPath = Path.Combine(basePath, "PublicAPI", $"V{version}", $"{assemblyName}.dll");
if (File.Exists(versionPath))
return versionPath;
}
var parentDir = Path.GetDirectoryName(basePath);
if (parentDir != null)
{
var apiBase = Path.Combine(parentDir, "PublicAPI");
if (Directory.Exists(apiBase))
{
foreach (var versionDir in Directory.GetDirectories(apiBase, "V*"))
{
var dllPath = Path.Combine(versionDir, $"{assemblyName}.dll");
if (File.Exists(dllPath))
return dllPath;
}
}
}
}
return null;
}
public static string[] GetTiaInstallationPaths()
{
var paths = new List<string>();
using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Siemens\Automation\InstalledApps"))
{
if (key != null)
{
foreach (var subKeyName in key.GetSubKeyNames())
{
if (subKeyName.Contains("Portal"))
{
using (var subKey = key.OpenSubKey(subKeyName))
{
var path = subKey?.GetValue("INSTALLPATH") as string;
if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
{
paths.Add(path);
}
}
}
}
}
}
return paths.ToArray();
}
}
4.2 使用方法
class Program
{
static void Main(string[] args)
{
TiaPortalResolver.RegisterResolver();
var tiaVersion = Siemens.Engineering.Version.SupportedVersions[0];
using (var plc = tiaVersion.Attach(null))
{
// 您的应用程序逻辑
}
}
}
5、注册表读取工具
TIA Portal安装在HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\InstalledApps下注册。每个子键代表一个已安装的西门子应用程序,其INSTALLPATH值包含基本安装目录。
| 注册表键 | 典型值 |
|---|---|
| HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\InstalledApps\Totally Integrated Automation Portal V15.1 | C:\Program Files\Siemens\Automation\Portal V15_1 |
| HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\InstalledApps\Totally Integrated Automation Portal V16 | C:\Program Files\Siemens\Automation\Portal V16 |
| HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\InstalledApps\Totally Integrated Automation Portal V17 | C:\Program Files\Siemens\Automation\Portal V17 |
重要提示: 在64位Windows上,注册表视图可能在WOW6432Node下。请同时检查HKEY_LOCAL_MACHINE\SOFTWARE\Siemens和HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Siemens。
6、版本检测逻辑
实现动态解析时,在ResolveEventArgs.Name中匹配程序集名称时,请使用EndsWith而不是Contains。某些绑定失败可能包含"Siemens.Engineering"作为子字符串,但指的是不同的程序集。已解析的程序集名称格式为:
Siemens.Engineering, Version=15.1.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84
7、限制和已知问题
- 配置缓存: app.config在程序启动时加载并缓存。运行时修改需要重新启动应用程序。
- 清单不匹配: 尝试加载与预期清单不同的DLL可能会抛出
BadImageFormatException。请确保以正确的DLL版本为目标。 - 引用版本: 您仍必须在Visual Studio项目中引用DLL的某个版本。解析器在运行时重定向到已安装的版本。
- V17行为: TIA Portal V17在单个安装中包含从V14到V17版本的DLL。从V17文件夹引用V15.0 DLL仍可能启动V17 TIA Portal。
8、验证步骤
- 构建引用一个TIA Portal版本(例如V15.1 DLL)的应用程序
- 部署到安装了不同TIA Portal版本(例如V16)的计算机
- 启动您的应用程序
- 通过任务管理器或TIA Portal UI验证是否启动了正确的TIA Portal版本
- 检查应用程序日志以确认程序集解析成功
原文链接: Configuring TIA Portal Openness DLL for Multi-Version Support
汇智网翻译整理,转载请标明出处