After two year, the 99% of email that I received were about the .net environment, particularly about how to interface a VB.Net program with Snap7.
So, although I’m not a big .net expert, I decided to write two lines about interfacing it with Snap7. (.net experts please forgive my inaccuracies).
I want to highlight that the problems found interfacing VB.NET with Snap7 are not strictly related to Snap7 but are the same for all Win32/Win64 binary DLLs.
So, if the mechanism is not completely clear after these (poor) lines, I suggest you to visit MSDN site, not all the functions are covered by the .net framework and in future you would need to interface other binary DLLs.
Thanks to the release of Visual Studio Community 2013 (free downloadable) there is no need to have different compilers (VB and C#). From this release you can compile with it all .net demos including VB_Mixed which contains the C# code of snap7.net.cs.
From this release you will find two solutions, one for console demos and one for winform demos.
You don’t need to use dotnet.bat anymore.
Ø .NET programs are called “managed”, this means that they are not executed directly by the CPU but, once compiled into CIL (an intermediate code) there is an interpreter, the CLR, that executes them.
Ø Snap7.dll is a binary library, it’s
executed (i.e. its functions are called) directly by the CPU.
If you compile Snap7 under Windows or Linux x86, it will contain Intel/AMD machine code, if you compile it into a Raspberry, it will contain ARMHF V6 machine code, and so on..
This sadly means that you cannot link directly Snap7 with your .net program. I.e. there is no menu item in Visual Studio that allows you to directly import snap7.dll (and all other binary libraries).
To call binary functions (called sometime “plain c api” or “native functions”) from a .net program, the common language runtime provides Platform Invocation Services through referencing System.Runtime.InteropServices.
You don’t need to do this, the classes S7Client, S7Server and
S7Partner that you find into snap7.net.cs already contain all is needed to
interface your code with snap7.dll.
They are .net classes, so you can use them directly in your programs.
At this point we need to divide the path : VB and C# because there are some important differences.
Just add snap7.net.cs file to your project and the clause “using Snap7” into the files that reference a Snap7 class.
There are some demos for you : the console
examples (compatible with MONO) that you find into examples\dot.net and a WinForm example that you can open with Visual Studio Community 2013
Visual Studio 2010+ into examples\dot.net\WinForm\CSharp.
That’s all for you.
Unluckily for you, you cannot use directly snap7.net.cs in your program because it’s a c# source class library.
To be used, the wrapper must be compiled into a compiled class library, i.e. an “universal” .net library that can be loaded by any .net language.
You need of : snap7.net.dll
In spite of its extension, snap7.net.dll is not a windows DLL (like snap7.dll) but a class library. Thank Microsoft for the enlightening name ;)
So, in order to use the snap7 classes, you need to import snap7.net.dll referencing it into the project properties, otherwise the compiler does not know how to find them.
is VS2010 screen (the only that I have in English language) in any case VS2012
and VS2013 screens are exactly the same.
Select Project properties -> References ->Add…->Browse and select snap7.net.dll
The compiler now is aware that a namespace called Snap7 can be used.
The last step is to reference the namespace into your source code.
This is quite simple, just add Imports Snap7 in your source code as in figure.
Now you are ready to use the S7Client class after having declared it :
Dim Client As Snap7.S7Client
From 1.4.0 use VB_Mixed as template to compile snap7.net.cs with your VB application.
But unluckily for you, this is still not the end.. The
compiled class library, within certain limits,
must match the framework and the architecture of your program, it could
happen that the copy that you find into the Snap7 package is refused by the
compiler. Please don’t email me, but learn
how to recompile it yourself, it’s very simple ;) To compile snap7.net.cs you need of
a C# compiler. There are two scenarios: 1.
You have Visual Studio Professional
(at least) 2.
You have Visual Studio Express (the
VB compiler). Scenario 1 – You have two choice: ·
Open the solution Snap7.sln from
examples\WinForm.net\BuildSnap7Assembly\ set the properties that you need
(architecture, framework etc..) then build the project. Copy snap7.net.dll from bin\Debug (or bin\Release)
into your project folder. ·
Create a mixed solution (see the
solution into \VB_Mixed) : one project is your VB
application, the other is the C# assembly.
The advantage is that you can change “onfly” the properties and rebuild the whole solution. Once you decided the framework and the architecture you can remove it from the project.
2 : You
need to download and install Visual Studio Express (C# compiler), maybe into
another PC or into a Virtual machine then follow the first choice
\VB and VB_Mixed you will find a small WinForm example ready to run.
(For both VB and C# users)
The 1.4.0 demos are now created with VS2013 and already contain both platforms (x86 and x64) and both snap7.dll into the related bin folders.
With Visual Studio you can produce
both 32 and 64 bit programs but there is no compiler #IF that can help us,
sometime this is decided at runtime. The binary libraries (luckily)
don't have the same freedom : they are 32 xor 64 bit. This mean that you could get an
error about a wrong dll format. For 32 bit executables
you need to use snap7.dll from \release\windows\Win32 For 64 bit executables
you need to use snap7.dll from \release\windows\Win64 snap7.dll must be copied into the same
folder of your compiled application (into
\bin\Debug or bin\Release to understand). The
demos that you find into \examples\WinForm.net were purposely created with
Visual Studio 2010. So you can load them with VS2010, VS2012, VS2013. The Snap7.dll inside is a 32 bit library, you need to replace it, as
said, if you compile your application for x64 or AnyCpu
and your program runs into a 64 bit OS. If you
are using VS2008 you can download an Express edition of VS2013 then copy and
paste the code.
Please don’t ask me to do this for you.
From 1.4.0 release all native types are supported (including extended S71200/1500 types). Please refer to the Client demo
Now, just a real example of how to read a S7 struct from a PLC using the new helper class (S7) in C# and VB.
Let’s suppose that we make a leak test on an automotive component and that we want to acquire the result of this test.
The data of this test consists of some values (Component serial number, Leak Value etc..) stored in DB 100 as in figure.
Every time a component is tested this struct is filled by the PLC and we want to read it into a .NET struct, picking the fields and adjusting their byte-order (the PLC is Big-Endian, the PC is Little-Endian, so the bytes must be reversed).
This is our C# sample struct:
public struct ComponentResult
public String SerialNumber; // Component Serial Number
public int TestResult; // Result code – 0:Unknown, 1:Good, 2:Scrap
public single LeakDetected; // Leak value [cc/min]
public DateTime TestDateTime; // Test Timestamp
And this is the C# sample function that fills the struct. Notice that the outcome of any Client function call should be checked, here is skipped for brevity.
private ComponentResult LeakResult()
ComponentResult Result = new ComponentResult();
byte Buffer = new byte;
// Reads the buffer.
Client.DBRead(100, 0, 26, Buffer);
// Extracts the fields and inserts them into the struct
Result.SerialNumber = S7.GetCharsAt(Buffer, 0, 12);
Result.TestResult = S7.GetIntAt(Buffer, 12);
Result.LeakDetected = S7.GetRealAt(Buffer, 14);
Result.TestDateTime = S7.GetDateTimeAt(Buffer, 18);
Same as above in VB.NET
Private Structure ComponentResult
Public SerialNumber As String ' Component Serial Number
Public TestResult As Integer ' Result code 0:Unknown, 1:Good, 2:Scrap
Public LeakDetected As Double ' Leak value [cc/min]
Public TestDateTime As DateTime ' Test Timestamp
…and the function
Private Function LeakResult() As ComponentResult
Dim Result As ComponentResult
Dim Buffer(26) As Byte
Client.DBRead(100, 0, 26, Buffer)
Result.SerialNumber = S7.GetCharsAt(Buffer, 0, 12)
Result.TestResult = S7.GetIntAt(Buffer, 12)
Result.LeakDetected = S7.GetRealAt(Buffer, 14)
Result.TestDateTime = S7.GetDateTimeAt(Buffer, 18)
Finally, if you put a button and 4 labels in the form of VB demo, with this simple code you can test the mechanism.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim CR As ComponentResult = LeakResult()
Label1.Text = CR.SerialNumber ' It’s already a string
Label2.Text = System.Convert.ToString(CR.TestResult)
Label3.Text = System.Convert.ToString(CR.LeakDetected)
Label4.Text = System.Convert.ToString(CR.TestDateTime)