In a c#
app how would I find all the variables in a project with a specific Attribute
?
class Program
{
static void Main()
{
try
{
using (AdsClient Client = new AdsClient())
{
// Connect to the TwinCAT ADS router
Client.Connect("172.18.233.27.1.1", 851);
//Creating a symbol loader
SymbolLoaderSettings settings = new SymbolLoaderSettings(SymbolsLoadMode.DynamicTree);
IAdsSymbolLoader dynLoader = (IAdsSymbolLoader)SymbolLoaderFactory.Create(Client, settings);
// Search for symbols with a specific attribute
string desiredAttribute = "AddToConfig";
foreach (IAdsSymbol symbol in dynLoader.Symbols)
{
if ( symbol.Attributes.Contains(desiredAttribute))
{
// Perform actions on the symbol that has the attribute
Console.WriteLine($"Symbol Name: {symbol.InstanceName}");
Console.WriteLine($"Symbol Path: {symbol.InstancePath}");
// ... Additional actions
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
I get this error.
Error: Unable to cast object of type 'TwinCAT.TypeSystem.DynamicVirtualStructInstance' to type 'TwinCAT.Ads.TypeSystem.IAdsSymbol'.
The code you are trying to implement requires a little bit more of recursion to find nested variables inside global variable lists or also in a POUs
(Program), i had a similar situation once and i developed the following solution:
using System;
using System.Collections.Generic;
using System.Linq;
using TwinCAT;
using TwinCAT.Ads;
using TwinCAT.Ads.TypeSystem;
using TwinCAT.TypeSystem;
namespace StackOverflow
{
internal class Program
{
static void Main()
{
try
{
using (AdsClient Client = new AdsClient())
{
string ams = "172.18.233.27.1.1";
// Connect to the TwinCAT ADS router
Client.Connect(ams, 851);
//Creating a symbol loader
SymbolLoaderSettings settings = new SymbolLoaderSettings(SymbolsLoadMode.DynamicTree);
var symbolCollectionDict = (SymbolLoaderFactory.Create(Client, SymbolLoaderSettings.Default).Symbols as SymbolCollection).ToInstanceDictionary();
// Search for symbols with a specific attribute
string desiredAttribute = "AddToConfig";
foreach (var symbol in symbolCollectionDict)
{
var firstAttribute = symbol.Value.Attributes.FirstOrDefault(x => x.Name.Contains(desiredAttribute));
if (firstAttribute != null)
{
// Perform actions on the symbol that has the attribute
Console.WriteLine($"Symbol Name: {symbol.Key}");
Console.WriteLine($"Symbol Path: {symbol.Value.InstancePath}");
// ... Additional actions
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
// This static class will define extension methods that
// we are calling in our program
public static class ExtMethods
{
public static Dictionary<string, Instance> ToInstanceDictionary(this ISymbolCollection symbolCollection)
{
if (symbolCollection == null)
{
return new Dictionary<string, Instance>();
}
var dict = symbolCollection.ToDictionary(t => t.InstancePath, t => (Instance)t);
foreach (var symbol in dict.Values.ToArray())
{
dict.MergeDicts(GetMemeberList(symbol));
}
return dict;
}
private static Dictionary<string, Instance> GetMemeberList(Instance symbol)
{
var memberInstancesPropInfo = symbol.GetType().GetProperty("MemberInstances");
if (memberInstancesPropInfo != null)
{
var dict = ((ISymbolCollection)memberInstancesPropInfo.GetValue(symbol)).ToDictionary(t => t.InstancePath, t => (Instance)t);
foreach (var internalSymbol in dict.Values.ToArray())
{
dict.MergeDicts(GetMemeberList(internalSymbol));
}
if (dict.Count > 0)
{
return dict;
}
}
return new Dictionary<string, Instance>();
}
public static Dictionary<T1, T2> MergeDicts<T1, T2>(this Dictionary<T1, T2> masterDictionary, Dictionary<T1, T2> dictionaryToAppend)
{
foreach (KeyValuePair<T1, T2> keyValuePair in dictionaryToAppend)
{
if (masterDictionary.ContainsKey(keyValuePair.Key) == false)
{
masterDictionary.Add(keyValuePair.Key, keyValuePair.Value);
}
}
return masterDictionary;
}
}
}
The extension methods handle the recursion and generate a dictionary where you can find the variable name and instance, after that you have to loop inside the attributes until you find the required variables, i tested with a small project in twincat 3. I got the following output in the console:
which is correct!