18. August 2011: Desktop-Spielereien
Bei manchen Dingen, wie zum Beispiel den Windows Gadgets bin ich immer wieder hin und her gerissen: Sind sie nützlich oder ablenkender Spielkram? In den meisten Fällen trifft wohl eher letzteres zu. Allerdings hat mich ein Artikel im SAP Developer Network dann doch auf eine interessante Idee gebracht: Wieso nicht den KPI, nach denen man gemessen wird (und sich nie anschaut), die benötigte Aufmerksamkeit verschaffen indem man sie mittels eines Gadgets von einem Pull- zu Push-Medium umwandelt?
Gedacht, getan! In diesem Falle auch recht einfach, denn die Desktop Gadgets sind nicht mehr als mit JavaScript angereichertes HTML. Und da ich ja bereits kurz zuvor einen XML-Export aus SSRS heraus realisiert hatte, war auch dieser Teil kein Problem. Und so hatte ich nach kurzer Zeit ein funktionsfähiges Gadget erstellt, das mir nun alle wichtigen Informationen verdichtet zur Verfügung stellt – ganz automatisch und recht dezent.
Schaut man in die Design Guidelines stellt man fest, dass das auch genau der Sinn und Zweck von Gadgets ist: Informationen zu sammeln, aufzuarbeiten und auf einfachste Art und Weise zur Verfügung zu stellen. Und das machen sie dann auch sehr gut. Allerdings sind sie dadurch zwangsweise sehr individuell und auf spezielle Anforderungen zurecht geschnitten. Wodurch ein Großteil der Online angebotenen Gadgets dann doch wieder nur Spielkram ist.
14. Juli 2011: Warum kompliziert...
Es gibt Tage, an denen man die Welt nicht mehr versteht. Letztens war einer dieser Tage. Ich programmierte ein kleines Tool um Labels auf einem Zebra Drucker auszugeben. Dachte ich Anfangs noch das die Erstellung des Layouts in ZPL die größte Herausforderung werden würde, wurde ich alsbald eines besseren belehrt.
ZPL – das sei an dieser Stelle ausdrücklich erwähnt – ist eine schnörkellose, schnell erlernbare Beschreibungssprache. Hat man sich erst einmal an die Syntax gewöhnt, kann man in kürzester Zeit ansprechende Layouts erstellen. Das man die Anweisungen in Klartext via TCP/IP direkt an den Drucker übergeben kann, macht es auch sehr angenehm die Schnittstelle in eigenen Programmen zu implementieren – ganz gleich welche Sprache man benutzt.
So verwundert es im Nachhinein nicht wirklich, dass dies nicht die befürchtete Herausforderung darstellte. Nun sollte das Tool noch Daten aus einem MS SQL Server laden um diese in das Label-Layout einzufügen. Es ist nicht mein erstes Programm, dass Daten aus einem MS SQL Server laden sollte – und um die Dinge noch einfachere zu machen wählte ich VB.NET als meine Programmiersprache. Doch hier begann die Verzweiflung zuzuschlagen…
Da ich keinen direkten Zugriff auf die Datenbank hatte, musste ich den Umweg über die SSRS gehen. Naiv wie ich bin, ging ich davon aus das dies kein Problem darstellen sollte – gibt es doch entsprechende Objekte und Klassen im .NET Framework. Und siehe da: Man kann sogar mit wenigen Mausklick eine Referenz auf einen SSRS Server anlegen (wenn man die URL kennt und manuell entsprechend aufbereitet):
Aber… da habe ich wohl zu einfach gedacht. Denn trotz mannigfaltiger Ansätze, dem quer-lesen dutzender Artikel und des testens nahezu jeder Funktion der ReportingService2005-Klasse musste ich nach zwei Tagen aufgeben. Zwar konnte ich den Server ansprechen und auch diverse Aktionen durchführen – allein Daten auszulesen war mir nicht möglich. Und darum ging es ja nun schließlich.
Also besann ich mich auf eine althergebrachte Methode: XML. Und ein XML-Export stellt für die SSRS kein Problem dar (wenn man die URL entsprechend manuell aufbereitet). Hier also meine kleine Funktion für all jene, die gegebenenfalls in dieselbe Bredouille geraten:
Dim url As String = _
<ServerURL> + _
<ReportPath> + _
"&rs:Command=Render&rs:Format=XML&" + <ParameterName> + "=" + <ParameterValue>
Dim httpReq As WebRequest = _
WebRequest.Create(url)
With httpReq
.Credentials = CredentialCache.DefaultCredentials
End With
Dim httpDoc As WebResponse
Try
httpdoc = httpReq.GetResponse()
Catch ex As Exception
Debug.Print(ex.Message)
Return False
End Try
Dim xmlDoc As New XmlDocument()
Dim xmlNodes As XmlNodeList
Dim xmlNode As XmlNode
Dim xmlAttr As XmlAttribute
Try
xmlDoc.Load(httpDoc.GetResponseStream())
Debug.Print(xmlDoc.InnerXml)
Catch ex As Exception
Debug.Print(ex.Message)
Return False
End Try
Return True
End Function
14. März 2011: Zählen für Anfänger
Unglücklicher Weise musste ich heute eine Datenbank migrieren – oder eigentlich eher kopieren. Denn so ein SQL Server Express bietet leider wenig Möglichkeiten die Daten strukturiert zu extrahieren. Nachdem ich also die Datenbank mit dem Microsoft SQL Server Management Studio auf einen richtigen SQL Server umziehen konnte, wurde ich mit einem merkwürdigen, nicht aussagekräftigen Status abgespeist:
Stopped ist weder Fisch noch Fleisch, daher wollte ich zumindest die Anzahl der Datensätze vergleichen. Wie sich herausstellte ist das gar nicht mal so einfach. Aber mit ein wenig Tricksereien (und SQL Injection) geht auch dies:
declare @TotalNumRows int, @CurNumRows int, @CurTableName varchar(50), @sql varchar(4000)
declare TotalNumRows_Cursor Cursor FOR
SELECT table_name FROM information_schema.TABLES WHERE table_type='BASE TABLE'
SET @TotalNumRows = 0
open TotalNumRows_Cursor
fetch next FROM TotalNumRows_Cursor
while @@FETCH_STATUS = 0
begin
fetch next FROM TotalNumRows_Cursor INTO @CurTableName
SELECT @sql = 'select * from [' + @CurTableName +']'
exec(@sql)
SELECT @TotalNumRows = @TotalNumRows + @@RowCount
End
close TotalNumRows_Cursor
Print @TotalNumRows
deallocate TotalNumRows_Cursor
go
Achja, bei besagtem SQL Server Express kann man sich übrigens mit dem kleinen Programm qsql.exe an der Datenbank via SQL Prompt anmelden. Auch das muss man erst einmal wissen.
2. März 2011: Ein Bildschirm wie im Film
Was tut man am besten um sich in eine Sprache einzuarbeiten? Richtig! Kleine, meist unnütze Applikationen schreiben. Zum Beispiel ein Skript, dass den Inhalt von Dateien anzeigt – ganz so wie es einem in vielen Filmen und TV-Serien täglich gezeigt wird.
$sleep_time = 150
$max_size = 4 * 1024 * 1024
function Get-HexDump($path){
$width = 15
Get-Content -encoding byte $path -readCount $width -totalCount $max_size | ForEach-Object {
$characters = $_
if (($characters -eq 0).count -ne $width){
$hex = $characters | ForEach-Object {
" " + ("{0:x}" -f $_).PadLeft(2,"0")
}
$char = $characters | ForEach-Object {
if ([char]::IsLetterOrDigit($_))
{[char] $_ }else{ "." }
}
"$hex $char"
start-sleep -milliseconds 10
}
}
}
foreach ($i in Get-ChildItem . -recurse) {
if (!$i.PSisContainer) {
if($text_types -contains $i.Extension){
get-content $i.fullname | foreach-object { echo $_; start-sleep -milliseconds $sleep_time }
}else{
#Get-HexDump($i.fullname)
}
}
}
Richtig professionell wird es allerdings erst mit der Hex-Anzeige für binäre Dateien (oder, um genau zu sein, nicht-definierte Datei-Endungen). Die Entsprechende Funktion habe ich auf PowerShell.com gefunden.
Wer mag darf es sich gerne herunterladen. Falls man sich mit der PowerShell beschäftigen will (was ich jedem IT’ler mit Windows-Kontakten nur nahelegen kann), sollte allerdings versuchen es selbst umzusetzen. Man lernt dabei eine Menge!
21. Januar 2011: Bosch bei Channel9
Über was man manchmal so stolpert:
Leider wird Silverlight für die Darstellung benötigt.
1. November 2010: Ein Filesystem in Excel
Vor kurzem musste ich die Datei- und Ordner-Struktur unserer File-Server abbilden (mit Zeitstempel der letzten Änderung). Idealer Weise in einer Form, in der man die Daten in einer Tabellenkalkulation weiter bearbeiten konnte. Mit Standard-Mitteln war zu viel manueller Aufwand involviert und die üblichen Skriptsprachen waren zu unflexibel. Daher habe ich meine reichlich angestaubten Java-Fähigkeiten bemüht und ein kleines Tool dafür geschrieben:
public static void main(String args[]){
String root = ".";
if(args.length > 0)
root = args[0];
FileCrawler fc = new FileCrawler(root);
}
java.io.FileWriter fout;
java.text.SimpleDateFormat dformat;
public FileCrawler(String root){
try{
this.fout = new java.io.FileWriter("FileCrawler.txt");
} catch(java.io.IOException e){
System.err.println("Could not write to FileCrawler.txt, using Console...");
}
this.dformat = new java.text.SimpleDateFormat("M/d/y h:m:s a");
this.crawl(root);
try{ this.fout.close(); } catch(java.io.IOException e){ }
}
private void crawl(String path){
java.io.File root = new java.io.File(path);
if(!root.exists() && !root.isDirectory()){
System.err.println("Invalid path: " + path);
return;
}
try{
java.io.File files[] = root.listFiles();
for(int i = 0; i < files.length; i++){
if(files[i].isDirectory())
this.crawl(root.getPath() + java.io.File.separator + files[i].getName());
else
this.writeFile(path, files[i].getName(), files[i].lastModified());
}
} catch(java.lang.Exception e){
System.err.println("Access denied: " + path);
}
}
private void writeFile(String path, String file, long timestamp){
String modified = this.dformat.format(new java.util.Date(timestamp));
String msg = path + "\t" + file + "\t" + modified;
try{
this.fout.write(msg + "\n");
} catch(java.io.IOException e){
System.out.println(msg);;
}
}
}
Es nimmt einen zu scannenden Pfad als Parameter entgegen und schreibt die Ergebnisse als CSV-Datei weg. Vielleicht hilft es ja jemandem weiter. Und bedenken: Excel 2003 kann nur bis zu 46500 Zeilen verwalten!
19. Juli 2010: Festplatten-Horror
Wenn jemand den Gang zur Kaffeemaschine dazu ausnutzt die Email-Signatur eben jenes Koffein-Junkies zu ändern, ist das amüsant. Handelt es sich bei dem Opfer jedoch um den lokalen IT-Verantwortlichen, ist es fahrlässig. Und da ich der Geschädigte war, musste ich einfach zurück-sticheln.
Am nächsten Morgen wurde der Täter von einem kleinen Bildschirm begrüßt, der ihn darüber informierte das seine Festplatte gelöscht würde. Sehr zum Gefallen seines Chefs, der auch schon des öfteren das Opfer geben musste.
Er selbst fand es übrigens auch sehr amüsant. Komisch nur, dass sich passend dazu ueber das Wochenende die Festplatte meines Laptops zerlegt hat. Heute früh wurde ich von einem unschönen Error loading Operating System begrüsst. Ein Schelm wer böses dabei denkt!
Für den Fall, dass jemand einen ähnlich gelagerten Scherz vorhat:
echo Local Security has been compromised!
echo Performing Emergency System Cleansing, please stand by...
set randID=5623478
set loopcount=0
:loop
call :genrandid
echo Wiping Sector x%randID%
sleep 1
set /a loopcount=%loopcount% + 1
if %loopcount%==30 goto endloop
goto loop
:genrandid
SET /a randID=%randID% + 1
SET /a randID=%randID% * 214013 + 2531011
SET /a randID=%randID% ^>^> 16 ^& 0x7FFF
goto eof
:endloop
echo ...
echo Waerst du bloss nett zu deinem Admin gewesen,
echo er haette dir helfen koennen...
pause
echo BeNICE!
sleep 5
:eof
14. Februar 2010: PHP füttern
Vor geraumer Zeit hatte ich schon mal eine RSS-Reader Klasse in PHP vorgestellt. Wie ich mittlerweile gelernt habe, ist es mit PHP5 nicht mehr nötig selbst dem Code auszulesen und zu interpretieren. Es gibt dort die schöne Klasse DOMDocument, die einem diese Arbeit abnimmt. Und das auch noch recht elegant:
$reader->load($url) || die('Could not read Feed');
foreach($reader->getElementsByTagName('entry') as $item)
$data[] = $item->getElementsByTagName('title')->item(0)->childNodes->item(0)->nodeValue;
Et voilà, man hat alle Titel eines RSS-Feed in seinem Array versammelt. Praktisch! Gedacht ist die Klasse für XML, daher kann man damit noch sehr viel mehr anstellen. Zum Beispiel SOAP. Aber dazu später mehr.
5. März 2009: Vom Consultant zum Experten
Ich bin ja gerade wieder dabei mich ein wenig mit meinem alten Arbeitsumfeld SAP zu beschäftigen. Erschreckend wie es ist nach gut und gern anderthalb Jahren immense Wissenslücken bei sich selbst zu erkennen, so interessant ist es doch auch geblieben. In diesem Zusammenhang lernte ich letztens auch Puneet Suppal kennen. Ein Name, der mir bis vor kurzem noch gänzlich unbekannt war. Dann habe ich einen Webcast der SAP teched 2007 mit dem interessanten Titel How To Transform from an IT, Application, or Business Consultant to a Business Process Expert gefunden, bei dem er einer der Vortragenden war.
Um es kurz zu machen: Er hat mir deutlich imponiert. Im Jahr 2007, als die Stiftung, bei der ich mein täglich Brot verdient habe, gerade den Großteil des Rollouts eines reichlich veralteten SAP-Releases hinter sich gebracht hat, steht dieser Mann auf der Bühne und propagiert einen Systemwechsel in der IT. Weg von der Anpassung der Unternehmen auf ein Softwareprodukt hin zur flexiblen IT, die sich den Bedürfnissen und Besonderheiten ihrer Nutzer anpasst. Und dabei die Vorteile einer heterogenen Systemlandschaft für sich nutzt statt sie in einem einzelnen System zu harmonisieren.




