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.
This
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.
Scenario
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
(BuildSnap7Assembly).
Into
\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[26]; //
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); return Result; } |
Same as above in VB.NET
The struct
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 End Structure |
…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) Return Result End Function |
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) End Sub |