.NET Environment

 

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.

1.4.0

 

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.

 

Key concepts

 

Ø  .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.

C#

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.


 

VB

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.

 

Remarks

(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.

 

Example

 

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