Archiv der Kategorie: Software Technical View

Für Programmers: Firebird und Microsoft SQL Server nutzen

Das ist jetzt eine Betrachtung für C# und DOT NET Anwendungsprogrammierer! Der eine oder andere hat es ja schon ausführlich diskutiert: im Rahmen unserer Produktpflege werden wir die Lagerverwaltung AE WWS Lite (Link hier) zukünftig mit zwei SQL Clients versehewn:

  • Für Microsoft SQL Server (incl der kostenfreien Microsoft SQL Server Express Versionen)
  • als auch für Firebird SQL Server. LINK_HIER.

Technisch gesehen benötigt die Software daher zwei SQL Clients: für Microsoft SQL Server und die Firebird DOT NET Bibliothek, beide jeweils als DLL Datei im Programmverzeichnis.

Im ersten Workaround gehen wir davon aus, dass die Software jeweils nur für einen der Clients compiliert wird. Natürlich wäre es problemlos möglich, beide Clients zum gleichen Zeitpunkt zu integrieren – jedoch würde hierbei das Anwendungsprogramm u.E. nach unnötig aufgebläht werden, so dass wir erst mal mit der Trennung auf Compilerebene arbeiten.

De facto sind bereits heute alle SQL Aktivitäten in einer eigenen SQL Klasse ausgelagert. Das hat den Vorteil dass für die Umstellung nur eine Datei angepasst werden muss.

Datei: SQL Class


Preprocessor Compiler Definition

Am Anfang: Preprocessor Defintion für den Compiler. Via Copy und Paste wird hier  direkt vor dem Compilieren wahlweise Firebird oder MSSQL eingetragen. Im Beispiel aktuell wird der Code auf Firebird compiliert:

// Firebird OR MSSQL
#define Firebird

Weil uns Fragen erreichten:

Exkurs: Was macht der Preprocessor im Compiler

Mit dem Preprocessor kann man den Compiler beim Übersetzen der Anwendung dazu bringen, gewisse Teile des Codes zu ignorieren oder zu verwenden. Erreicht wird dieses in der Regel durch

#if (AUSDRUCK)

#elif (AUSDRUCK)

#endif

Formulierungen. Wenn der Compiler findet dass AUSDRUCK wahr (TRUE) ist, wird der eingeschlossene Code compiliert. Ansonsten ignoriert. Dieses Verhalten ist besonders dann von Bedeutung, wenn man seinen Code für bestimmte Bedingungen übersetzen will, z.B. nur für eine bestimmte Sprache oder wie in diesem Fall nur für einen bestimmten SQL Client – und trotzdem in allen Fällen mit dem gleichen Sourcecode in einem Projekt arbeiten möchte.

Und natürlich kann man den Preprocessor auch durch jederzeit eine if Bedingung im Code ersetzen. Dann werden alle Optionen compiliert und man eröffnet dem Anwender die Möglichkeit, beide Teile zu verwenden. (Hier muss man dann natürlich eine Anwendungssteuerung für den Benutzer programmieren, dass dieser mittels Auswahlfeld zur Laufzeit bestimmen kann, welchen Teil er haben möchte. Der Nachteil dieser Kombination: Da immer alles compiliert wurde, wird das Programm hierdurch größer, Insofern sind

#if (DEUTSCH)

hier nur der deutsche Teil

#endif

und 

if (DEUTSCH == TRUE) { deutscher Teil; }

im Prinzip gleichwertig. Allerdings kann man den #if / #endif Teil dazu verwenden dass der Compiler den Inhalt ignoriert = das Programm kürzer macht. Hier gilt es also zu überlegen, ob dem Anwender alle Bedingungen gleichermaßen zur Verfügung stehen müssen, oder ob man mittels Preprocessor Compilerschalter bestimmten Code einfach ausblendet.

 


SQL DLLs einbinden, für Firebird SQL oder Microsoft SQL

Die Einbindung der verschiedenen DLL für die SQL Clients. Es wird nur derjenige SQL Client eingebunden, der im Compiler aktiviert wurde.

#if (MSSQL)
using System.Data.SqlClient;
#endif

#if (Firebird)
using FirebirdSql.Data.FirebirdClient;
#endif

SQL Datensatz schreiben

Beispiel der Routine die einen Datensatz an den SQL Server schreibt – mit Unterstützung SQL Client Microsoft SQL Server und Firebird:

// Nur aktivieren wenn SQL aktiv!

if (Form1.OpenMode != (int)OpenModeValue.SQL) { return;}

// Das SQL Kommando. In diesem Fall haben wir den Namen der SQL Tabelle als Parameter in Form1 definiert. Schöner, aber für unser Beispiel etwas unübersichtlicher, ist es natürlich den Tabellennamen beim Aufruf der Sub zu übergeben.

string cmdstring = "INSERT INTO " + Form1.SQLTable_Data + " (Idx, ArtNr, ArtText, MaterialGroup) " + "VALUES (@Idx, @ArtNr, @ArtText, @MaterialGroup )";

// Die Befehlsfolge für Microsoft SQL

#if (MSSQL)
SqlConnection connection = new SqlConnection(Form1.SQLConnectionstringNeu);
connection.Open();
SqlCommand command = new SqlCommand(cmdstring, connection);
#endif

// Die Befehlsfolge für Firebird SQL

#if (Firebird)
FirebirdSql.Data.FirebirdClient.FbConnection connection = new FirebirdSql.Data.FirebirdClient.FbConnection(Form1.SQLConnectionstringNeu);
connection.Open();
FirebirdSql.Data.FirebirdClient.FbCommand command = new FirebirdSql.Data.FirebirdClient.FbCommand(cmdstring, connection);
#endif

// Und hier die Befehle für beide SQL Clients: Daten füllen und schreiben. Da die Befehle identisch sind, ist eine Trennung nicht mehr notwendig. Wer mag, kann diese Befehle noch in ein “try … catch (exception)” kapseln und sich so vor ungewollten Ausnahmen schützen.

command.Parameters.AddWithValue("@Idx", myAdv["Idx"]);
command.Parameters.AddWithValue("@ArtNr", myAdv["ArtNr"]);
command.Parameters.AddWithValue("@ArtText", myAdv["ArtText"]);
command.Parameters.AddWithValue("@MaterialGroup", myAdv["MaterialGroup"]);

command.ExecuteNonQuery();

// Auf gar keinen Fall Close vergessen!!! Dateien oder Datenbanken nach Verwendung NICHT zu schließen ist ein Kapitalverbrechen für jeden Programmierer und sollte in Fleisch und Blut übergehen.

connection.Close()

SQL Datensätze lesen

Ähnlich aufgebaut wenn alle Datensätze aus einer Tabelle gelesen werden sollen. Auf die erläuternden Kommentare verzichten wir hier und zeigen gleich die ganze Routine:

public bool SQLReadTable(string mySQLTable, DataTable myDT1)
{
//=======================================================
//Ganze Tabelle lesen. Firebird und MSSQL
//Return: TRUE wenn alles OK, FALSE im Fehlerfall
//=======================================================

//Die Datatable wird vor dem Lesen geloescht
myDT1.Clear();

#if (MSSQL)
SqlDataAdapter locAdapter = new SqlDataAdapter("Select * from " + mySQLTable, Form1.SQLConnectionstringNeu);
#endif
#if (Firebird)
FirebirdSql.Data.FirebirdClient.FbDataAdapter locAdapter = new FirebirdSql.Data.FirebirdClient.FbDataAdapter("Select * from " + mySQLTable, Form1.SQLConnectionstringNeu);
#endif

try
{
locAdapter.Fill(myDT1);
}
catch (Exception ex)
{
//Sollte es zu einer Ausnahme gekommen sein, greifen wir die hier ab!
MessageBox.Show("#1610101100 ERROR.\n\n" + ex.Message, "SQL ERROR: sqlreadtable", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}

return true;

} //end sub



 

Visual Basic Dot Net und C#

PC / Windows Programmierung in Visual Basic VB DOT Net oder C# (unter DOT Net)?

Inzwischen dürfte es sich herum gesprochen haben: Das Visual Basic VB DOT hat nichts mehr gemein mit dem alten Visual Basic VB6! Zwischen VB DOT NET und VB6 liegen Welten – und die Sache mit der Objektorientierten Programmierung. Dafür verwendet VB DOT NET nun (welche Überraschung) das Microsoft DOT NET Framework – genauso wie C#.

Die Unterschiede beider Sprachen liegen jetzt irgendwo in der Syntax und in rudimentären Eigenheiten – wobei nicht verschwiegen werden soll, dass für die eine oder andere Anwendung gerade das Rudimentäre lebenswichtig sein kann.

Doch in unserem Hause, Standard Windows Programmierung, manchmal auch etwas Linux, SQL Server, Datenbankanwendungen, Embedded Anwendungen, sehen wir die Verwendung beider Sprachen bisher als weitgehend gleichwertig an. Der VB DOT NET Programmierer coded seine Aufgaben in seiner Sprache, die C# Fraktion wuselt sich durch Kommandozeilen, die mit ; abgeschlossen werden. Und alle zusammen verwenden als Entwicklungsumgebung Microsoft Visual Studio, tauschen untereinander erstellte Codeteile aus und können sich sogar an einen Tisch sitzend eine Pizza teilen.

Etwas Bedeutung erlangt das Wörtchen BISHER im obigen Absatz. Bisher hat Microsoft Visualität Basic und C# gleichwertig entwickelt – zumindest aus Entwicklersicht. Doch im Februar 2017 tauchten in Microsoft Entwickler Blogs vermehrt Einträge auf, die aufhorchen lassen. Sinngemäß, um ein paar Kerngedanken aufzugreifen:

C# hat eine Entwicklergemeinde von einigen Millionen, VB DOT Et von einigen Hunderttausend…

Zukünftige Entwicklungen für Mobile und Cloud werden primär für C# voran getrieben…

Visual Basic sollte sich auf Einsteiger konzentrieren und schon alleine deswegen nicht mit allen zukünftigen Entwicklungen überfrachtet werden, die in C# auftauchen

Und natürlich: MS bleibt bei VB DOT NET und auch weiterhin bleibt Visual Basic DOT NET in der DOT NET Gemeinde ein Bürger erster Klasse. (“Citizen 1st class”)

Wir wissen nicht, wie das bei Microsoft läuft. Doch bei unserer heimischen Kanzlerin Fr. Dr. Merkel hat sich bereits seit Jahren so ein Gassenwitz breit gemacht: Spricht sie einem Mitglied ihres Kabinetts explizit “das Vertrauen aus” – so ist das der Beginn der Demission. Bereits wenige Wochen später ist die betreffende Person dann oftmals aus der Regierung verschwunden.

Für Interessierte hier einige Links zum Thema:

https://www.heise.de/developer/meldung/Visual-Basic-C-und-F-Microsoft-justiert-die-Programmiersprachen-Strategie-neu-3615374.html

www.infoworld.com/article/3167210/application-development/visual-basic-is-the-odd-man-out-in-the-new-net.html

https://visualstudiomagazine.com/articles/2017/06/13/visual-basic-future.aspx

Und natürlich auch die Vergleichstabelle zwischen VB Dot Net und C#:

https://www.codeproject.com/Articles/9978/Complete-Comparison-for-VB-NET-and-C

Problem: BindingSource.FIND funktioniert nicht, wenn Tabelle sich ändert

VB DOT NET, ab Visual Studio VS2005

Problem: Diese paar Zeilen ergeben Datenchaos, wenn sich die der BindingSource zugrunde liegende Liste ändert:

—————————————
dim SuchIndex as integer = -1
SuchIndex = Form1.BindingSource1.Find(“ArtNr”, Artikel)
if (SuchIndex > -1) {

Form1.BindingSource1.Position = SuchIndex
advStamm = CType(Form1.BindingSource1.Current, DataRowView)

…. verarbeite Datensatz advStamm, Mengen addieren etc ….

}

—————————————

Alles funktioniert super, solange die Liste der BindingSource nach ArtNr sortiert ist.

Ist die Liste aber z.B. nach Menge sortiert und wird beim Verarbeiten eben diese Menge geändert, so kann sich auch die Reihenfolge des Datensatzes in der Liste ändern. Das bekommt bindingsource.find aber nicht mit – und liefert fleissig den alten SuchIndex Wert zurück. Kurzum: advStamm enthält NICHT den Datensatz mit der gesuchten ArtikelNummer! Wenn der nachfolgende Code dass nicht abprüft gibt es dramatischen Datensalat!

Einache Abhilfe des Problemes, bevor man sich eine eigene BindingSource.Find Methode bastelt:

With Form1.BindingSource1
.Sort = “ArtNr”
End With

an den Anfang setzen. Unbedingt sicherstellen, dass sich die Sortierung der Liste innerhalb der Verarbeitung nicht ändert!

 

 

Praktikumsbericht: Industrie Etikettendrucker

Untersucht haben wir den Etikettendrucker Marke TSC. Industrieausführung im Stahlblechgehäuse.

Wertigkeit: Super. Alles passt und macht einen hochwertigen Eindruck.

———————————

Dokumentation:

Haben wir nur in Englisch gefunden. Keine deutschen Benutzerdokumente. Das zumindest dürfte den Einsatz bei unseren Kunden erschweren. Oder unseren Supportaufwand.

———————————

Medienzuführung.

Auch hier sind Supportprobleme zu befüchten. Erwies sich für uns als kompliziert. In diversen Dokumnentationen sind zwar Bilder und Zeichnungen zu finden, jedoch an verschiedenen Stellen aber halt auch mit verschiedenen Informationsgehalten.

Was man unbedingt wissen sollte: 1) Exakte Etikettengröße (wird für Labeldesign benötigt) und 2) ob bei Farbrolle die beschichtete Seite außen oder innen angebracht ist. (Lieferschein lesen!).

Bis wir den Drucker dazu gebracht haben, das eingelegte Etiketenmedium zu akzeptieren, sich zu kalibrieren und einen Selbsttest zu drucken, verging so ein halber Tag. Überflüssig zu erwähnen, dass man nach dem Gesetz des Lebens immer an der falschen Stelle sucht… Für das allererste Etikettengefuddel sollte man also wohl besser etwas Zeit und Geduld mitbringen.

———————————

Inbetriebnahme 1:

Drucker hatte LAN Kabel UND USB Kabel dabei. Löblich! Anschluß Drucker via USB Druckertreiber von CD installiert. Knack. Zack. Lief problemlos. Drucker war dann unter Drucker sichtbar. Windows 7 64bit.

———————————

Inbetriebnahme 2:

zwei Utility Programe auf der CD. Genaue Verwendung erschloß sich uns nicht. Aber zumindest mit DiagTool_V163.exe lassen sich Kommandos an den Drucker übertragen. War eine längere Phase von Versuch und Irrtum, bis wir da was zustande bekommen haben. Aus unterschiedlicher Dokumentation haben wir uns dann folgenden Labelstring in TSPL (TSC Programming Language) zusammengebastelt:

SIZE 4,2
CLS
BARCODE 100,50,”128″,100,1,0,2,2,”1234567890″
BARCODE 100,200,”128″,100,1,0,2,2,”MAUS”
PRINT 1

Text kann mittels Utility Programm direkt an Drucker gesendet werden. Labelstring in Datei gespeichert. Kann man schnell ändern.

Lt Doku unterstützt der Drucker Zebra Programming Language ZPL. Weitere Informationen und Beispiele haben wir im Lieferumfang aber nicht gefunden und es daher nicht weiter getestet.

———————————

Ansteuerung via DOT NET Software

Drucker zum Laufen zu bringen war die eine Aufgabe. Lösung für Software nutzbar zu gestalten der zweite Teil. In DOT NET haben wir standardmässig nichts für direkte Kommunikation mit USB Printern gefunden. Microsoft Lösungsvorschlag hier: https://support.microsoft.com/de-de/kb/322091

Via System.Runtime.InteropServices; und Einbindung der API Funktion WINSPOOL.DRV. (Unsere Umsetzung auf Server unter Testprojekte VISUAL STUDIO 2015….)

Mini C# Programm. Zwei Buttons: Button 1 lädt eine Befehlsdatei (die mit dem obigen Etikettenstring). Button 2 sendet diese Datei an den per USB angeschlossenden Drucker.

(PS: Was mich gerade an Google nervt, dass standardmässig das Datum ignorieren und auch alte Daten nach oben schieben. Ich hätte meine Ergebnisse viel lieber sortiert nach Datum. Tipps, die sich noch auf Windows 95 oder so beziehen sind wenig hilfreich….)

———————————

Drucker mit serieller RS232.

RS232 hat der Drucker. Hätten wir auch gerne getestet. Senderoutinen, um beliebige Zeichen an COM Port zu übertragen haben wir ja bereits zuhauf als DOT NET Software herum fliegen. Allerdings ist der RS232 Anschluß als 9pol BUCHSE herausgeführt. Das mag zwar für ein solches Gerät richtig sein, ist aber inzwischen ungewöhnlich: standardmässige Nullmodemkabel können nicht verwendet werden. Selbst unsere serielle Waage verfügt inzwischen über 9pol STECKER. Um Übergang von Buchse auf Stecker zu realisieren wäre bei uns daher etwas Adapterkuddelmuddel notwendig, dann hätten wir noch sicherstellen müssen dass RxD / TxD weiterhin Leitungen 2 und 3 betreffen, damit die Daten richtig angekommen. Last not least noch die seriellen Übertragungsparameter abgeleichen… kurzum: zu viel Fehlermöglichkeiten, zu viel Aufwand für diesen Test. Haben wir daher darauf verzichtet.

Nachtrag: Dieser Text ist KEINE Wertung eines Produktes. Wir dokumentieren hier lediglich UNSERE Erfahrungen und Eindrücke. Wenn etwas fehlerhaft oder falsch dargestellt wurde, liegt es zweifelsfrei an uns und nicht am Produkt. Wir verwenden Texte dieser Art, um unsere Arbeiten für die Zukunft zu sichern, falls weitere Arbeiten anstehen sollten…

Windows CE 6.0 Problems with Datalogic Memor X3

With DATALOGIC MEMOR System X3 together with operating system Windows CE 6.0, we detected fatal software crash after Power OFF / Power ON the system, during usage our software for mobile data collection WIN CE MOBILE DATA – GERMAN or ENGLISH.

The software WIN CE MOBILE DATA is mainly unchanged since some years and well tested in Windows CE 5.0 and other operating systems. We still not found such problems in the old DATALOGIC MEMOR system – but the new MEMOR X3 system, after power down and switching the system on again, in some cases, the software crashes totally with an error message, sometimes the software is frozen.

We found out two reasons:

1) This configuration is not able to work with more then one timer inside the software.

Our software used several timers to present a valid date / time combination for the user at any time.. One timer inside the user menu, others inside the different input menus, updated every second.

Solution: We just created an updated version for WIN CE MOBILE DATA software 1..6.x with supports one timer inside the main menu only. All other timers are removed from  the software package.

2) This configuration crashes when the software is started from the internal SD CARD medium.

Solution: We copy the software from SD CARD into a folder inside PROGRAMM FILES and start the software from this folder.

Together with this two changes our test environmen works well again. We will change our production information system for a new setup workaround in delivering such systems. We did not recogneized any other problems still yet.

Hans-J. Walter
Software Engineering