if errorlevel

hilft beim Batchscripting um Fehler während der Ausführung eines Befehls abzufangen. Hier verbirgt sich aber ein Anfängerfehler, über den jeder mal stolpert.

Ein Befehl, der ausgeführt wird, gibt normalerweise einen Wert zurück, wenn er fertig ausgeführt wurde. Dieser Rückgabewert ist normalerweise 0, wenn der Befehl erfolgreich ausgeführt wurde. Fehler werden mit einem positiven Rückgabewert ungleich 0 angegeben. Viele Programme haben für verschiedene Fehler auch verschiedene Rückgabewerte, diese muss uns aber nicht weiter interessieren.

Mit

if errorlevel

fragen wir den Rückgabewert des zuvor ausgeführten Befehls ab.
Ein Beispiel:

md c:\checkdir
if errorlevel 0 echo Test

Was macht diese Befehlskombi? Man könnte denken der Rückgabewert von md (makedir – Verzeichnis erstellen) wird geprüft und wenn der Befehl erfolgreich ausgeführt wurde (errorlevel 0) dann wird „Test“ ausgegeben.
Stattdessen wird aber immer „Test“ ausgegeben, egal ob der Befehl erfolgreich ausgeführt wurde oder nicht. Warum?
Geprüft wird nicht

if errorlevel = X

sondern

if errorlevel >= X

! Demzufolge prüft

if errorlevel 0

nicht nur auf den Wert 0 sondern prüft mit >= 0 auch alle Werte, die größer sind als 0.
Das heißt egal ob ein Programm 0 zurück gibt, 1 oder 213, der Befehl hinter

if errorlevel 0

wird immer ausgeführt.

Korrekt müsste es lauten:

md c:\checkdir
if errorlevel 1 goto fehler
echo befehl erfolgreich
:fehler
echo befehl nicht erfolgreich

Alle Rückgabewerte >= 1 (nicht erfolgreich) werden nun also an die „fehler“ Sprungmarke geschickt. Der Ablauf des erfolgreichen Programmteils erfolgt normal unter der errorlevel Abfrage.

Wichtig ist, dass ihr die Abfrage des Errorlevels ausführlich in eurer Situation testet – der Abfragerückgabewert ist in speziellen Situationen nicht sehr zuverlässig und kann durch andere Komponenten und Code variieren.

Die IP-Einstellungen einer Netzwerkverbindung nicht von Hand sondern mit einem Batch Script machen zu lassen kann mehrere Vorteile haben. Natürlich schließt man dadurch Tippfehler aus und spart auch ein wenig Zeit aber sinnvoller ist der Einsatz bei mehreren Standorten mit unterschiedlichen IP-Einstellungen, zwischen denen man selber oder ein Kollege pendelt. Die IP Settings eines jeden Standorts lassen sich dann einfach per Doppelklick übernehmen.

Hier ein Beispiel Batch Script:

netsh interface ip set address "LAN-Verbindung" static 192.168.178.44 255.255.255.0 192.168.178.1 256
netsh interface ip set dns "LAN-Verbindung" static 192.168.178.10 PRIMARY
netsh interface ip set dns "LAN-Verbindung" static 192.168.178.11 index=2

Achtung: Hier müssen also Name der Netzwerkverbindung und natürlich die Adressen angepasst werden.

Mit diesem Script werden an der Netzwerkverbindung „LAN-Verbindung“ folgende Einstellungen übernommen:
IP-Adresse: 192.168.178.44
Subnetzmaske: 255.255.255.0
Gateway: 192.168.178.1
Gateway-Metrik: 256
DNS 1: 192.168.178.10
DNS 2: 192.168.178.11

Für DHCP bei den IP- als auch den DNS-Einstellungen einfach folgende Zeilen verwenden:

netsh interface ip set address "LAN-Verbindung" dhcp
netsh interface ip set dns "LAN-Verbindung" dhcp

Für Informationen zu den aktuellen Einstellungen reicht der Befehl

netsh interface ip show config

oder ganz klassisch

ipconfig /all

.

Umlaute in Batch-Script Ausgaben sind ja ein bekanntes Problem. Statt ä ö ü oder auch ß erscheinen leider nur sehr kryptische Symbole, dabei kann das aktuelle DOS doch umlaute darstellen.

Aber wie bekommen wir eine makellose Ausgabe am besten realisiert?

Ganz einfach, ihr braucht ein Texteditor, der MS DOS schreiben kann.
Zum Beispiel kann Notepad++ ein Dokument im MS DOS Stil bearbeiten. Dazu könnt ihr einfach die Bearbeitungssprache unter Sprachen -> M -> MS DOS Stil einstellen.
Das Script wird unter Umständen neu geöffnet, die Syntaxgestaltung verschwindet und alle Umlaute (mit dem ß) werden in kryptische Zeichen umgewandelt. Nun könnt ihr alle diese seltsamen Symbole durch die gewollten Umlaute ersetzen.

In der Ausgabe werden diese dann auch endlich normal angezeigt.

Ihr könnt dann in Notepad++ die Sprache wieder auf Batch zurückstellen. Und – bei mir war es zumindest so – danach sollten sogar in dieser Spracheinstellung eingetippte Umlaute korrekt angezeigt werden. Testet es aus.

Dieses Howto als Video:

Jetzt funktioniert der Passwortstärke Analyzer endlich so, wie er soll. Ein Fix von Ahmet hat das Problem behoben, dass die Passwortüberprüfung nach Anzeigen/Verstecken des Passworts beendet hat.

Details:
Jetzt gibt es 2 Eingabefelder, 1 ist jeweils versteckt. Ein Feld ist vom Typ password und eins vom Typ text. Denn durch das Ersetzen des Eingabefeldes mit

replaceWith()

oder

html()

ist auch automatisch der Link zu den Events verloren gegangen. Das Problem wird damit behoben, guter Gedankengang.
Ich sehe das trotzdem als Manko schließlich kann ich mir viele Situationen vorstellen wo viel HTML Inhalt ersetzt werden muss, danach diese eingesetzten Inhalte aber dynamisch verlinkt sein müssen. Ich glaube über diese Thematik werde ich noch öfter stolpern. 🙂
Ich hab den Code entsprechend mit Credits versehen.

Neuer Codeanfang der passwort.js:

$(document).ready(function()  {
$("input[type=checkbox]:first").change(function(){
	/* Made by Ahmet Topal
	* http://basicblogger.de/
	*/
	var nopw = $("#passwrap input:not(.pw)").attr('id');
	var pw = $("#passwrap input.pw").attr('id');
	$("#"+nopw).addClass('pw').fadeIn(0);
	$("#"+pw).removeClass('pw').fadeOut(0);
});
	
$("#passwrap input").keyup(function() {
	/* Made by Ahmet Topal
	* http://basicblogger.de/
	*/
	var passtemp = $('#passwrap input.pw').val();
	$("#passwrap input:not(.pw)").val(passtemp);
		
	ratePW();
});

Auch die .css und .html haben sich leicht verändert, bitte beachten!

So, mein letzter Post ist ohne Beispiel gekommen. Das hatte den Grund, dass ich noch einen Bug in dem Tool war.
Das „Passwort anzeigen“ unterbricht die Analyse Funktion. Einmal betätigt wird das Passwort nicht weiter bewertet. Das hat sicher mit dem Austausch des HTML Inhalts zu tun. Ich habe bereits

html()

und

replaceWith()

probiert. Denke mal ich brauche da eine ganz andere Herangehensweise. @Ahmet, noootfalls nehme ich das showPassword Plugin 😉

Soo, ich habe es nicht gefixt bekommen bis jetzt 😀
Egal, hier ist es: jQuery Passwortstärke Analyzer

Ich habe einen jQuery Passwortstärke Analyser programmiert. Dieser ist natürlich sehr basic und der Code alles andere als optimal oder perfekt. Ich kriege selber Gänsehaut wenn ich ihn sehe. Man könnte so viel Code kürzern, modularisieren, verbessern, auslagern; so viel Design aufhübschen, interaktiver machen und so weiter. Aber die Zeit hab ich einfach jetzt nicht.
Ich empfehle also natürlich professionelle Plugins dieser Art. Den Code zeige ich rein aus informativen und lerntechnischen Gründen.

Wenn ich mal Zeit habe dann würde ich sicherlich probieren, meine Features in etwa wie hier auszubauen. Ein Großteil davon hat sich an 1, 2 Tagen aber nicht realisieren lassen.

Hier der Code und darunter die Erklärung einzelner Zeilen:

Update 05.06. – es gibt mittlerweile eine verbesserte Version 1.2 des Tools, bitte also den neuen Code aus diesem Post beachten!

$(document).ready(function() 
{
$("input[type=checkbox]:first").change(function(){
if($("#passwort").is('.pw')) {
	var passtemp = $("#passwort").val();
	$("#passwrap").replaceWith('<div id="passwrap"><input type="text" id="passwort" class="text" size="30" maxlength="30" /></div>');
	$("#passwort").val(passtemp);
} else {
	var passtemp = $("#passwort").val();
	$("#passwrap").replaceWith('<div id="passwrap"><input type="password" id="passwort" class="pw" size="30" maxlength="30" /></div>');
	$("#passwort").val(passtemp); 
}
});
	
$("#passwort").keyup(function() {
	ratePW();
});

function runde(zahl) {
  var rzahl = (Math.round(zahl * 10) / 10).toString();
  rzahl += (rzahl.indexOf('.') == -1)? '.0' : '0';
  return rzahl.substring(0, rzahl.indexOf('.') + 2);
}

function ratePW() 
{
var strength = 0,
klein = 0,
cap = 0,
zahl = 0,
zeichen = 0;

var passlength = $("#passwort").val().length;
var input = $("#passwort").val();

$("#length").text("Passwortlänge: "+passlength+" Zeichen");
	
for(var i=0,l=passlength;i<l ;i++)
{
var x = input.charCodeAt(i);
if ( x >= 97 && x < = 122 ) {
	klein += 1;
	if ( klein > 4 ) {
		strength += 0.2;
	} else {
		strength += 1;
	}
	} else if ( x >= 65 && x < = 90 ) {
		cap += 1;
		if ( cap > 4 ) {
			strength += 0.6;
		} else {
			strength += 2;
		}
		} else if ( x >= 48 && x < = 57 ) {
			zahl += 1;
			if ( zahl > 4 ) {
				strength += 1;
			} else {
				strength += 3;
			}
			} else if ( x >= 32 && x < = 47 || x >= 123 && x < = 126 || x >= 91 && x < = 96 || x >= 58 && x < = 64  ) {
				zeichen += 1;
				if ( zeichen > 4 ) {
					strength += 2;
				} else {
					strength += 4;
				}
				} else {
					alert("Fehler");
					}
}

var rstrength = runde(strength);
$("#strength").text("Passwortstärke: "+rstrength);
if (rstrength == 0.0) { 
	$("#cover").css({'width':'208px','left':'1px'});
	} else if (rstrength > 0.0 && rstrength < = 4.0) {
		$("#cover").css({'width':'173px','left':'35px'});
		} else if (rstrength > 3.0 && rstrength < = 8.0) {
			$("#cover").css({'width':'139px','left':'69px'});
			} else if (rstrength > 6.0 && rstrength < = 12.0) {
				$("#cover").css({'width':'105px','left':'103px'});
				} else if (rstrength > 9.0 && rstrength < = 16.0) {
					$("#cover").css({'width':'71px','left':'137px'});
					} else if (rstrength > 12.0 && rstrength < = 20.0) {
						$("#cover").css({'width':'37px','left':'171px'});
						} else if (rstrength > 15.0) {
							$("#cover").css({'display':'none'});
							} 
};	
}); //$(document).ready

Zeile 3:
Das Ändern einer Checkbox lässt sich mit

.change()

ganz leicht abfangen, hier wird die Checkbox durch eine ID identifiziert:

$("#hide").change(function() {

Man könnte auch

$("input[type=checkbox]:first").change

nehmen; wie immer führen viele Wege nach Rom,

.change()

ist jedenfalls an dieser Stelle perfekt um Buttons aus dem Weg zu gehen.

Zeile 4:
Prüfen, ob ein Element eine Klasse besitzt.

is()

bietet sich da an.

if($("#passwort").is('.pw')

Zeile 5:

.val()

fragt den Inhalt eines Elements ab, Inhalt auslesen. Mit

.val("bla")

(Zeile 7) kann man den Inhalt setzen.

var passtemp = $("#passwort").val();

Zeile 6:

replaceWith()

ersetzt den Knoten, der angesprochen wird mitsamt Inhalt mit dem neuen Inhalt. Wird

replaceWith()

auf einen Tag mit ID angewendet so verschwindet auch der Tag mit der ID. Daher habe ich in den neuen Inhalt diesen Tag mit drin.

$("#passwrap").replaceWith('<div id="passwrap"><input type="text" id="passwort" class="text" size="30" maxlength="30" /></div>');

Ich glaub das könnte man mit

append()

,

html()

oder anderen inhaltsverändernden Funktionen eleganter lösen aber mein Beispiel ging in meinem Kopf am schnellsten umzusetzen, bei anderen Methoden hätte ich erstmal nochmal lesen müssen ^^

Zeile 15-17:
Beim Tastendruck im Textfeld mit der ID passwort wird die Funktion

ratePW()

ausgeführt.

$("#passwort").keyup(function() {
	ratePW();
});
.keydown()

und

.keypress()

sind hier nicht geeignet. Testet mal aus, wie es sich dann verhält.

Zeile 19-23
Das Runden einer Zahl, in diesem Fall auf 1 Nachkommastelle. Full Credits an die Herren hier, denn von dort habe ich den Code geklaut. Hatte nicht die Nerven das selber zu schreiben. Danke 🙂

function runde(zahl) {
  var rzahl = (Math.round(zahl * 10) / 10).toString();
  rzahl += (rzahl.indexOf('.') == -1)? '.0' : '0';
  return rzahl.substring(0, rzahl.indexOf('.') + 2);
}

Wenn vorhanden wird „.0“ auch angezeigt. Ich überlege noch ob das besser aussieht als ausblenden. Weil wenn mit Nachkommastellen dann eigentlich ja immer. Egal, keine Zeit 😀

Zeile 33
Wie oben beschrieben komme ich mit

.val()

an den Inhalt des Eingabefelds und mit

.length()

an die Anzahl der Zeichen, die Länge.

var passlength = $("#passwort").val().length;

Zeile 34,38-40:
Jedes mal, wenn eine Taste in das Eingabefeld eingetragen wird, bekommt

input

den Inhalt des Textfelds neu zugewiesen. Durch die Schleife wird jedes Zeichen dieser Zeichenkette einzeln durchlaufen. Die letzte Zeile weist x den dezimalen Charcode des Zeichen zu.

var input = $("#passwort").val();
for(var i=0,l=passlength;i<l ;i++)
{
var x = input.charCodeAt(i);

Ich hatte erst mit

.Number()

und

.parseInt()

probiert an den dezimalen Charcode zu kommen, kam immer NaN bei raus. Weiß einer wieso? Bin mir nicht so sicher, was da im Hintergrund abläuft. Bei Google findet man zu 90% diese 2 Funktionen, nur ganz selten die

.charCodeAt()

.

Zeile 41-71:
Ich spar es mir den Code hier nochmal zu posten. Die Zeilen überprüfen, welcher Typ Zeichen der zwischengespeicherte Char ist. Ich weiß, das if if else Chaos ist tödlich. Zudem sind viel zu viel Zeichen erlaubt. Die Fehlerbehandlung wie z.B. bei Umlauten ist noch nicht fertig. Es gehen auch Zeichen, die normalerweise bei Passwörtern nicht erlaubt sind. Viele Details die jemand mit Langerweile besser machen würde 😉

Ein verbautes Gimmick: Wird eine Zeichenart mehr als 4 Mal benutzt gibt es Abzüge in der Wertung. Damit soll die Variation der Zeichentypen gefördert werden. Schrecklich gelöst 😀

klein += 1;
   if ( klein > 4 ) {
	strength += 0.2;
   } else {
	strength += 1;
   }

Zeile 74:
Wie oben beschrieben, rundet den Wert.

var rstrength = runde(strength);

Zeile 76-90:
Was in diesem Codeblock passiert ist mir wieder etwas peinlich. Ginge wahrscheinlich kürzer und besser, aber es funktioniert ^^
Mit

.css()

setze ich je nach Wertung die CSS Eigenschaften des #cover DIVs. Dies ist ein grauer Balken über dem eigentlichen, bunten Balken. Dieser graue Balken wird Stück für Stück kleiner, bis er bei über 20 Punkten ganz ausgeblendet wird. Die meisten vermuten, man habe nur einen farbigen Balken, der immer größer wird. Aber ich glaube das ist schwerer zu realisieren als 2 Balken. einer davon überdeckendend.

$("#cover").css({'width':'208px','left':'1px'});
  $("#cover").css({'width':'173px','left':'35px'});
    $("#cover").css({'width':'139px','left':'69px'});
      //..
        $("#cover").css({'display':'none'});

So, das wars. Eigentlich schon ein tolles Ding. Man kann natürlich auch eins der hunderten jQuery Plugins nutzen, die es mittlerweile gibt wie Sand am Meer. 😉

Und, wie stark ist euer Passwort?

Als kleine Vorbereitung den Artikel von gestern über PixelSearch lesen, wenn ihr den noch nicht kennt.

Zusätzlich zu PixelSearch spielt PixelGetColor eine sehr wichtige Rolle beim Automatisieren von komplexeren Aufgaben. Wie der Name der Funktion schon deutlich macht wird die Farbe eines Pixels abgefragt. Das Prinzip ist also recht simpel:

PixelGetColor(x, y)

liefert den dezimalen Farbwert des Pixels mit den Koordinaten x und y. Da wir bei PixelSearch und auch sonst aber öfter mit den hexadezimalen Farbwerten arbeiten bietet es sich an PixelGetColor immer mit der Funktion Hex zu kombinieren:

Hex(PixelGetColor(x, y),6)

Hex wandelt den übergebenen Wert um, 6 gibt die Länge des hexadezimalen Rückgabewerts an (bis zu 8).
Das Ergebnis von

Hex(PixelGetColor(x, y),6)

auf einem bestimmten Pixel losgelassen ist eine simple Zeichenkette wie „A3BB4C“ und kann daher auch ganz einfach so abgefragt werden:

If Hex(PixelGetColor($x, $y),6)="A3FFBC" Then
   do something
EndIf

Ansonsten kommt nicht viel dazu, es wird nur etwas konkreter.
Und zwar geht es um dieses geniale Flash Game hier: Curveball.
Vielleicht kennen es einige von euch ja. Die Grafik des Spiels ist ebenso bahnbrechend wie die Spielidee. Ein Wunder, dass es noch kostenlos ist!
Aber Spaß beiseite, das Spiel eignet sich suuper zum üben dieser Funktionen.

Der Hauptteil des Bots ohne Kommentare sieht in etwa so aus:

MsgBox(0,"Ecke oben links","Führe die Maus über die Ecke des Flash-Games oben links, du hast " & ($waittime/1000) & " Sekunden.")
Sleep($waittime)
$ol = MouseGetPos()
$center = PixelSearch($ol[0],$ol[1],$ol[0]+472,$ol[1]+315, 0xFFFFFF)
while True
	If Hex(PixelGetColor($center[0]+170,$center[1]+110),6)="FFFFFF" Then
		MouseClick("left",$center[0]+170,$center[1]+110,1,1)
	EndIf
	If Hex(PixelGetColor($center[0]+170,$center[1]+110),6)="EFFFEC" Then
		MouseClick("left",$center[0]+170,$center[1]+110,1,1)
	EndIf
	$Ballposition = PixelSearch($ol[0],$ol[1],$ol[0]+472,$ol[1]+315, 0xF0FFED, 2, 1)
	If Not @error Then
		MouseMove( $Ballposition[0], $Ballposition[1], 1)
	EndIf
WEnd

Simpel aber äußerst effektiv. Wie im letzten Post gestern schon geschrieben; das ganze PixelSearch-relative Variablen-PixelGetColor-Gedöns zu schreiben kostet erstaunlich viel Zeit. Es sieht so simpel aus aber bei jedem Spiel muss man theoretisch komplett von vorn anfangen. Überlegen, ob man Pixel sucht, relative Koordinaten abfragt und ganz viel Kleinkram. Aber ist das Werk vollbracht ist es natürlich viel mächtiger als wenn der User jedes Mal am Anfang alle Koordinaten übergeben muss.

Interessiert, wie es aussieht? Dann Spielseite geöffnet und mein Script gezogen:
Download section
CurveBot.exe
oder
CurveBot.au3 (mit all meinen Tests, Kommentaren etc, die nötig waren, bis ich den Bot funktionstüchtig fertig hatte)

Ich hoffe ihr konntet was lernen!