Posts Tagged ‘Programming’

How about using ActiveX-controls in 64-bit zenon?

Wednesday, June 12th, 2013

64-bitIn some projects ActiveX-controls are used for custom GUI objects rather than creating them from standard zenon screen elements. Usually these ActiveX-controls are written in VB6 or C++. All these ActiveX-controls are 32-bit components and cannot be used in 64-bit applications out of the box. But under some circumstances it takes only some simple modifications to make them run in 64-bit aswell.

Background

ActiveX-controls in principle are DLLs with a standardized COM interface. So they are in-process COM-servers and are loaded directly into the host application process. Now, fact is that generally a 64-bit application is only able to load 64-bit DLLs. So 32-bit ActiveX-controls cannot be loaded by 64-bit zenon. To make this possible, the 32-bit ActiveX-control must be ported and compiled into a 64-bit DLL.

Bad news

Unfortunately the previous VB6 is not able to generate 64-bit output. So there is no way of bringing a VB6 ActiveX-control into 64-bit zenon except by rewriting it completely in C++ e.g. If it is absolutely necessary to keep them, one must stick to 32-bit zenon even if the used platform would offer using the 64-bit version. The same is true of course, if you do not have the source code at all and only have the 32-bit binaries.

Good news

If your ActiveX is written in C++ and you have the source code, you can easily introduce a second x64 configuration into the project and compile a 64-bit AcitveX-control then. Usually there are no or only minor changes necessary in your source code that make it run again in 64-bit. And please don’t forget to also register 64-bit ActiveX with regsvr32 afterwards. 32-bit and 64-bit ActiveX-controls are registerd in different registry paths, even if they have “the same control” with the same CLSID and name.

How to create an event driven report with zenon Analyzer using a VSTA macro in the zenon runtime and send it optionally as an email attachment with message control

Wednesday, May 22nd, 2013

zenon Analyzer not only offers manual report generation, it enables the creation of reports based on schedules and can generate them event-driven. The event-driven report generation is able to create reports based on external events, such as the end of a lot production. In this case, the zenon Runtime works hand-in-hand with the zenon Analyzer.

General description:

zenon AnalyzerThis functionality needs to be implemented in zenon using a VSTA macro. The triggering event starts this macro which sets the parameters like report template name, rendering format (e.g. pdf, jpg, html, …), time filters, event classes, … to the zenon Analyzer, using the Reporting Services Web service interface. The zenon Analyzer processes the report and returns the rendered report to the VSTA macro of the runtime for further processing. The VSTA macro can store the report in a file share or send it by message control as an email attachment.

Detailed description:

1. Information collection:

First the required parameters, which are needed to call up the VSTA macro, are determined. Two different

cialis order

types of parameters exist. Those which are necessary for the report itself and those which give additional information and control the report generation.

Report parameter:
In order to be sure about the report parameters, we suggest to open the report in the Microsoft SQL Server Report Builder 3.0 and check them in the parameters section.

Other parameters;
Are rendering methods and project name.

2. VSTA programming:

Creating a Web service reference:
To create the required reference you can use the VSTA-Editor or the wsdl.exe (Web Services Description Language), provided by several Microsoft SDKs (.NET SDK, Windows SDK, Visual Studio, …)

C#-code:
It is important that the macro is running in its own thread, otherwise the runtime will be blocked and a deadlock is created!

In the C#-code the following parameters are passed to the zenon Analyzer:

    • rendering method
    • project
    • report execution parameters (e.g. time filters, …)

Now the VSTA macro waits for the report to be processed from the zenon Analyzer and be returned to the runtime. The macro now can save the report under any name on the hard drive or send it as an email extension with message control.

3. Finally the C#-code needs to be saved as a ProjectAddin.

 

Possible usages:

  • manual activation with a button in the runtime
  • automatic activation for violated limits
  • automatic activation using scheduler or Production & Facility Scheduler
  • automatic activation using a time control function

 

Although the C#-code has a limited length, it would exceed the scope of this blog.
For implementation comprehensive documentation, including code samples, is available.

 

Visual Basic for Applications version 7.1, 32Bit and 64 Bit

Wednesday, June 27th, 2012

Introduction

The next version of zenon will be available in 32 and 64 bit. Therefore the included Visual Basic for Applications package will be upgraded from the 6.5 (32Bit) to 7.1 (32 and 64Bit). When using the 32Bit version of zenon none of the existing code needs to be modified, workspace and runtime projects can stay the way they are. But to take full advantage of the available memory and hardware the 64 Bit version is obviously the better choice.

Changes

When using the 64 Bit version of zenon, VBA 7.1 will also run in 64 Bit mode. To differentiate between the 32 and 64 Bit version quite a few keywords, defines and declarations have been introduced to VBA.

Any existing API declarations have to be modified in order to be used in 64 Bit mode. For example the API-function “FindWindow” (which can be used to find a window by use of its class name and window name) used to be defined like this in a 32Bit VBA project:

Private DeclareFunction FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Whereas the 64 Bit version of this declaration needs to be:

Private Declare PtrSafe Function FindWindow
Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

NOTE: The 64 Bit declaration will work for the 32 Bit version mode of VBA 7.1 as well.
Since Microsoft currently does not include a 64Bit version of the “Microsoft Common Controls”, objects from this package cannot be used in the 64 Bit mode. This  package includes the CommonDialog-Controls often used for “File-Open” and “Color-Picking”-Dialogs.

Additions and mixing

Microsoft introduced two new conditional compilation constants: “VBA7” and “Win64”. The VBA7 constant can be used to determine whether the project is running under VBA7 or on an older version. This constant is useful for backwards compatibility, and prevents the requirement for separate
“pre-7” and “7”-versions of custom created classes.

#If VBA7 Then
'Use VBA7 functionality
#Else
'Stick to old VBA solution
#End If

The Win64 constant enables a separation between the 32 and 64 bit version of VBA and can be used to ensure that code is only executed when VBA runs in the correct mode.

How to adapt a VSTA-Form to appear as a VSTA-Wizard in the Wizard dialog (VB.Net)

Wednesday, May 16th, 2012

Introduction Although most .Net solution are developed using c#, in some cases porting existing old code (from vba) to VB.Net might be more efficient than starting from scratch in c#. This blog entry explains which methods and functions are to be implemented in order to have a VB.Net Wizard displayed in the zenon Wizard dialog which pops up when creating a new project. Similar, yet different in small details

cialis no prescription

compared to the c# scenario. Integrating VSTA-Code into the wizard dialog In order for VSTA-C ode to be available in the wizard dialog the automation code needs to be contained (implemented) into a Windows-Form. Additionally the Form-Class needs to

popular pills online

implement the following set of static functions (all without parameters): Public Shared Function GetWizardName() As String Return the name of the wizard, displayed as “Name of the wizard” in the wizard dialog. Public Shared Function GetWizardInfo()

purchase viagra

As String Return a description of the wizard, shown as “A more detailed description of the wizard.” in the wizard dialog. Public Shared Function GetWizardCategory() As String Returns the category of the wizard and is displayed as “Wizard category” in the wizard dialog. Note: An existing category can be used here. And a VSTA and a VBA wizard can reside in the same category. Public Shared Function IsZenOnWizard() As Boolean This function determines whether the wizard should appear in the dialog. It offers the possibility to stop a wizard from appearing without having to delete all functions or removing it from the Addin. Public Shared Function GetWizardVersion() As Integer This function returns the version number of the wizard, indicated next to the wizard information. Public Sub StartWizard() This method is called when the wizard has been selected in the wizard dialog and confirmed with “OK”. NOTE: It’s not allowed to have any functions with the same name inside of the wizard class, not even if their return type of parameter count is different from the “Wizard-Functions”.

How to adapt a VSTA-Form to appear as a VSTA-Wizard in the Wizard dialog (C#)

Thursday, March 1st, 2012

Introduction

In average day working with the zenon Editor quite a few actions are required for each project. Actions like creating a default set of users, common drivers, default templates, etc. can be time consuming. Obviously these actions can be replaced and automated by use of VSTA-code in

cialis without prescription

the editor. But if

price of viagra

these actions are to be performed for each new project, it would be more efficient if the actions could be triggered in a more comfortable way: By use of the integrated Wizard dialog which pops up when creating a new project in zenon.

Integrating VSTA-Code into the wizard dialog

In order for VSTA-Code to be available in the wizard dialog the automation code

cheap viagra

needs to be contained (implemented) into a Windows-Form. Additionally the Form needs to implement the following set of static functions (all without parameters):

static public string GetWizardName ()
Return the name of the wizard, displayed as “Name of the wizard” in the wizard dialog.

static public string GetWizardInfo ()
Return a description of the wizard, shown as “A more detailed description of the wizard.” in the wizard dialog.

static public string GetWizardCategory ()
Returns the category of the wizard, shown as “Wizard category” in the wizard dialog.
Note: An existing category can be used here. And a VSTA and a VBA wizard can reside in the same category.

static public bool IsZenOnWizard ()
This function determines whether the wizard should appear in the dialog. It offers the possibility to stop a wizard from appearing without having to delete all functions or removing it from the Addin.

static public int GetWizardVersion ()
This function returns the version number of the wizard, indicated next to the wizard information.

NOTE: It’s not allowed to have any functions with the same name inside of the wizard class, not even if their return type of parameter count is different from the “Wizard-Functions”. If all functions are correctly implemented and the Addin has been successfully compiled, the Form will appear in the wizard dialog.

Link VBA with Straton WB by using StratOnCom interface

Tuesday, January 3rd, 2012

Link VBA with straton WB by using StratOnCom interface

This topic describes how to configure the VBA editor

cheap cialis

to connect with the Straton Workbench and how to use the StratOnCom interface. First of all you need a Straton Workbench Project. Create one.

Open the VBA Editor and select “myWorkspace” and click on the meneu “Extras/References” and set the “StratOnCom” active.

vba_with_straton_stratoncom_interface

Now you can use the Straton Com Interface for your VBA Project

This code sample shows us how to initialize the com interface for your project:

Attention! The VBA access to the straton workbench just works in the zenon workpace (zenon Editor)!

Public Sub

comprare viagra

StratonTest()


‘Create a new instanz on the SratOnCom Object
Dim myStraton As New StratOnCom.Project
Dim myPath As String

‘Path to the Straton Path
myPath = “C:\ProgramData\COPA-DATA\SQL\ff8cdbaa-47f3-44e8-bd33-1c582fd4cadc\FILES\straton\Project”

‘Set the entry point to your straton project
myStraton.ProjectPath = myPath

‘Show straton path again
Debug.Print myStraton.ProjectPath
‘Count all my Straton Programs
Debug.Print myStraton.Programs.Count
‘Show the name of the first program
Debug.Print myStraton.Programs.Item(0).Name

‘Show the first global Variable
Debug.Print myStraton.GlobalVariables.Item(0).Name

‘Show some details of the first retain variable
Debug.Print myStraton.RetainVariables.Item(0).Name
Debug.Print myStraton.RetainVariables.Item(0).Comment
Debug.Print myStraton.RetainVariables.Item(0).EmbedSymbol
Debug.Print myStraton.RetainVariables.Item(0).InitValue
Debug.Print myStraton.RetainVariables.Item(0).Tag

 

End Sub

 

The following list shows the objects available

generic viagra

for both VBA and VSTA.

– StratonCom
– Project
– GlobalVariables
– Variables
– Variable
– VarProps
– VarProperty
– RetainVariables
– Variables
– Variable
– VarProps
– VarProperty
– Programs
– Variables
– Variable
– VarProps
– VarProperty
– ProgramContent
– ProgramObjects
– GraphicalObject
– ProgramLines
– LineObject

Move free definable screens via VSTA

Friday, December 16th, 2011

Introduction

When you try to move free defineable screens via the mouse, you will figure out that those screens have no titlebar where you can move it. Can I move screens without title bar in zenon? A quick answer YES. You can achieve this functionality for example via VSTA.

How to move the window

The window can easily be moved via VSTA by using the IDynPicture.Move Method.

void Move(int Left, int Top, int Width, int Height)

Please download the zenon project backup for further investigation.

Processing zenon variable information in a VSTA thread using a thread safe queue

Tuesday, November 29th, 2011

Introduction

There is often the need to process zenon data (e.g. variable values, etc.) in VSTA without influencing time critical functions of the zenon Runtime itself. With VSTA/.NET and the usage of multithreading you have new possibilities which you did not have with VBA before (where the Runtime was blocked when executing time consuming VBA function).

Nevertheless when using multithreading you still have to keep in mind that objects from the zenon object model must be only accessed from one thread at a given time.

The following example will show how to gather zenon variable information in a zenon event, write this information into a custom object and how to put these objects in a thread safe queue. The queue itself is then be read out by the use of a worker thread.

Class ThisProject

In the class ThisProject you need to create an Online Container and a queue for the custom variable items.

//Online Container

zenOn.IOnlineVariable MyOnlineContainer = null;

 

//Queue for custom variable objects

ZenonQueue<Variable> Queue = null;

In ThisProject_Startup, the event handlers for Project Active/Inactive are created.

privatevoid ThisProject_Startup(object sender, EventArgs e)

{

     //Create Eventhandlers for ThisProject Active/Inactive

     this.Active += new zenOn.ActiveEventHandler(ThisProject_Active);

     this.Inactive += new zenOn.InactiveEventHandler(ThisProject_Inactive);     

}

In ThisProject_Active, the Online Container and the queue are initialized.

void ThisProject_Active()

{

     //Create a new queue of custom variable objects

     Queue = newZenonQueue<Variable>();

 

     //Create Online Container, add two variables, create event handler

     MyOnlineContainer =    
     t
his.OnlineVariables().CreateOnlineVariables(“OnlineVar”);
     MyOnlineContainer.Add(
“var1”);

     MyOnlineContainer.Add(“var2”);

     MyOnlineContainer.Define();

     MyOnlineContainer.VariableChange += new
     zenOn.
VariableChangeEventHandler(MyOnlineContainer_VariableChange);

}

The uninitialization is done in the ThisProject_Inactive/ThisProject_Shutdown.

 

void ThisProject_Inactive()

{    

     //Undefine,defererence Online Container, release event handler

     MyOnlineContainer.Undefine();

     MyOnlineContainer.VariableChange -= new
     zenOn.
VariableChangeEventHandler(MyOnlineContainer_VariableChange);

     MyOnlineContainer = null;



     //Dereference the queue

     Queue = null;         

}

 

privatevoid ThisProject_Shutdown(object sender, EventArgs e)

{

     //Release event handlers

     this.Active -= new zenOn.ActiveEventHandler(ThisProject_Active);

     this.Inactive -= new zenOn.InactiveEventHandler(ThisProject_Inactive);

}

 

In the Variable Change Event of the Online Container, a custom variable object containing information of a zenon variable is created and put in the queue.

void MyOnlineContainer_VariableChange(zenOn.IVariable obVar)

{

     //Create a new custom variable object with the information (name and
     value) of a (numerical) zenon variable                 

     Queue.Enqueue(newVariable(obVar.Name, (double)obVar.get_Value(0)));

}

 

The items of the queue are taken out from the queue and written to the Immediate Window of the VSTA Editor using a zenon VSTA Macro and a thread.

publicvoid Macro_DeQueue()

{

     //Create a thread which dequeues all items from the queue and writes the
     name and value into the Immediate Window

 

     Thread consumerThread = newThread(() =>

     {

          while (Queue.GetCount() > 0)

          {

               Variable var = Queue.Dequeue();

               System.Diagnostics.Debug.Print(var._name + “, “ +    
               var._value.ToString());

          }

     });

     consumerThread.Start();

}

Helper Classes

The class Variable.cs is the class for our custom variable object.
The class ZenonQueue.cs is the class for our thread safe queue containing the custom variable objects.
For more information please have a look on the source code.

Download zip file!

DependencyProperties for zenon WPF controls

Wednesday, September 28th, 2011

Introduction:

When you begin to develop WPF controls for zenon, you will soon stumble across DependencyProperties. What are dependency properties? The quick definition from the MSDN documentation says that a dependency property is a "property that is backed by the WPF property system." They are quite similar to normal .NET properties, but the concept behind DependencyProperties is much more

online pharmacy

complex and powerful. It gives you a bunch of infrastructure to do all things you often want to do with a normal property: validate it, coerce it into a proper range, give out change notifications and a number of other aspects. A normal .NET property is read directly from a private member in your class, whereas the value of a DependencyProperty is resolved dynamically when calling the GetValue() method that is inherited from DependencyObject.

Advantages of DependencyProperties:

  • Reduce memory footprint
  • Value inheritance
  • Change notification
  • Value validation

How to create a DependencyProperty:

To create a DependencyProperty, you have simply to add a static field of type DepdencyProperty to your type and call DependencyProperty.Register() to create an instance of a dependency property. The naming convention of DependencyProperties fields is important. The name of the fields is always the name of the property, with the suffix Property appended. To make it accessible like a normal .NET property you need to append a property wrapper. This wrapper does nothing else than internally getting and setting the value by using the GetValue() and SetValue()

usa pharmacy

Methods inherited from DependencyObject and passing the DependencyProperty as key. HINT: If you are using Visual Studio, you can type propdp and hit 2x TAB to create a dependency property.

// Dependency Property
public static readonly DependencyProperty LastNameProperty =
     DependencyProperty.Register( "LastName", typeof(String),
     typeof(MyControl));
 
// .NET Property wrapper
public String LastName
{
    get { return (String)GetValue(LastNameProperty); }
    set { SetValue(LastNameProperty, value); }
}

Each DependencyProperty provides callbacks for change notification, value coercion and validation. These callbacks are easily registered on the dependency property with

cheap generic cialis

FrameworkPropertyMetadata.

// FrameworkPropertyMetadata
new FrameworkPropertyMetadata( "zenon",
    OnCurrentTimePropertyChanged,  
    OnCoerceCurrentTimeProperty,
    OnValidateCurrentTimeProperty);

Correct releasing zenon Objects in VSTA

Friday, July 8th, 2011

Problem:
When a Macro with a zenon Object zenOn.IRecipes is set to null execute thrice the zenon RT can be crash.
Usually zenon Interface Objects (e.g. IVariables, IAlarms …) returns a pointer of the zenon-COM-Object but in the case of the IRecipes the zenon Interface returns a copy of the Object. If you set any zenon Interface Objects = null the pointer will released. In the case of the copy, the copy will exist until the Garbage Collector has time to release the Object. This depends on the CPU-Capacity and other .NET internal things. If the Macro is called again and the Garbage Collector doesn’t have the time to release the object, the Object will have a not valid condition and zenon RT will crash.

Example:

public void MacrocoloreSuVariabile()

{

zenOn.IRecipes projectRecipes;

zenOn.IRecipe ricetta;

zenOn.IRecipeValue item;

try

{

projectRecipes = this.Recipes();

if (projectRecipes != null)

{

ricetta = projectRecipes.Item("RICETTA_UNIFILARE");

if (ricetta != null)

{

for (int r = 0; r < ricetta.Count; r++)

{

item = ricetta.Item(r);

if (item != null)

{

item.Value = Convert.ToDouble(r);

item = null;

}

}

ricetta.ExecuteValues();

ricetta = null;

}

//This will cause the crash
projectRecipes = null;

}

}

catch (Exception ex)

{

Debug.Print("ERROR : " + ex.Message.ToString() + " " + ex.Source.ToString());

}

}

public void MacrocoloreSuVariabile()

{

zenOn.IRecipes projectRecipes;

zenOn.IRecipe ricetta;

zenOn.IRecipeValue item;

try

{

projectRecipes = this.Recipes();

if (projectRecipes != null)

{

ricetta = projectRecipes.Item("RICETTA_UNIFILARE");

if (ricetta != null)

{

for (int r = 0; r < ricetta.Count; r++)

{

item = ricetta.Item(r);

if (item != null)

{

item.Value = Convert.ToDouble(r);

item = null;

}

}

ricetta.ExecuteValues();

ricetta = null;

}

projectRecipes = null;

}

//Usually zenon Interface Objects (e.g. IVariables, IAlarms ...) returns a
//pointer of the zenon-COM-Object but in the case

//of the IRecipes the zenon Interface returns a copy of the Object.

//If you set any zenon Interface Objects = null the pointer will released.
//In the case of the copy, the copy will exist until

//the Garbage Collector have time to release the Object. This depends on
//the CPU-Capacity and other .NET internal things.

//In this case you must call the Garbage Collector manually to release the
//Object correctly.

GC.Collect();

GC.WaitForPendingFinalizers();

GC.Collect();

}

catch (Exception ex)

{

Debug.Print("ERROR : " + ex.Message.ToString() + " " + ex.Source.ToString());

}

}