BigBasti's Blog About Me & my Digital Lifestyle

17Feb/100

VB.NET: FitzBox IP erneuern ueber uPnP

Die FritzBox ist als Router weit verbreitet und bietet einen Haufen an Konfigurationsmöglichkeiten an. Eins der nützlichsten Features ist uPnP (Universal Plug and Play). Diese Schnittstelle bietet uns eine sehr bequeme Möglichkeit mit dem Gerät zu kommunizieren ohne dass man einen Benutzernamen oder ein Kennwort benötigt!

Wer öfter mal im Internet unterwegs ist, kennst sicherlich mehrere gute Gründe seine IP zu wechseln. Und das ist sehr einfach, denn alles was dafür nötig ist, ist eine erneute Einwahl ins Internet.

Dies kann man sehr einfach über die Benutzeroberfläche der FritzBox machen oder einfach "oldschool"-mäßig das Netzwerkkabel aus der FritzBox ziehen und wieder einstecken. (Letzteres erfordert ebenfalls keinen Benutzernamen und Passwort)

Doch wenn man des öfteren auf diese Funktionalität angewiesen ist, ist es doch relativ nervig und umständlich. Deswegen werden wir hier ein einfaches kleines Programm entwickeln, dass für uns den Router zu einer Neueinwahl ins Internet "zwingt".

Wie oben bereits erwöhnt heißt die Technologie dafür UPnP (Universal Plug and Play). Über diese Technologie lassen sich sehr viele Befehle an die Fritzbox senden, vorausgesetzt, man befindet sich in dem selben Netzwerk.

Von Statusabfragen über Auslastungen und Übertragung, lassen sich sogar Telefonnummern anwählen und Anrufe steuern, im Prinzip kann man alle Funktionen darüber ansteuern. Hier gibts eine nette Übersicht mit vielen Beispielen.

Wie werden die Anfragen eigentlich an die Fritzbox übertragen? Das geschieht sehr einfach über einen POST Aufruf, denn auf der Fritzbox (und auch auf den meisten anderen Routern) läuft ein kleiner Webserver denn man ganz einfach über den Browser erreicht, wenn man die adresse "fritz.box" in die Adresszeile tippt.

Dort ist die Fritzbox genauso aufgebaut wie eine gewöhnliche Webseite. Und diese nimmt auch POST und GET aufrufe entgegen. Genau hier setzen wir an und werden unsere Befehle rüber schicken.


        Dim client As New TcpClient

        client.Connect("fritz.box", 49000)

        Dim stream As NetworkStream = client.GetStream
        Dim bytes As Byte() = New Byte((My.Resources.msg.Length)) {}

        bytes = Encoding.ASCII.GetBytes(My.Resources.msg)

        stream.Write(bytes, 0, bytes.Length)
        bytes = New Byte(1024) {}

        Dim str As String = String.Empty

        Dim count As Integer = stream.Read(bytes, 0, bytes.Length)

        str = Encoding.ASCII.GetString(bytes, 0, count)

        stream.Close()
        client.Close()

Der Code ist sehr simpel, wir erstellen uns einen WebClient und verbinden uns mit der FritzBox. Nach der Verbindung senden wir ein POST Request raus und lesen anschließend die Antwort wieder aus.

Mit dem obigen Code senden wir folgenden Befehl an die Fritzbox:


POST /upnp/control/WANIPConn1 HTTP/1.1
HOST: fritz.box:49000
SOAPACTION: "urn:schemas-upnp-org:service:WANIPConnection:1#ForceTermination"
CONTENT-TYPE: text/xml ; charset="utf-8"
Content-Length: 293

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:ForceTermination xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1" />
   </s:Body>
</s:Envelope>

Wie man sieht ist der Befehl ein gewöhnlicher POST Aufruf inkl. Header. Dieser übergibt einen Befehl urn:schemas-"upnp-org:service:WANIPConnection:1#ForceTermination", der der Fritzbox sagt die Verbindung ins Internet neu aufzubauen.

Man muss hierbei sehr aufpassen, besonders die Content-Length Angabe muss genaustens passen, da sonst ein Fehler als Antwort eintrudelt.

Wie immer gibts auch eine kleine Demoanwendung.

Bild 1: Das Demo Programm in action

Download hier: Download [VS 2008 Projekt]

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
9Dez/090

VB.NET: Saubere Klassen erstellen mit Properties

Heutzutage wird fast nurnoch Objektorientiert programmiert. Das bedeutet, dass ein größeres Projekt schnell mal auf eine Klassenanzahl von 100 und mehr wächst.

Damit man den Überblick behält und den Code, den man schon geschrieben hat möglichst wiederverwenden kann, sollte man ein paar grundlegende Regeln beachten.

In diesem Artikel möchte ich ein Beispiel zeigen, wie man eine Klasse in ein Projekt integriert und dank der benutzten Standardmethoden an ein Datagrid bindet.

Warum schreibe ich diesen Artikel überhaupt? Erst gestern habe wurde in einem Forum die Frage gestellt, warum man eine Liste (Of T) nicht als DataSource für ein DataGridView benutzen kann. Dabei ist das sehr wohl möglich, der User hat seine Klasse aber "unschön" gestaltet, weswegen sich die anderen Steuerelemente auch quer gestellt haben.

Hier ein Beispiel einer solchen "Unschönen" Klasse:


Public Class Auto
    Public marke As String
    Public motor As String
    Public geschw As Integer
End Class

        Dim al As New List(Of Auto)
        al.Add(New Auto With {.marke = "VW", .motor = "Diesel", .geschw = 0})

        al(0).geschw += 10

Wie man sieht sind hier alle Klassenvariablen öffentlich zugänglich, und die Klasse hat keinerlei Kontrolle darüber, wie sie befüllt werden. Ein weiterer Nachteil ist auch die Inkompabilität zu anderen Steuerelementen, da diese einen Standardkonformen Aufbau der Klasse erwarten. Finden sie bestimmte Elemente in der Klasse nicht so verweigern diese die Funktionalität!

Wie müsste diese Klasse also umgebaut werden, damit diese kompatibel zu anderen Objekten wird?


Public Class Auto
    Private geschw As Integer

    Public Sub New(ByVal marke As String, ByVal motor As String)
        Me._marke = marke
        Me._motor = motor
    End Sub

    Private _marke As String
    Public Property Marke() As String
        Get
            Return _marke
        End Get
        Set(ByVal value As String)
            _marke = value
        End Set
    End Property

    Private _motor As String
    Public Property Motor() As String
        Get
            Return _motor
        End Get
        Set(ByVal value As String)
            _motor = value
        End Set
    End Property

    Public Sub beschleunigen(ByVal a As String)
        geschw += a
    End Sub

    Public Sub bremsen(ByVal a As String)
        geschw -= a
    End Sub
End Class

Wie man sieht ist die Klasse nun natürlich um einiges länger geworden. Leider kann man das zur zeit noch nicht anders machen. Aber Abhilfe kommt in der neuen VB.NET Version, wo man die properties so wie in C# 3.0 erstellen kann.

Die Zugriffe auf die Klassenvariablen werden nun über properties gesteuert, die nun auch zB. überprüfen könnten, ob der übergebene Wert überhaupt passt und gegebenenfalls noch Änderungen daran vornehmen.

Aber was bringt uns nun dieser längere Aufbau der Klasse? Nun, wenn wir unser Objekt, das aus dieser Klasse entsteht an andere Objekte übergeben, erwarten diese, dass sie properties vorfinden, mit denen sie arbeiten können.

Hat die Klasse keine Properties so können wir auch bestimmte Funktionen auch nicht benutzen. Ich möchte das mal an einem DataGridView demonstrieren, da dieses Element von den properties sehr schön Gebrauch macht!

Fügt man folgenden Code einem Form mit einer DataGridView hinzu:


    Private Sub Form1_Load() Handles MyBase.Load
        Dim autos As New List(Of Auto)

        autos.Add(New Auto("VW", "Diesel"))
        autos.Add(New Auto("Audi", "Benziner"))
        autos.Add(New Auto("Mercedes", "Diesel"))
        autos.Add(New Auto("Renault", "Diesel"))
        autos.Add(New Auto("BMW", "Beziner"))

        Dim bs As New BindingSource
        bs.DataSource = autos

        Me.DataGridView1.DataSource = bs
    End Sub

erhält man folgendes Bild:

datagridviewBild 1: Die Datagridview stellt alle Informationen angenehm dar

Wie man sieht konnte man mit nur 3 Zeilen Code (Abgesehen vom Erzeugen der Werte) alle Daten der Liste visualisieren. Man beachte desweiteren, dass sogar die Namen der Properties (Marke und Motor) ausgelesen werden und der richtigen Tabelle zugeordnet werden!

Dies könnte man natürlich auch ohne Properties hinbekommen, doch würde man viel mehr Aufwand betreiben müssen und man denke an die Zukunft, in der unser Modell sehr einfach zu warten wäre.

Hier gibts ein kleines Demoprojekt: Download [VS 2008]

VN:F [1.8.4_1055]
Rating: 8.0/10 (4 votes cast)
1Dez/090

Kostenloses E-Book von Microsoft zum Thema VB.NET

Es ist wieder soweit. Microsoft bietet wiedermal ein Buch komplett gratis zum Download an. Dieses Mal ist Visual Basic.NET das Thema.

Visual-Basic-2008-Das-Entwicklerbuch-1259659733

Das Buch ist von dem Hauseigenen Verlag MicrosoftPress, welches einen sehr guten Ruf genießt. Ich selber habe mehrere Bücher von denen.

Dieses Buch kostet normalerweise 59 € und ist somit ein sehr gutes "Schnäppchen". Dabei kann es sich vom Inhalt sehen lassen. Dieses Buch vermittelt alles von den Grundlagen, bishin zur fortgeschrittenen Programmierung mit Datenbanken.

Auch wenn ihr kein VB.NET Programmierer Seit kann ich es euch trotzdem empfehlen dieses Buch zu laden, den man weiß ja nie!

Download: Hier

VN:F [1.8.4_1055]
Rating: 0.0/10 (0 votes cast)
9Nov/094

Windows Aero Glass in eigenen Projekten nutzen Teil 2

dotnetIn dem ersten Teil dieses Beitrags, der nun schon einige Monate her ist habe ich gezeigt, wie man die Aero Glas Effekte auch in eigene Projekte einbauen kann. Doch leider waren da noch einige Probleme, so konnten wir nur das ganze Formular in Glas verwandeln und die Darstellung der Steuerelemente war falsch.

Genau hier möchte ich den zweiten Teil ansetzen und diese letzten Probleme aus der Welt schaffen!

Wir beginnen genauso wie im ersten Teil nur nennen wir unsere Klasse diesmal GlassForm um nicht durcheinander zu kommen.

Diesmal importieren wir eine weitere Methode aus der Windows API, nämlich DwmIsCompositionEnabled() die es uns ermöglicht zu prüfen, ob diese Effekte, die wir nutzen möchten auch verfügbar sind.

Die zweite Funktion DwmExtendFrameIntoClientArea müsste aus Teil 1 schon bekannt sein, diese hilft uns die Formränder zu vergrößern und somit die Glasoberfläche ins Formularinnere zu holen.

Da wir dieses Mal die eine Option für alle Ränder haben möchten, sodass wir zB. nur den oberen Rand in Glas verwandeln, benötigen wir ein Structure, in dem wir die Werte für jeden Rand speichern können und den wir dann später der Funktion DwmExtendFrameIntoClientArea übergeben.

So sieht unsere Klasse aus:


Imports System.Runtime.InteropServices

Public Class GlassForm
 _
        Private Shared Sub DwmExtendFrameIntoClientArea _
                (ByVal hwnd As IntPtr, ByRef margin As AeroDemo2.MARGINS)
    End Sub
 _
    Public Shared Function DwmIsCompositionEnabled() As Boolean
    End Function

    Public Shared Function ExtendGlassFrame _
        (ByVal hwnd As IntPtr, ByVal margin As AeroDemo2.MARGINS) As Boolean

        GlassForm.DwmExtendFrameIntoClientArea(hwnd, margin)

        Return True

    End Function

End Class

Public Structure MARGINS
    Public left As Integer
    Public right As Integer
    Public top As Integer
    Public bottom As Integer

    Public Sub New(ByVal l As Integer, ByVal r As Integer, _
                   ByVal t As Integer, ByVal b As Integer)
        left = l
        right = r
        top = t
        bottom = b
    End Sub
End Structure

Wie man sieht enthält die Structure MARGINS je eine Variable für jede Seite des Formulars, wobei der Wert den sie beinhaltet den Abstand zum eigentlichen Rahmen angibt!

Wechseln wir nun zur Klasse Form1, da wir hier fertig sind. In der Form_Load Methode können wir uns nun einen neuen Structure erstellen und diesem unsere gewünschten Rahmenabstände übergeben. Daraufhin rufen wir unsere Funktion auf die für sns das Glas herzaubern soll.

Doch wenn wir das Programm nun starten werden wir kein Glas vorfinden! Das liegt daran, dass Windows die Farbe Schwarz für Transparente Darstellung auf Glas verwendet. Das bedeutet, dass alle Steuerelemente, die Schwarze Farbe enthalten transparent und somit zu Glas werden! Das konntet ihr aber auch im ersten Teil schon beobachten!

Dieses Problem nehmen wir aber später nocheinmal in Angriff! Kommen wir ersteinmal zu unserem Glasfenster!

Damit wir auch wirklich Glas sehen, müssen wir ersteinmal das Fenster mit schwarzer Farbe füllen. Dazu schreiben wir folgendes in die Form_Paint Methode:


    Dim margins As AeroDemo2.MARGINS

    Private Sub Form1_Load() Handles MyBase.Load
        'Den "normalen" Bereich festlegen
        margins = New AeroDemo2.MARGINS(0, 0, 35, 50)
        'Die Fensterränder erweitern
        GlassForm.ExtendGlassFrame(Me.Handle, margins)
    End Sub

Wenn man das Programm startet, müsste das ca so aussehen:

aerodemo1Bild 1: Alles ist schwarz, bis auf den Glasteil

Bitte nicht erschrecken, denn eigentlich ist es keine Überraschung, dass wir nur schwarz sehen, denn wir haben im letzten Schritt alles Schwarz gefärbt. Der Aero Teil ist dadurch nun transparent geworden!

Da das Schwarze aber ziemlich blöd aussieht möchten wir das natürlich wieder auf unsere Standardeinstellung ändern. Dazu müssen wir diesen schwarzen Rechteck da oben nun wieder mit der Ausgangsfarbe füllen! Das machen wir so:


    Private Sub Form1_Paint(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        If GlassForm.DwmIsCompositionEnabled() = True Then
            'Hintergrund Schwarz füllen, um den Glass effenkt zu erhalten
            e.Graphics.Clear(Color.Black)
            'Nun das Stück, dass nicht aus Glas sein soll wieder "zurückmalen"
            Dim clientArea As New Rectangle(margins.left, margins.top, _
                    Me.ClientRectangle.Width - margins.left - margins.right, _
                    Me.ClientRectangle.Height - margins.top - margins.bottom)
            Dim b As Brush = New SolidBrush(Me.BackColor)
            e.Graphics.FillRectangle(b, clientArea)
        End If
    End Sub

Nachdem wir das Rechteck wieder mit der Ausgangsfarbe bemalt haben sieht das schon viel angenehmer aus:

aerodemo2Bild 2: Das Fenster hat nun wieder die "Normale" Farbe

Was natürlich nun auffällt ist das Komplett schwarze Label (ja, es ist wirklich eins) und der nicht lesbare Button.

Dies sind die oben besagten Probleme von GDI Objekten. Diese werden Standardmäßig genutzt um Abwärtskompabilität zu gewährleisten. Schaltet man aber das TextRendering auf GDI+ so werden auch die Schriften korrekt dargestellt.

Um das zu ändern muss die Option SetCompatibleTextRenderingDefault auf true gesetzt werden. Dies muss aber geschehen bevor das Programm gestartet wird. Also klicken wir mit der Rechten Maustaste auf unser Projekt -> Hinzufügen -> Modul

In das Modul schreibt ihr nun folgendes rein:


    Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(True)
        Application.Run(New Form1) 'Name eurer Form
    End Sub

Nun müssen wir nurnoch dafür sorgen, dass unser Projekt durch das Modul gestartet wird. Das machen wir in dem wir auf "Projekt" oben im Menü klicken und dann auf Eigenschaften. Hier muss nun der Haken bei "Anwendungsframework aktivieren" herausnehmen und dann bei "Startobjekt" "Sub Main" wählen:

aerodemo2_1Bild 3: Das Projekt über das Modul starten

Wenn wir das Programm nun starten sollte man die Texte und auch den Button lesen können!

Nun sind wir eigentlich schon durch. Was noch zu sagen bleibt ist, dass man es möglichst vermeiden sollte Steuerelemente auf dem Glas zu platzieren, da diese sehr oft falsch dargestellt werden.

Wenn ihr unbedingt Schrift auf Glas haben wollt solltet ihr diese Schrift auf das Formular Zeichnen und nicht einfach über ein Label dort platzieren. Das selbe gilt auch für Grafiken. Leider kann man nicht einfach mit der Graphics.DrawString() Methode Zeichnen sondern muss den Text erst in ein GraphicsPath Objekt "zeichnen" bevor man es dem Glas übergibt. So stellt man sicher, dass die Textverläufe richtig dargestellt werden!

Hier ein Beispiel:


            'Text zeichnen
            Dim txt = Me.CreateGraphics()
            Dim path = New GraphicsPath()

            path.AddString("Ich bin ein gezeichneter Text", _
                           New FontFamily("Tahoma"), CInt(FontStyle.Regular), _
                           20, New Point(60, 0), StringFormat.GenericDefault)

            Dim brush = New PathGradientBrush(path)
            Dim clr As Color() = {Color.Transparent}

            txt.SmoothingMode = SmoothingMode.HighQuality
            brush.CenterColor = Color.White
            brush.SurroundColors = clr
            txt.FillPath(Brushes.Black, path)

            brush.Dispose()
            path.Dispose()
            txt.Dispose()

Und wie es aussehen könnte:

aerodemo3Bild 4: So könnte ein Aero Formular aussehen

Weitere Informationen auch mit Beispielen findet ihr hier: (englisch & C#)

Microsoft
CodeProject
CodeProject

Wie üblich habe ich das Ganze in ein kleines Demoprojekt verpackt: Download

Wie hats euch gefallen, möchtet ihr einen dritten Teil? Freue mich auf euer Feedback!

Teil 1 des Tutorials gibts hier
Zum dritten Teil gehts hier lang

VN:F [1.8.4_1055]
Rating: 9.6/10 (5 votes cast)
6Nov/090

Windows Lizenzschlüssel aus der Registry auslesen

Da der Beitrag über das Auslesen des Office Schlüssels sehr beliebt ist, habe ich nun auch das Lesen des Windows Schlüssels als Beispiel verfasst.

Das Vorgehen hierbei ist sogar noch einfacher als beim Office Schlüssel, da es keine Aufteilungen in Versionen gibt! In allen Windows NT Versionen (also alle ab XP) befindet sich der Schlüssel in der Registry unter diesem Pfad:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

winkeyBild 1: Der Registryordner mit dem Windows Schlüssel

In diesem Ordner finden wir den Binärwert "DigitalProductId", der viele Hexadezimalzeichen enthält!

Der Code ist hierbei dem aus dem Officebeispiel sehr ähnlich, da er ja auch nichts anderes macht, als den im HEX-Code vorhandenen Key in lesbare Schrift umzuwandeln! Die einzige Schwierigkeit hierbei besteht darin, den Key richtig zusammen zusetzen, denn es wird nicht das komplette Alphabet verwendet um einen Windows Key zu generieren sondern nur diese Zeichen:

B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9

Wenn man das beachtet steht einem nichts mehr im Wege! Der Code aus diesem Beispiel stammt ausnahmsweise nicht von mir sondern von vcware.de - danke dafür an dieser Stelle!

Ich habe diesbezüglich wie immer ein kleines Demoprojekt angefertigt, das ihr euch herunterladenkönnt! Download

Bitte berichtet ob es bei euch gut geklappt hat.
Hier könnt ihr euch das komplette kostenlose Programm zum auslesen von Windows & Office key herunterladen. (English & Deutsch)

VN:F [1.8.4_1055]
Rating: 9.0/10 (1 vote cast)
5Nov/091

Windows 7 und seine Schönheitsfehler Teil 1: Ordnerpfade

win7Seit einiger Zeit ist nun Microsofts neues Betriebssystem Windows 7 auf dem Markt und schlägt sich bisher sehr gut! Ich nutze es selber jeden Tag und bin begeistert von der Geschwindigkeit und den neuen Features die es bietet. Doch leider gibt es auch hier ein paar (wenn auch wenige) Schattenseiten, über die ich in dieser Reihe berichten möchte!

In diesem Ersten Teil geht es um ein kleines "Feature", dass einem nicht gleich ins Auge springt und teilweise auch schon in Windows Vista vorzufinden war. Der "normale" Nutzer würde es wahrscheinlich garnicht bemerken, doch wir als Programmierer müssen desöfteren mit konkreten Pfaden arbeiten, und das ist genau die Sache!

Blicken wir kurz zurück auf Windows XP und seine NT-Vorgänger. Jede Windows XP Version, egal in welcher Sprache sie vorliegt hat den selben Aufbau, zB. wird man immer den Ordner C:\Programme vorfinden, in dem die ganzen installierten Programme liegen.

Wenn wir nun also diesen Pfad fest in unser Programm einbauen, da wir ja davon ausgehen, dass dieser Pfad konstant ist müsste es ja "immer" laufen! Doch das ist leider nicht so, denn wenn man unser Programm auf einem Rechner mit einer Englischen Kopie von Windows (XP) startet, wird das Programm abstürzen, da es den Ordner C:\Programme nicht finden wird!
Warum? Ganz einfach, denn im Englischen gibts das Wort "Programme" nicht! Dort heißt der Ordner "Program Files" und müsste dementsprehend über "C:\Program Files" angesprochen werden! - Ja, ich weiß, ein normaler Mensch würde hier die Umgebungsvariable "ProgramFiles" nutzen, die immer auf den richtigen Ordnerpfad zeigt, aber das würde das Problem nicht verdeutlichen! (dazu kommen wir noch)

Also zurück zu Windows 7. Microsoft dachte sich auch, dass das wohl blöd ist und entschied sich dazu alles einheitlich zu machen! - Gute Idee, doch etwas komisch umgesetzt!

Schauen wir uns doch mal einen Typischen Windows 7 Ordnerpfad an:

win71Bild 1: Der Ordner "Eigene Bilder" ausgewählt im WIndows Explorer

Wenn ich Sie nun nach dem Pfad zu dem ausgewählten Ordner frage, würden Sie wohl wie folgt antworten:

C:\Benutzer\Basti\Eigene Bilder

Ich kann Sie beruhigen, diese Angabe ist völlig korrekt, so scheint es. Denn an dieser Stelle täuscht uns Windows 7 bzw. der Windows Explorer.

Denn würden Sie den o.g. Pfad aufrufen wollen, würde Windows eine Fehlermeldung ausgeben, die besagen würde, dass der Ordner nicht existiert! - Wie kann das sein?

Das liegt daran, dass Windows uns die deutsche Sprache nur vortäuscht! Denn der echte Pfad sieht so aus:

win72Bild 2: Der wahre Pfad steht oben

Nach einem Klick in die Adresszeile wird man feststellen, dass der Ordnerpfad komplett nur aus Englischen Wörtern besteht!

Das macht es manchmal umständlich eine Datei zu finden, auch wenn es für den eigentlichen Nutzer angenehmer erscheint!

Wie kann man sich schützen?

ALs Programmierer sollte man seinen Code immer so schreiben, dass es auf allen Windows Versionen lauffähig ist, doch wie macht man das wenn die Ordner immer anders heißen?

Die Antwort ist relativ leicht und lautet "Umgebungsvariable"! Denn Windows übersetzt nicht alle Ordner, sondern nur die so genannten "Special Folders". Das sind Ordner, die für das System von Bedeutung sind!

Dazu gehören der Windows Ordner Selbst, der Systemordner, der Programmordner oder der "Eigene Dateien" Ordner. Aber woher weis ich, ob ein Ordner ein "Special Folder" ist oder nicht?

Das kann man ganz einfach herausfinden, indem man in die Liste der Umgebungsvariablen (Environmentvariables in English) schaut. Diese findet ihr zb so: [Start]+[R] Tippt nun "cmd" ein und drückt auf [ENTER] um in die Eingabeaufforderung von Windows zu gelangen. Nun tippt "set" ein und drückt erneut auf [ENTER].

win73Bild 3: Die Liste mit den Umgebungsvariablen unter Windows

Hier sehr ihr eine komplette Liste mit allen dem Benutzer zugänglichen Umgebungsvariablen. Alternativ könnt ihr auch so vorgehen: [Start] und nun tippt ihr in das Suchfeld von Windows Vista oder 7 "erweitert" ein und lasst Windows ein paar Sekunden suchen, dann klickt ihr auf den Eintrag "Erweiterte Systemeinstellungen Anzeigen", wählt nun oben den Tab "Erweitert" auf und klickt unten auf "Umgebungsvariablen" ihr bekommt folgendes zu sehen:

win74Bild 4: Die Grafische Oberfläche der Umgebungsvariablen

Unter Windows XP Erreicht ihr dieses Fenster mit einem Rechtsklick auf Arbeitsplatz und dann Erweitert!

Auf diese Variablen kann man auch sehr bequem vom Code aus zugreifen, und da diese auf jedem System stimmen hat man keine Probleme zu erwarten!


        '
        '
        'Pfad zum Programmordner
        Dim ProgrammPfad As String
        ProgrammPfad = Environment.GetEnvironmentVariable("ProgramFiles")

Wie man sieht kann man so sehr einfach den Programmordner auslesen.

Windows 7 bietet noch weitere kleine Überraschungen über die ich im Nächsten Teil schreiben werde!

Hat euch diese Beitrag gefallen? Schreibt mir einen Kommentar!

VN:F [1.8.4_1055]
Rating: 3.5/10 (4 votes cast)
3Nov/090

VB.NET: Eigenes Programm mit Windows starten lassen

Oftmals ist es es von Nöten sein eigenes Programm beim Hochfahren von Windows automatisch starten zu lassen. Dies ist nicht wirklich anspruchsvoll aber dennoch sehr nützlich!

Windows bietet uns hier 2 Möglichkeiten dieses Vorhaben umzusetzen. Die erste ist es eine Verknüpfung zu unserem Programm zu erstellen und diese dann im Autostart Verzeichnis zu platzieren.

winstart11Bild 1: Der Windows Autostart Ordner im Startmenü

Dieser Ordner befindet sich unter dem folgendem Pfad:

C:\Users\[BENUTZERNAME]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

Windows führt automatisch alle Dateien aus, die sich in diesem Ordner befinden, nachdem der Startvorgang abgeschlossen ist!

Die zweite (und meiner Meinung nach), bessere Methode ist es, einen entsprechenden Eintrag in der Registry zu setzen. Dies hat auch den Vorteil, dass man später die Verknüpfung nicht suchen und entfernen muss und dass der Benutzer diese nicht ausversehen löscht.

Wenn ihr in den dafür vorgesehenen Ordner schaut werdet ihr feststellen, dass dort (wahrscheinlich) auch andere Programme ihr Unwesen treiben.

winstart2Bild 2: Weitere Autostart Einträge

Diesen Registry Ordner findet ihr im Regestrierungseditor unter folgendem Pfad:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

In dem folgenden Codebeispiel werden wir hier einen Eintrag mit dem Verweis auf unser Programm einfügen.


    Public Sub LoadOnStartup(ByVal DoOrNot As Boolean)

        Dim RegKey As String = "HKEY_CURRENT_USER\Software\" &amp;amp;amp;amp; _
                               "Microsoft\Windows\CurrentVersion\Run"
        If DoOrNot = True Then
            My.Computer.Registry.SetValue _
            (RegKey, "[PROGRAMMNAME]", My.Application.Info.DirectoryPath &amp;amp;amp;amp; _
                                "\" &amp;amp;amp;amp; My.Application.Info.AssemblyName &amp;amp;amp;amp; ".exe")
        Else
            My.Computer.Registry.SetValue _
            (RegKey, "[PROGRAMMNAME]", "")
        End If

    End Sub

Wie man sieht ist es dank .NET nicht wirklich schwer einen Registryeintrag zu erstellen und zu bearbeiten, denn wenn ihr nicht mehr wollt, dass euer Programm mit Windows gestartet wird, löscht ihr den Eintrag einfach oder gebt statt dem Pfad etwas anderes ein.

In dem Code verwende ich den Kern-Schlüssen "HKEY_CURRENT_USER" statt des oben erwähnten "HKEY_LOCAL_MACHINE". Dies heißt nur, dass das Programm nur bei dem User Automatisch starten wird, der diesen Code ausführt. Benutzt man allerdings "HKEY_LOCAL_MACHINE" wird das Programm bei allen Benutzern des Computers automatisch gestartet!

Zur Benutzung: Ruft diese Funktion einfach auf und übergebt True um euer Programm automatisch starten zu lassen, oder False um dies wieder zu unterbinden!

Da dies nur ein Copy & Paste Beispiel ist, habe ich hierfür kein Demoprojekt angefertigt, ich hoffe ihr könnt mir verzeihen! :-)

VN:F [1.8.4_1055]
Rating: 7.0/10 (3 votes cast)
29Okt/090

VB.NET: ICQ Benutzerinformationen auslesen

In Deutschland ist der Instant Messaging Client ICQ seht weit verbreitet. So könnte man doch ab und zu eine Funktion gebrauchen mit der man prüfen kann, ob ein Benutzer grade am PC ist.

Leider schränkt ICQ uns hier sehr ein und bietet keinerlei Schnittstelleninformationen. So müssen die Entwickler berühmter Clients wie QIP, Miranda oder Trillian die Funktionsweise des Protokolls selbst erarbeiten durch Reverse Engeneering!

Ich bin vor ein paar Tagen aber auf ein interessantes Skript gestolpert, dass die ICQ Webseite wohl intern dazu benutzt den Status der User im Forum und auf der eigenen Homepage darzustellen. Und natürlich können wir diesen auch anzapfen!

Das Skript befindet sich unter dieser Adresse: http://www.icq.com/js/pcc.php?Uin=[ICQNUMMER]

Ruft man diesen Link mit einer gültigen ICQ Nummer am Ende auf so erhält man ein großes Wirwar an Informationen die aber leider nicht geordnet dargestellt werden!

Auch wenn es nicht alle Informationen sind, die ICQ über einen speichert, so kann man mit den Daten trotzdem schon was anfangen!

icqcheckBild 1: Das ICQ Tool - und ja: Diese ICQ Nummer gibts wirklich

So kann man neben Status und Namen auch das Bild des Benutzers abfragen. Aber nur das Bild, das der User im Forum verwendet (glaube ich).

Desweiteren kann man nicht von allen Benutzern den Status abfragen. Ich vermute, das liegt daran dass diese Benutzer erst eine Autorisierung verlangen bevor sie den Status preisgeben.

Der Programmierteil beschränkt sich hierbei auf das Filtern der Informationen die man durch den Aufruf des oberen Links bekommt:


    Private Function getICQInfos(ByVal uid As String) As String()
        Dim Infos() As String
        Dim retVal(8) As String
        Dim web As WebClient = New WebClient

        Infos = web.DownloadString("http://www.icq.com/js/pcc.php?Uin=" &amp; uid).Split(vbNewLine)

        'Zeile  - Inhalt
        '3      - fullname
        '6      - userinfo
        '9      - onlinestatus
        '10     - email
        '11     - handynummer
        '13     - homepage
        '14     - icq uin
        '16     - userphoto
        '17     - hausnummer
        '18     - useronlineicon
        '19     - nickname

        'Vor und Nachnamen laden
        retVal(0) = Infos(3).Substring(Infos(3).IndexOf("""") + 1, _
                    Infos(3).Length - 3 - Infos(3).IndexOf(""""))
        'Benutzerbeschreibung7)
        retVal(1) = Infos(6).Substring(Infos(6).IndexOf("""") + 1, _
                    Infos(6).Length - 3 - Infos(6).IndexOf(""""))
        'Online Status als Zahl
        retVal(2) = Infos(9).Substring(Infos(9).IndexOf("""") + 1, 1)
        'E-Mailadresse
        retVal(3) = Infos(10).Substring(Infos(10).IndexOf("""") + 1, _
                    Infos(10).Length - 3 - Infos(10).IndexOf(""""))
        'Homepage
        retVal(4) = Infos(13).Substring(Infos(13).IndexOf("""") + 1, _
                    Infos(13).Length - 3 - Infos(13).IndexOf(""""))
        'Benutzerfoto URL 'jaja ich weis coole formel
        retVal(5) = Infos(16).Substring(Infos(16).IndexOf(""") + 6, _
                    (Infos(16).Length - (Infos(16).IndexOf(""") + 6)) _
                    - (Infos(16).Length - (Infos(16).IndexOf("" "))))
        'User Online Icon URL
        retVal(6) = Infos(18).Substring(Infos(18).IndexOf("""") + 1, _
                    Infos(18).Length - 4 - Infos(18).IndexOf(""""))
        'Nickname
        retVal(7) = Infos(19).Substring(Infos(19).IndexOf("""") + 1, _
                    Infos(19).Length - 3 - Infos(19).IndexOf(""""))

        web.Dispose()

        Return retVal
    End Function

Ich habe hier in dem Beispiel nicht alle Informationen gefiltert, aber für die Demo hier wirds wohl reichen!

Habt ihr auch schon mit solchen ICQ Skripts herumexperimentiert? Schreibt ein Kommentar mit euren Tools.

Das Demoprojekt gibts hier: Download

VN:F [1.8.4_1055]
Rating: 5.0/10 (4 votes cast)
28Okt/090

VB.NET: Dateioperationen mit Fortschrittsanzeige Teil 3 – Wiederaufnahme von Downloads

Wenn man grafische Oberflächen entwickelt wird man irgendwann an dem Punkt kommen wo man Dateien kopieren, verschieben oder herunterladen will. Wenn diese nicht grade wenig und klein sind bietet es sich natürlich an eine Fortschrittanzeige dafür zu erstellen. Damit wird sich diese Serie beschäftigen.

Teil 3 - Wiederaufnahme von Downloads nach einem Abbruch

Wer kennt das nicht, man lädt eine große Datei herunter und plötzlich bricht die Internetverbindung ab. Alles umsonst, und der Download muss neu gestartet werden!

webloadgoon1Bild 1: Das Demoprojekt bei der Wiederaufnahme des Downloads

Viele Downloadmanager heutzutage unterstützen das so genannte "wiederaufnehmen" von Downloads, sodass man nach einem Abbruch nicht die ganze Datei von vorne laden muss.

Doch wie funktioniert das? In diesem Teil werden wir das Projekt aus Beispiel 2 um diese Funktionalität erweitern. Und es ist erschreckend einfach und benötigt nur eine geringe Modifikation!

Zunächst einmal die Theorie. Wenn ihr in den Code aus Teil 2 schaut werdet ihr feststellen, dass beim herunterladen der Datei ein Strom aufgebaut wird, aus dem wir die Daten herunterladen und lokal speichern.

Wenn ihr den Code aus dem Form_Closing() Ereignis löscht, und dann einen laufenden Download durch das Beenden des Programms abbrecht, werdet ihr feststellen, dass die "temporäre" Datei nochimmer auf der Festplatte liegt!

Diese Datei ist natürlich nutzlos, da wir nur eine Teilmenge davon geladen haben. Aber da wir herausfinden können, wieviele Bytes wir schon geladen haben wissen wir schon wo wir wieder ansetzen müssen!

Dementsprechend müssen wir den neuen Download nicht an Stelle 0 im Strom starten, sondern an stelle [Anzahl heruntergeladener bytes].

Ich möchte jetzt nicht den ganzen Code hier posten sondern nur die Schlüsselstelle hier:


        Dim request As HttpWebRequest = HttpWebRequest.Create(url)

        request.Proxy = Nothing
        request.AddRange(CInt(curBytes))

        Dim response As HttpWebResponse = request.GetResponse

        If Not response.StatusCode = HttpStatusCode.PartialContent Then
            'falls der Server wiederaufnahme nicht unterstützt bei 0 anfangen
            curBytes = 0
        End If

Man muss beim erstellen des Requests und noch vor dem Response dem Server mitteilen, ab wo er die Daten schicken soll, da wir ja nicht die ganze Datei brauchen!

Dies machen wir mit dem Befehl request.AddRange(CInt(curBytes)) der dafür sorgt, dass der Stream an der von uns gewünschten Stelle startet!

Leider unterstützen nicht alle Server die Wiederaufnahme von Downloads. So kann es vorkommen, dass der Download nicht fortgesetzt werden kann. Diesen besonderen Fall muss man natürlich behandeln.

Wenn wir die Antwort vom Server bekommen (Response) können wir prüfen, welche Statusmeldung der Server zurückgegeben hat. Dafür benutzen wir die Methode response.StatusCode.

Wenn alles gut gelaufen ist und der Server die Wiederaufnahme zulässt bekommen wir den Status Code 206 - PartialContent. Wenn der Server es nicht unterstützt kriegen wir den Code 200 - OK.

Eine komplette Liste mit den Server Responses findet ihr im MSDN!

Wenn wir den Code 200 bekommen müssen wir die Datei wieder von Null laden und müssen darauf mit der Rücksetzung im Code reagieren!

Ich setze in der Demo noch den Proxy auf Null. Das mache ich, da ich ein paar Probleme hatte und der Stream etwas falsch ankam. Ihr könnt es gerne mal ohne diesen Befehl testen und dann hier berichten.

Um das ganze zu testen könnt ihr euch die Demo laden. Startet dann einfach einen Download und unterbrecht diesen irgendwo in der Mitte. Dann startet das Programm neu und startet den selben Download nochmal.

Ihr werdet nun gefragt, ob ihr diese Datei überschreiben wollt (Standartfrage von Windows) und ob ihr dann den Download fortsetzen wollt. Beides mit "Ja" beantworten.

Nun müsste das Programm den Download wiederaufnehmen.

Das Demoprojekt gibt es hier: Download

Teil 1 - Kopieren und Verschieben von Dateien
Teil 2 - Download von Dateien
Teil 3 - Wiederaufnahme von Downloads nach einem Abbruch
Teil 4 - Upload von Dateien

VN:F [1.8.4_1055]
Rating: 8.8/10 (4 votes cast)
22Okt/090

VB.NET: Dateioperationen mit Fortschrittsanzeige Teil 2 – Download von Dateien

Wenn man grafische Oberflächen entwickelt wird man irgendwann an dem Punkt kommen wo man Dateien kopieren, verschieben oder herunterladen will. Wenn diese nicht grade wenig und klein sind bietet es sich natürlich an eine Fortschrittanzeige dafür zu erstellen. Damit wird sich diese Serie beschäftigen.

Teil 2 - Download von Dateien

Im letzten Teil haben wir gesehen, wie man beim Kopieren von Dateien einen Fortschrittsbalken erzeugt, nun wollen wir das ganze für ein Download Programm umsetzen.

Wer sich schon mal im My-Namespace umgeschaut hat wird sicherlich die Funktion DownloadFile() entdeckt haben. Diese Funktion erleichtert uns das Leben sehr, da diese uns erlaubt mit nur einer Zeile Code eine Datei aus dem Internet zu laden.

Das blöde daran ist, dass wenn die Datei etwas größer ist blockiert der Download den Ganzen Thread sodass dieser nicht mehr reagiert bis der Download abgeschlossen ist! Dies wollen wir ändern und den Downloadvorgang visualisieren.

Das werden wir so ähnlich gestalten, wie in Teil eins, nur etwas Anfängerfreundlicher. (Ich habe gemerkt dass das Beispiel aus Teil 1 doch nicht so das Gelbe vom Eis ist!)

Das Vorgehen dabei ist aber fast das gleiche. Wir erstellen einen Stream zu der Datei die wir herunterladen wollen und einen Stream zu einer Lokalen Datei in die wir die gelesenen Bytes speichern. Klingt doch ganz easy oder?

Dabei werden wir folgende Variablen benutzen:


    Dim timer As Stopwatch          'Stoppuhr zur bestimmung der Downloadgeschwindigkeit
    Dim loaded As Long              'Anzahl na Bytes die in einer Zeiteinheit geladen wurden
    Dim speed As Double             'Downloadgeschwindigkeit in KB/s

    Dim url As String               'Die URL mit der zu ladenden Datei
    Dim des As String               'Zielpfad auf dem lokalen System

    Dim buffer(32768) As Byte       'Puffer für den Download -> Je größer desto schneller der Download

    Dim totBytes As Long            'Größe der zu ladenden Datei
    Dim curBytes As Long            'Bisher geladene Bytes
    Dim readBytes As Long           'Anzehl gelesener Bytes pro Block

    Dim bis As BinaryReader         'Der Strom mit der zu ladenden Datei
    Dim fos As FileStream           'Strom der die Datei lokal speichert

Wie man sieht findet man hier nichts ungewöhnliches. Das einzige, dass neu ist ist die Stopwatch-Variable. Diese benötigen wir später um die Downloadgeschwindigkeit zu ermitteln.


        timer = New Stopwatch

        'Stream zur Datei im Internet erstellen und Lokal
        Dim request As HttpWebRequest = HttpWebRequest.Create(url)
        Dim response As HttpWebResponse = request.GetResponse

        bis = New BinaryReader(response.GetResponseStream)
        fos = New FileStream(des, FileMode.Create, FileAccess.Write)

        totBytes = response.ContentLength

        timer.Start()                       'Mit dem Timer messen wir, wieviele Bytes in der letzten Sekunde heruntergeladen wurden
        While (True)
            readBytes = bis.Read(buffer, 0, buffer.Length)      'Aus dem Download Stream lesen
            If readBytes = 0 Then
                Exit While                                      'Download ist abgeschlossen
            End If

            fos.Write(buffer, 0, readBytes)                     'Geladene Bytes lokal Speichern

            curBytes += readBytes                               'Anzahl gesammt gelesener Bytes erhöhen
            loaded += readBytes                                 'Anzahl der Bytes erhöhen die in der Letzten Sekunde geladen wurden

            If timer.ElapsedMilliseconds >= 1000 Then           'Wenn eine Sekunde vergangen ist
                speed = 0
                speed = FormatNumber(loaded / 1024, 2)          'Geschwindigkeit berechnen
                loaded = 0                                      'und zähler zurücksetzen
                timer.Reset()                                   'den Timer neustarten
                timer.Start()
            End If
            'Die Anzeige im Formular-Thread aktualisieren
            Label1.Invoke(New refreshGUIDel(AddressOf refreshGUI), New Object() {})

        End While

        'Ressourcen Freigeben
        timer.Stop()
        fos.Close()
        bis.Close()

Kommen wir zu dem Kernunterschied. Hier kopieren wir Daten von einem Fremden Rechner (Server) zu dem wir ersteinmal eine Verbindung benötigen! Diese Verbindung können wir mit Hilfe eines HttpWebRequests (Eine Anfrage an den Server) herstellen. Und von dem bekommen wir dann auch eine Antwort in Form eines HttpWebResponse welcher uns dann auch einen Strom zu der angefragten Datei liefert!

Nun folgt der eigentliche Downloadvorgang. Wir lesen den Strom blöckchenweise und speichern ihn auch "gleichzeitig" ab. Da wir wissen wieviele Bytes übertragen wurden können wir auch einen Fortschritt anzeigen und auch die Geschwindigkeit berechnen.

Hier hat sich im Vergleich zu Teil 1 nicht viel getan. Neu ist die Stopwarch die nach jeweils einer Sekunde die Geschwindigkeit berechnet indem es misst wieviele Bytes in der letzten Sekunde übertragen wurden!

downloaderBild 1: Das Downloadprogramm in Aktion

Heraus kommt ein kleines Tool, das eine beliebige Datei herunterladen kann und uns währenddessen mit ein paar Informationen versorgt.

Wie üblich gibts hier das Demoprojekt: Download

Habt ihr Tipps oder Fragen? Zögert nicht und schreibt einen Kommentar oder Mail!

Teil 1 - Kopieren und Verschieben von Dateien
Teil 2 - Download von Dateien
Teil 3 - Wiederaufnahme von Downloads nach einem Abbruch
Teil 4 - Upload von Dateien

VN:F [1.8.4_1055]
Rating: 6.0/10 (2 votes cast)
Get Adobe Flash playerPlugin by wpburn.com wordpress themes