I have to use Beckhoff I/O in real-time mode (not PLC project), because the final goal is to make a Soft-PLC, where the program runs on the cumputer and not on Beckhoff. So in Visual Studio I wrote a c# code which opens an existing TwinCAT project in background (with a task and some variables linked), activates the configuration and then gets the symbols from that task, so I can use them to control in realtime the variables (e.g. reading an input or writing an output). The problem is I can't get the symbols! (Im using the SymbolLoaderFactory.Create method). I created a class "Controlling" in the same namespace which contains some methods like GoConfig(), Open(), Activate() etc..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
using System.IO;
using TCatSysManagerLib;
using System.Management;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Collections;
using System.Xml;
using TwinCAT.Ads;
using TwinCAT.Ads.ValueAccess;
using TwinCAT.Ads.TypeSystem;
using TwinCAT.TypeSystem;
namespace TCControl
{
class Program
{
[STAThread]
static void Main(string[] args)
{
string solName = "solution1";
string solPath = $#"B:\...solutionPath...\{solName}";
string[] terminal = new string[1];
terminal[0] = "EK1100";
string ipAddress = "10.157.4.69.1.1";
int port = 301;
Controlling co = new Controlling();
MessageFilter.Register();
//go to configuration mode
co.GoConfig(ipAddress);
//open the solution
string[,] treeItemsandTypes = co.Open(solPath, solName, ipAddress, terminal);
co.Activate(solPath, solName);
//obtain symbols
ISymbolLoader symbolLoader = co.SymbolsGetter(ipAddress, port);
ISymbol[] symbols = new ISymbol[symbolLoader.Symbols.Count];
int i = 0;
foreach (ISymbol symbol in symbolLoader.Symbols)
{
symbols[i] = symbol;
i++;
}
Console.WriteLine("\n" + symbols[0].ToString());
Console.WriteLine("\n" + symbols[1].ToString());
All projects I created to test this had 2 variables linked to the task.
Everything works fine until the SymbolsGetter method. From the Controlling class:
public ISymbolLoader SymbolsGetter(string indirizzo, int port)
{
using (TcAdsClient client = new TcAdsClient())
{
System.Threading.Thread.Sleep(2000);
client.Connect(indirizzo, port);
//Creates the Symbol Objects as hierarchical tree
SymbolLoaderSettings settings = new SymbolLoaderSettings(SymbolsLoadMode.Flat, ValueAccessMode.IndexGroupOffsetPreferred);
ISymbolLoader symbolLoader = SymbolLoaderFactory.Create(client, settings);
//System.Threading.Thread.Sleep(2000);
return symbolLoader;
}
}
The Thread.Sleep is because otherwise the client.Connect generated an error.
It only works in debug if I add a break point on "return symbolLoader" and if I pass over it with the mouse puntator to see the value (of symbolLoader).
I tried to insert another sleep but nothing, it doesn't work. Im actually starting thinking it is black magic.
Another problem is that I can't get symbols from all projects (nether using the debug technique of before). And even when it works I can't use the name of the symbol to write a high/low signal to that variable. So nothing is working, I'm just able to create and open a project, a task etc.
Just one more information: im using windows 10 (maybe TwinCAT works better on windows 7 or xp, but I have to make it work on windows 10).
I have to do everything without touching or seeing the TwinCAT project window, it has to stay in background. I'm not a programmer and I'm quite new into the Beckhoff/TwinCAT world. Please if anyone can help me I'd be incredibly thankful to him.
If you want to use the ADS library from beckhoff you cannot not have a Beckhoff PLC-Runtime in the background.
With the ADS-lib you access the symbols in the PLC Runtime which has an Ethercat Master with which it can communicate with the Beckhoff Ethercat IOs.
If you do not want to use a Beckhoff Plc-Runtime (and it's not really clear to me why you wouldn't want to) you need another kind of Ethercat Master in order to communicate with the IOs.
I have to use Beckhoff I/O in real-time mode (not PLC project), because the final goal is to make a Soft-PLC, where the program runs on the cumputer and not on Beckhoff.
This is confusing, because the Beckhoff runtime runs on computer besides windows.
If you want to control IOs without real time capability you can buy an Advantech PCI IO card for example and use their c# sdk.
You can't use c# to access Beckhoff IOs without a Beckhoff runtime in the background.
Twincat doesn't work better on windows 7 or xp in fact Twincat 3 is not even supported on windows xp and new machines only use windows 10 for security and support reasons.
Related
I am using Visual Studio Community 2019 to write a new serial port downloader program. I am relatively new to C# but have had to maintain a large-ish c# application that also uses the serial port to configure an embedded device.
Problematic (new) code is below. The "System.IO.Ports" using statement has no effect (is greyed out) and the issue is that the compiler has no clue what a "SerialPort" is (see the error after the code).
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.Ports;
using System.Drawing;
namespace PangeaUpdater
{
class Download
{
const byte STX_CHAR = (byte)'\x2';
const byte ETX_CHAR = (byte)'\x3';
const byte DLE_CHAR = (byte)'\x10';
const int MAX_DATA_PACKET_LEN = 128;
private BinaryReader pkgStream = null;
public SerialPort serialPort;
private void Create(String comPort, String baudrate,
System.Windows.Forms.RichTextBox msgListBox,
System.Windows.Forms.ProgressBar progressBar)
{
//Lots of stuff should be configurable but is not (yet)
serialPort = new SerialPort(comPort,
Convert.ToInt32(baudrate),
Parity.None,
8,
StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.Open();
serialPort.ReadTimeout = 1000;
progBar = progressBar;
messages = msgListBox;
}
public Download(String comPort,
String baudrate,
//String Product,
System.Windows.Forms.RichTextBox msgListBox,
System.Windows.Forms.ProgressBar progressBar)
{
Create(comPort, baudrate, /*Product,*/ msgListBox, progressBar);
}
}
}
C:...\Download.cs(20,16,20,26): error CS1069: The type name 'SerialPort' could not be found in the namespace 'System.IO.Ports'. This type has been forwarded to assembly 'System.IO.Ports, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly.
I have checked against the app that I maintain and which compiles and runs fine. The old app has a set of References, but the new app has just a set of dependencies, but I gather these are very similar or the same?
I suspect adding a reference is what is required but I have no clue what is needed. When I try to add a Reference in the new app I see nothing except for COM assemblies. There are loads but there is no clue as to which might be needed for serial port stuff. The old config app does not give any clue as the where it finds a reference for the SerialPort type.
Does anyone have a clue what I may have missed?
You probably need to add a reference to System.ComponentModel.Component.
See: https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=netframework-4.8
If its a .NET 6 application you probably need VS2022 and a NuGet package:
https://www.nuget.org/packages/System.IO.Ports/
(.NET 6 is not supported in VS2019)
I found the problem. It was that I had inadvertently chosen a framework "core" project as the template. As a newbie to Visual Studio C#, I don't understand why there are so many templates. It seems to be a confusing array of project types with no explanation of the subtle differences between them.
Anyway, thanks for the suggestions. I think that I focussed to closely on the actual error message and not enough on the other symptoms of this problem, like most of the components in the toolbox being missing!
I'm working on a cross platform app using the GTK toolkit and when I'm trying to access the System.IO namespace to extract Path fields, I'm getting the following error:
Error CS0119: 'Widget.Path(out uint, out string, out string)' is a method, which is not valid in the given context (CS0119) (netmonmd)
I have using System.IO; in the source file and I'm using other namespaces without any issue (eg System.Console and System.Refelection without any issues further down in the code).
I have almost identical code in a console application working without an issue.
Here is the code, if I fully provide the Path it works, I just can't use it within the namespace (but I can use other things that are in the same namespace)
using Gtk;
using System;
using System.IO;
using static System.Console;
public partial class MainWindow : Gtk.Window
{
private netmonmd.iplabel[] ids;
private int fSize = 12;
public MainWindow() : base(Gtk.WindowType.Toplevel)
{
Build();
//char filesep = System.IO.Path.DirectorySeparatorChar; // works
char filesep = Path.DirectorySeparatorChar; // error
I'm trying to understand the error (I am new to C#) and think it has to do with calling it within the MainWindow function since it seems to be referring to Widget.Path and not System.Path
Is this a case of just having to fully qualify it each time?
I could move all the code out of the main window and process it elsewhere in the app.cs file, however it is a single window app that I was developing in the one space. If it is better practise to separate it out I will do that.
(as is usually the case in asking on stack, while writing this question out I'm becoming more aware of what's actually happening here, I just don't know how to work around it)
I have a C# program running under Visual Studio 15 .NET Framework 4.5.2. It uses AutoMapper 4.1.1. It's been running fine for years. (I inherited it from someone else.) Just lately, it started erroring out at the line "AutoMappings.AutoMappings.CreateMaps();" Here's the relevant code:
using System;
using System.Windows.Forms;
using IVGOffice.UserInterface;
using System.Net;
using System.Net.Security;
namespace IVGOffice
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// Assign certification callback to allow for self-signed certs on the services
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(IVG.Common.Certificate.ValidateRemoteCertificate);
AutoMappings.AutoMappings.CreateMaps(); // <----- Errors out here
It throws a System.TypeInitiializationException with inner error "Configuration system failed to initialize". It never actually enters into the AutoMappings class, so I don't think the problem is related to the class, but here's the beginning of it anyway:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IVG.Common;
using IVG;
namespace IVGOffice.AutoMappings
{
public static class AutoMappings
{
private static bool mapsCreated = false;
private static Utilities2.Services services = new Utilities2.Services();
public static void CreateMaps()
{
// AutoMapper CreateMap should only be called once in an application domain. If we call this twice, check and just leave the second time
if (mapsCreated)
return;
// For every IAutomappedObject
System.Reflection.Assembly assm = System.Reflection.Assembly.GetCallingAssembly();
var interfaceTypes = assm.GetTypes();
var automappedTypes = interfaceTypes.Where(type => typeof(IAutomappedObject).IsAssignableFrom(type)
&& !type.IsAbstract
&& !type.IsInterface);
foreach (var type in automappedTypes)
...
My coworker tried running the same code on his laptop and it worked fine, so there must be something going on with my copy of Visual Studio or my computer settings. I've tried running different versions of the program, rebooting, restoring the program from backup, etc. to no avail.
Anybody have any ideas? Thanks.
I hit this today because I stupidly placed appSettings before the configSections in my app.config file.
The error possibly indicates that your config file contains illegal syntax/layout. I'd start your investigation there.
The problem was in the configuration, but not in app.config. I had added code to save and restore the window status, location, and size. These settings were saved into a new user.config file. The problem was that I had added this code to a new git repo. My boss had to approve the changes before merging them into the master repo. In the meantime, I had gone back to the master to start a new project. The master didn't have the new code, but the new user.config file was still there. For some reason, that seems to have confused the program. When my boss finally merged the new code and I updated my copy of the master, the problem went away. Thanks for your feedback.
I'm creating a program that uses the CodeProject CoreAudioApi (pretty popular framework for manipulating audio), but the problem is the CoreAudioApi uses system calls that aren't available in any versions of Windows earlier than Vista. If I run a program with CoreAudioApi compiled with it (using a using statement as normal), the program will crash on anything earlier than Vista.
I've created this function to get the version number of the current environment:
win_version = Environment.OSVersion.Version.Major;
That returns the major version number I need. '6' is Vista/7, anything else is not, which is all I need to determine. Utilizing this, I need to determine whether or not to include the CoreAudioApi namespace if the OS is over or equal to '6'. From research, usings need to be compiled with the program, but I've also read about something called Reflection - which might be what I need.
Once I get the CoreAudioApi namespace using'd (sorry for the lack of terminology), the rest is easy. How can I do this?
TL;DR
I need some form of code that would effectively do this:
using System;
using System.Text;
//etc
if(currentWindowsVersion>=6) using CoreAudioApi;
Except control structures won't work outside of a class, and all namespaces are compiled with the program, not controlled individually.
Thanks!
EDIT: So far, I'm using this to load the CoreAudioApi namespace as a compiled assembly:
if(win_version>=6){
CoreAudioApi = Assembly.LoadFrom("CoreAudio.dll");
CoreAudioApi.GetLoadedModules();
CoreAudioApi.GetTypes();
MessageBox.Show("Loaded CoreAudioApi");
}
From here, what I need to do is actually use the types, and methods from the API. My code that works on Windows Vista/7 is this:
public static MMDeviceEnumerator devEnum;
public static MMDevice defaultDevice;
//later in a mute method:
defaultDevice.AudioEndpointVolume.Mute = true/false;
I don't even really need devEnum AFAIK, so really the only important lines are the last two (besides the comment).
I've just tried the following:
Create a new console application project
Add the CoreAudioApi project from CodeProject to the solution
Add a project reference to CoreAudioApi in my console app
Create the following classes:
interface IAudio { void SetVolume(float level); }
class XpAudio : IAudio {
public void SetVolume(float level) {
// I do nothing, but this is where your old-style code would go
}
}
class VistaAudio : IAudio {
public void SetVolume(float level) {
MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
MMDevice defaultDevice = devEnum
.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
defaultDevice.AudioEndpointVolume.MasterVolumeLevel = level;
}
}
class Program {
static void Main(string[] args) {
IAudio setter = Environment.OSVersion.Version.Major >= 6
? (IAudio)new VistaAudio()
: (IAudio)new XpAudio();
float val = float.Parse(Console.ReadLine());
setter.SetVolume(val);
Console.ReadLine();
}
}
This runs on both my server (~ Windows 7) and local (Windows XP) machines. On my XP machine it'll happily take in a value and ignore it; on my server, it throws an exception, (presumably because I don't have a sound output). If I make my XP machine run the CoreAudioApi, I get an exception when I input a value, not before.
The question is, what are you doing differently to make your application break? Are you using CoreAudioApi code at startup?
EDIT: After seeing your edit, if you do this, you shouldn't need to mess about with Assembly.LoadFrom at all. The framework should dynamically load that assembly if (and only if) and when it needs to.
COREAUDIOAPI.dll does not work on XP or earlier, because they cant handle MMDEVICE API (Device Enumeration). I dont know about Vista.
I want to use SFML with C# .NET. I've had to get SFML 2.0 since 1.6 apparently had some issues with AMD graphics cards. The issue is that the constructor of SFML.Window.Window enters an infinite loop.
My code:
using SFML;
using SFML.Window;
using SFML.Graphics;
namespace SFML
{
class Program
{
static void Main(string[] args)
{
SFML.Window.Window window = new SFML.Window.Window(new VideoMode(800, 600), "Test widow");
}
}
}
It seems like nobody else on the internet has this issue, and I've tried it on another computer with the same result. Any help will be extremely appreciated.
Not sure you're creating the Window appropriately. Look at the examples from the Github source. If you're doing OpenGL, you'd use RenderWindow for instantiating your window object:
https://github.com/SFML/SFML.Net/blob/master/examples/opengl/OpenGL.cs
For 2D windows:
https://github.com/SFML/SFML.Net/blob/master/examples/window/Window.cs
Also note the inclusion of Tao bindings in those examples.