C# Usercontrol

Heute mal was ganz anderes. Wenn man ein Programm schreibt findet man nicht immer das Steuerelement was man braucht.
Letztens benötigte Ich eine „Oszilloskop Ansicht“ um eine Vorschau für eine berechnete Wellenform darzustellen.
Nun in Visual Studio gibt es zwar vieles aber eben dies nicht. Viele werden jetzt sagen „nimm einfach eine Picturebox und zeichne da rein“.
Nun das habe ich auch getan um den Algorithmus zu testen aber Ich wollte was schöneres. Also schnell ein neues Projekt aufgesetzt.

Entwicklungsumgebung einrichten

  • Leere Projektmappe anlegen (hier Usercontrol)
  • Neues Projekt hinzufügen „Windows Forms-Anwendung“ (TestAPP)
  • Neues Projekt hinzufügen „Windows Forms-Steuerelementbibliothek“ (Oszilloskop)
  • Die Eigenschaft (Name) von Usercontrol1 in Oszilloskop abändern
  • Projektmappe erstellen [F6] damit das neue Steuerelement in der TestAPP zu Verfügung steht
  • Das neue Steuerelement in der TestAPP Anwendung verwenden

Jetzt kann man mit der eigentlichen Entwicklung loslegen.

Steuerelement

Zunächst muss man sich den Quellcode der Datei UserControl1.cs anzeigen lassen.
Die erreicht man in dem man die Datei UserControl1.cs im Projektmappen-Explorer markiert und [F7] drückt.
Alternativ kann man auch das Kontextmenü verwenden und den Punkt „Code anzeigen“ auswählen.

Direkt unter dem Konstruktor fügt man jetzt folgende Codezeilen ein.

Code
private PointF[] _data = null; // Globale variable die die Kurvenform enthält
// Extern zugängliche Funktion zur übergabe der zu zeichnenden Kurvenform
public void Drawcurve(PointF[] data)
{
// Zwei Punkte werden benötigt zum zeichnen
if (data.Length < 2)
return;  _data = data;
this.Invalidate(); // Graph neu zeichnen
}

// Funktion zum skalieren von werten
private float scale(float x, float x1, float x2, float y1, float y2)
{
if (x1 == x2)
return 0.0f; // We don't devide by 0

float retval = ((y2 - y1) / (x2 - x1)) * (x - x1) + y1;
return retval;
}

Diese Codezeilen zeichnen jedoch noch keine Kurve oder andere Elemente im Steuerelement. Dazu müssen wir die Funktion OnPaint des Steuerelements überschreiben.

Code
protected override void OnPaint(PaintEventArgs e)
{
Pen pGrid = new
Pen(Color.DarkGray);

float x1 = 0.0f,
x2 = this.Width - 1.0f, // Breite des Steuerelements
y1 = 0.0f,
y2 = this.Height - 1.0f; // Höhe des Steuerelements

float vdiv = 10.0f, hdiv = 10.0f; // Anzahl an Horizontlen/Vertikalen linien

// Vertikale linien
for (float y = x1; y < x2; y+=((x2 - x1 - 0.001f) / vdiv))
{
e.Graphics.DrawLine(pGrid, y, y1, y, y2);
}

// Horizontale linien
for (float x = y1; x <= y2; x+=((y2 - y1 - 0.001f) / hdiv))
{
e.Graphics.DrawLine(pGrid, x1, x, x2, x);
}

if (_data != null && _data.Length >= 2)
{
// Enthaltene Daten zeichnen
for (int i = 0; i < _data.Length; i++)
{
// Zu zeichnende Daten auf die Zeichenfläche skalieren
// Hier mit fester Skala

_data[i].X = scale(_data[i].X, 0.0f, 0.02f, 0, this.Width);
_data[i].Y = scale(_data[i].Y, -325.0f, 325.0f, this.Height, 0);
}

e.Graphics.DrawCurve(Pens.DarkCyan, _data);
}

base.OnPaint(e);
}

Testdaten berechnen

Zum berechnen des Augenblickswertes einer Sinusförmigen Spannung benötigt man folgende Formel.

Da jedoch ein einzelner Wert relativ sinnfrei ist für eine Darstellung einer ganzen Welle muss man sich die Werte für t=0 bis t=T berechnen und in einem Array abspeichern.

Code
PointF[] Ut = new
PointF[4096]; // Augenblickswertarray
float u = 325.0f; // Spitzenwert
float f = 50.0f; // Frequenz der Spannung
float T = 1.0f / f; // Periodendauer
float phi = 0.0f; // Phasenwinkel
float omega = Convert.ToSingle(2.0f * Math.PI * f);
float stepsize = T / Ut.Length;
int idx = 0; // Arrayindex

// Testdaten berechnen
for (float t = 0; t < T; t+=stepsize)
{
idx = Convert.ToInt32(t / stepsize);
if (idx < Ut.Length)
{
Ut[idx].X = t;
Ut[idx].Y = Convert.ToSingle(u * Math.Sin(omega * t + phi));
}
}

Steuerelement testen

Wenn man mit der obigen Funktion seine Testkurve berechnet hat muss man diese nur noch an das neue Steuerelement übergeben und Sie darstellen lassen. Die folgende Codezeile muss man nur noch unter die obige For-Schleife schreiben und seine Anwendung starten.

Code
oszilloskop1.Drawcurve(Ut);

Going OLD-School with Assembler


Ok, Seit ein paar Tagen bin ich stolzer Besitzer eines Dev-Kits für einen C8051F930 von Silicon Labs.
Da ich mir das Teil für die Technikerschule angeschafft habe musste ich gleich mal ein wenig damit Spielen. In der Technikerschule arbeiten wir zwar mit einem Anderen Prozessortyp (Infineon SAB80C517) aber der Kern ist derselbe ein 8051.
Somit kann man das Board zum üben verwenden, man muss allerdings aufpassen das man mit den Registernamen sowie den Eigenheiten nicht durcheinander kommt.
Beim 80C517 gibt es bspw. einen Watchdog den man in Assembler mittels

SETB WDT
SETB SWDT

bedienen muss. Beim C8051F930 geschieht dies anders.
Des Weiteren wurde bei dem Dev-Kit eine „Vollversion“ von Keil µVision V4 mitgeliefert.
Die Vollversion bezieht sich allerdings nur auf die µCs von Silicon Labs, was durchaus verständlich ist.
Zum Spielen hab ich mir mal 2 Programme geschrieben und deren Footprint im Flash des µCs gegenübergestellt.
Die Programme schalten jeweils nur die LED die am Portpin 1.6 angeschlossen ist ein und gehen dann in eine Dauerschleife.
Zuerst die Assemblerversion:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Name Test
; Description: Turn on the LED connected to PortPIN 1.6
; Author: Manuel Koenig
; Date: 03.03.2014

$include(C8051F930.INC)

CSEG AT 0000h

MOV P1MDIN,#60h ;// P1.5, P1.6 are digital
MOV P1MDOUT,#60h ;// P1.5, P1.6 are push-pull
MOV XBR2,#40h ;// Enable crossbar and
;// enable weak pull-ups

;// High = LED Off, Low = LED On
MOV P1,#0FFh ;// Turn off all LEDs
CLR P1.6 ;// Turn on LED on Portpin 1.6

endlos: JMP endlos
END

Assembler footprint im Flash
1
2
3
4
5
6
C:0x0000 75F260 MOV P1MDIN(0xF2),#0x60
C:0x0003 75A560 MOV P1MDOUT(0xA5),#0x60
C:0x0006 75E340 MOV XBR2(0xE3),#0x40
C:0x0009 7590FF MOV P1(0x90),#VDM0CN(0xFF)
C:0x000C C296 CLR 0x90.6
C:0x000E 80FE SJMP C:000E

Hier das C Programm:

C-Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <compiler_defs.h> // compiler declarations
#include <C8051F930_defs.h> // SFR declarations

SBIT (YELLOW_LED, SFR_P1, 6); // ‚0‘ means ON, ‚1‘ means OFF
#define LED_ON 0

void main (void)
{
P0MDIN |= 0x0C; // P0.2, P0.3 are digital
P1MDIN |= 0x60; // P1.5, P1.6 are digital

P0MDOUT &= ~0x0C; // P0.2, P0.3 are open-drain
P1MDOUT |= 0x60; // P1.5, P1.6 are push-pull

XBR2 = 0x40; // Enable crossbar and enable
// weak pull-ups
YELLOW_LED = LED_ON; // Turn on the LED on Portpin 1.6

while (1) {} // Spin forever
}

Assembler footprint im Flash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
C:0x0000 020016 LJMP C:0016
C:0x0003 43F10C ORL P0MDIN(0xF1),#0x0C
C:0x0006 43F260 ORL P1MDIN(0xF2),#0x60
C:0x0009 53A4F3 ANL P0MDOUT(0xA4),#0xF3
C:0x000C 43A560 ORL P1MDOUT(0xA5),#0x60
C:0x000F 75E340 MOV XBR2(0xE3),#0x40
C:0x0012 C296 CLR YELLOW_LED(0x90.6)
C:0x0014 80FE SJMP C:0014
C:0x0016 787F MOV R0,#0x7F
C:0x0018 E4 CLR A
C:0x0019 F6 MOV @R0,A
C:0x001A D8FD DJNZ R0,C:0019
C:0x001C 758107 MOV 0x81,#0x07
C:0x001F 020003 LJMP C:0003
.
.
.

Wie man sieht hat man bei C einen deutlichen Overhead, daher sollte man bei begrenztem Speicher, hier max. 64kB (-Variablen, -Stack,-etc.) auf Assembler zurückgreifen.
Wer möchte kann die beiden Programme gerne runterladen und selbst ausprobieren sofern Ihr das Dev-Kit habt.

Test_ASM.zip Test_C.zip

Task automation with Visual Basic Script

In case you want to automate some tasks, for example backing up a specific folder from your computer every time you plug in a specific USB-Stick.
All you need to do is to execute the following Visual Basic Script on your computer.
Place it in the Startup folder of Windows if you want it to run every time you login.
Script on your computer

Set Shell = CreateObject( "WScript.Shell" )
Set fso = CreateObject("Scripting.FileSystemObject")
Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colME = oWMI.ExecNotificationQuery("Select * from Win32_VolumeChangeEvent")

' Name of the Volume we are after
strVolumeName = "BACKUPDISK"

' Watch for new Drives
Do
Set oLE = colME.NextEvent
If oLE.EventType = 2 Then
' New Drive arrived
Set d = fso.GetDrive(oLE.DriveName)

If d.VolumeName = strVolumeName Then
Shell.Run oLE.DriveName & "\backup.vbs"
End If
End If
Loop

The Script will check for the Drivename (here: „BACKUPDISK“) and if the Drive is found it will execute the BackupScript on the USB-Stick.

Script (backup.vbs) on the USB-Stick

' This Script must be on the USB-Drive in the root directory
Set Shell = CreateObject( "WScript.Shell" )
Set fso = CreateObject("Scripting.FileSystemObject")

' Get the Userprofiledirectory & Computername
strUP = Shell.ExpandEnvironmentStrings( "%USERPROFILE%" )
strCN = Shell.ExpandEnvironmentStrings( "%COMPUTERNAME%" )
strDRV = fso.GetDriveName(WScript.ScriptFullName)

' Create a subfolder on the USB-Drive if it doesn't exist
If Not(fso.FolderExists (strDRV & "\Backup\" & strCN)) Then
fso.CreateFolder strDRV & "\Backup\" & strCN
End If

' Backup the Data (Overwrite existing files)
fso.CopyFolder strUP & "\Pictures", strDRV & "\Backup\" & strCN & "\", vbTrue

In this case all your pictures from the Picturefolder in your Userprofile are backed up.

Softwareentwicklung aus Sicht eines Testers

In Zeiten immer schnellerer Computer mit Arbeitsspeicher jenseits der 4GB Grenze verschlingen die neuen Programme zunehmend mehr und mehr dieser Resourcen.
Ich meine hier nicht die neuen 3D Spiele die immer bessere Grafik aufweisen, bei denen finde ich das OK.
Das aber Entwickler von Client/Server Applikationen auch mal eben alles in den RAM pusten und dort halten weil es einen „Performancezuwachs“ bringt halte ich für sehr bedenklich.
Mir ist bewusst dass das jetzt klingt als wäre ich im gestern stehen geblieben aber meiner Meinung nach sollte jede Anwendung (auch ihre Komponenten) ihren Arbeitsspeicher möglichst intelligent verwalten, um auch anderen Anwendungen eine Koexistenz zu ermöglichen bzw. dem System selbst auch noch was übrig zu lassen.
In meiner Tätigkeit als Software Tester konnte ich dies schon mehrmals beobachten.

Bei meinen Recherchen ob das gängige Praxis ist bin ich mehrmals auf die regeln

  • make it run
  • make it right
  • make it fast
  • (make it small)

Source: James Coplien and Kent Beck, „After all, we can’t ignore efficiency – part 2“

gestoßen. Aus meiner Sicht umfassen diese Stichpunkte genau das was wirklich wichtig ist.

** Die folgende auflistung gibt nur meine Meinung zu den Stichpunkten wieder. **

make it run:
Hier sollte die Spezifikation der Applikation zusammen mit Kunden, Entwicklern und Testern erfolgen.
Die sogenannten Kick Off Meetings. Dies bedeutet man bringt das Projekt ans laufen.

make it right:
Zu diesem Zeitpunkt ist das Projekt schon in den Händen der Entwickler.
Diese sollten in dieser Phase darauf achten das ihr Source Code Modularisiert, Kommentiert, Wiederverwendbar und Wartbar ist.

Da die Tester nicht immer Zugriff auf den Source Code der Applikation haben (Blackbox), sollten Schnittstellen für Automatisiertes Testen ebenfalls implementiert werden damit wiederkehrende Testaufgaben schneller überprüft werden können.
Ein Exploratives Testen ist meist sehr Zeitaufwendig und kann von Tester zu Tester zu unterschiedlichen Ergebnissen führen. Daher sollte der Anteil der Automatisierten Tests bei ca. 60 – 70% liegen.
Die restlichen Prozente müssen von Hand durchgeführt werden, da ein Automatisierter Test schlecht die Benutzerfreundlichkeit einschätzen oder wenn erforderlich den PC Herunterfahren und sich neue Hardware einbauen kann.
Sicher es gibt Virtualisierungssoftware die auch Hardware durchreichen kann (Passthrough), nur dann stellt sich die frage verhält sich die Hardware jetzt auch ordnungsgemäß.

make it fast:
Bei diesem Schritt soll die Applikation noch optimiert werden in Hinblick auf Ladezeiten, Speicherverbrauch und Code Optimierung.

Bei der Code Optimierung muss allerdings darauf geachtet werden das die Wartbarkeit des Codes nicht darunter leidet und das Kommentare auch nachgezogen werden.

make it small:
Bezogen auf den benötigten Festplattenplatz würde ich dies verneinen aber im Hinblick auf den Arbeitsspeicherverbrauch, naja da sagt der vorangegangene Text eigentlich alles.

Soviel jetzt zu meiner Meinung. Was ist eure? Was haltet ihr von der Resourcenverschlingerei der neuen Programme?

Networkscanner written in Batch

Wie der Titel schon verät handelt es sich hierbei um einen Netzwerscanner der in Batch geschrieben ist.

Nach der eingabe des IP-bereiches listet dieser alle vorhandenen Geräte in einer CSV-Datei auf.

Die auflistung funktioniert aber nur solange der Host auf einen Ping antwortet, ist dies nicht der fall findet sich ein entsprechender vermerk in der CSV-Datei.

Nun aber zum wesentlichen, zum Source Code.

Source:
@echo off

if exist ips.csv del ips.csv > nul

echo *****************
echo * Batch IP-Scan *
echo * *
echo *****************
echo Listet alle sich im Netzwerk befindlichen Computer auf.
echo Bitte geben Sie den ersten Teil der IP ein:
echo z.b. 192.168.0.
set /p ip=

echo _IP._IP._IP._IP; Hostname >> ips.csv

for /L %%N IN (1, 1, 255) DO (
echo Die IP: %ip%%%N wird nun angepingt
ping %ip%%%N -n 1 -w 1 | find "TTL" >NUL
if errorlevel 1 (
echo %ip%%%N; Kein Host oder durch Firewall blockiert >> ips.csv
) else (
nslookup %ip%%%N | find /i "Name:" >NUL
if errorlevel 1 (
echo %ip%%%N; N/A >> ips.csv
) else (
for /f "tokens=2" %%i in ('nslookup %ip%%%N ^| find /i "Name:"') do (
echo %ip%%%N; %%i >> ips.csv
)
)
)
)

Für etwas mehr Komfort sorgt die Namensauflösung für die entsprechende IP.
Viel Spass damit.

Hier der Source Code als TXT-Datei.
ipscan source

How to enable / disable screen saver in Windows from VB

Method
To enable or disable the screen saver, use the SystemParametersInfo Windows API.

Here is an example on how to use it from VB. For more information, search for Microsoft article Q126627 in the MSDN help. You can also use the VB API Viewer to copy and paste the declarations used in this example.

Code Example
Option Explicit

Private Declare Function SystemParametersInfo Lib "user32" _
Alias "SystemParametersInfoA" _
(ByVal uAction As Long, ByVal uParam As Long, _
ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long

Const SPI_GETSCREENSAVEACTIVE=16
Const SPI_SETSCREENSAVEACTIVE=17
Const SPIF_SENDWININICHANGE=&H2

Public Sub EnableScreenSaver(enable As Boolean)

SystemParametersInfo SPI_SETSCREENSAVEACTIVE, _
enable, 0&, SPIF_SENDWININICHANGE

End Sub

Public Function IsScreenSaverActive() As Boolean

Dim pvParam As Long
SystemParametersInfo SPI_GETSCREENSAVEACTIVE, 0, pvParam, 0
IsScreenSaverActive=(pvParam=1)

End Function

To enable the screen saver, call EnableScreenSaver with an argument of True.

EnableScreenSaver True

To disable the screen saver, call EnableScreenSaver with an argument of False.

EnableScreenSaver False