Archiv

Archive for the ‘Allgemein’ Category

Automatische Applikationsverteilung mit Powershell

Herausforderung

Damit wir zukünftig Script-basiert unsere Applikation und die damit verbundenen Produkte automatisch verteilen wollen, habe ich, auftrund der Flexibilität der Powershell ein entsprechendes Script erstellt.

Dieses Script verteilt unter anderem:

  • Dienste
  • Anwendungen
  • Webseiten

Ziele

Folgende Ziele sollen dafür erreicht werden:

  • Die Dienste werden konfiguriert und mit der entsprechenden Datenbankverbindung gestartet (Entwicklungs-, Integrations- oder Produktionsumgebung).
  • Gleiches Ziel gilt für die Anwendung
  • Gleische Ziel gilt auch für die Webseite

Durchführung

Die Anwendungen und die Webseiten übrprüfen beim Start in welchem Ordner sie sich befinden und wählen automatisch die korrekte Konfiguration aus. Dies gilt nicht für die Dienste, also müssen die .config Dateien nach dem Verteilen angepasst werden, sodass der Dienst auf die richtige Datenbank verbinden kann.

Hierzu wird das folgende Powershell Script erstellt, welches Schritt für Schritt erläutert wird.

Vorbereitung

Das SetUp des Scriptes sieht wie folgt aus:

param([Parameter(Mandatory=$true)][string]$environment, [Parameter(Mandatory=$true)][string]$buildPath)

$server = [string]::Empty;
$deployPath = [string]::Empty;
$dbServer = [string]::Empty;
$global:session = $null;

if($environment.Equals('Entwicklung')){
    $server = "Entwicklungsserver-01";  
    $deployPath = "\\EntwicklungsZielServer-01\D$\Produkt";      
    $dbServer = "EntwicklungsDbserver-01";
    $session = New-PSSession -ComputerName $server
}elseif($environment.Equals('Integration')){
    $server = "Integrationsserver-01";  
    $deployPath = "\\Integrationsserver-01\D$\Produkt";      
    $dbServer = "Integrationsserver-01";
    $session = New-PSSession -ComputerName $server;
}elseif($environment.Equals('Production')){
    $server = "Produktionsserver-01";  
    $deployPath = "\\Produktionsserver-01\D$\Produkt";      
    $dbServer = "Produktionsserver-01";
    $session = New-PSSession -ComputerName $server;
}

Das SetUp überprüft an der Stelle, welcher Parameter am Anfang mit gegeben worden ist und stellt die Werte dementsprechend zusammen.

Verteilung der Benutzerapplikation

In unserem Fall ist diese Applikation eine Desktop-Applikation, die vom entsprechenden Share aus gestartet wird. Aufgrund in welchem Ordner diese liegt, wird dann die richtige Verbindungszeichenfolge genommen. Die Funktion sieht so aus:

Function DeployProduct(){   
        
    Write-Host('Deploying ' + $buildPath + ' in ' + $environment);

    Write-Host('Deploy Produkt 01');

    if($environment.Equals('Entwicklung'))
    {
        copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "Produkt-01")) -Recurse -Force -Destination "\\Share-01\DEVELOPMENT";
    }
    elseif($environment.Equals('Integration'))
    {
        copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "Produkt-01")) -Recurse -Force -Destination "\\Share-01\INTEGRATION";
        Write-Host('CleanUp xml and pdb files');
        Get-ChildItem -Path "\\Share-01\Produkt-01" -Recurse -Force -Include '*.pdb', '*.xml', '*sccm*exe', '*.nupkg', '*.nuspec' | Remove-Item -Force;
    }
    elseif($environment.Equals('Production'))
    {
        copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "Produkt-01")) -Recurse -Force -Destination "\\Share-01\PRODUCTION";
        Write-Host('CleanUp xml and pdb files');
        Get-Item -Path "\\Share-01\PRODUCTION\Produkt-01" -Recurse;
    }
}

Somit hätten wir die Applikation unseres Produktes verteilt.

Dienstverteilung

Bei der Dienstverteilung gibt es einen Fallstrickt, den ich hier vorenthalten möchte und zwar MUSS man, wenn man die .config Datei anpassen will, diese wie folgt speichern.

(Get-Content -Path $_.FullName).Replace('SAIFC1-AISQLD-03', $dbServer) | Out-File -FilePath $_.FullName -Force -Encoding utf8;

Ganz wichtig hierbei ist, dass man die Datei im UTF-8 Format speichert. Ansonsten kann es sein, dass man den Fehler ‚Side-by-Side‘ erhält.

Nun die ganze Verteilung der Dienste, wie ich sie vorgenommen habe:

Stoppen der Dienste

Function StopServices(){
    Get-Service -ComputerName $server -Include "*%DienstName%*" | Stop-Service -Force;    
}

Kopieren des Dienstes

Function ServiceDeployment(){      
    if($environment.Equals('Entwicklung'))
    {        
        copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "DailyService")) -Recurse -Force -Destination $deployPath;
    }
    elseif($environment.Equals('Integration'))
    {
        copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "DailyService")) -Recurse -Force -Destination $deployPath;
        Write-Host('CleanUp xml and pdb files');
        Get-ChildItem -Path $deployPath -Recurse -Force -Include '*.pdb', '*.xml', '*sccm*exe', '*.nupkg', '*.nuspec' | Remove-Item -Force;
    }
    elseif($environment.Equals('Production'))
    {
        copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "DailyService")) -Recurse -Force -Destination $deployPath;
        Write-Host('CleanUp xml and pdb files');
        Get-Item -Path $deployPath -Recurse -Force -Include '*.pdb', '*.xml', '*sccm*exe', '*.nupkg', '*.nuspec' | Remove-Item -Force;
    }    
}

Änderung der Verbindungszeichenfolge

Function ChangeConnectionStrings(){
    
    Get-ChildItem -Path $deployPath -Filter "*.config*" -Recurse | ForEach-Object{                     
        (Get-Content -Path $_.FullName).Replace('EntwicklungsDbServer-01', $dbServer) | Out-File -FilePath $_.FullName -Force -Encoding utf8;        
    }
}

Starten des Dienstes

Function StartServices(){
    Get-Service -ComputerName $server -Include "*%DienstName%*" | Start-Service;    
}

Fast haben wir es geschafft.

Verteilung der Webseite

Da die Webseite wie auch die Applikation weiss mit welchem Datenbankserver sie sich verbinden muss, wenn sie in einem bestimmten Ordner liegt, muss man hier nur folgende Aktivitäten durchführen:

  • Stoppen der jeweiligen Webseite
  • Kopieren des Inhaltes der Webseite
  • Starten der Webseite
Function DeployWebSite(){
$session = New-PSSession -ComputerName InternetServer-01;
    if($environment.Equals('Entwicklung'))
{
    Invoke-Command -Session $session -ScriptBlock { Stop-Website -Name Web-Entwicklung };
    copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "Web-Entwicklung\_PublishedWebsites\Web-Entwicklung")) -Recurse -Force -Destination "\\InternetServer-01\D$\WebSites\Development";
    Invoke-Command -Session $session -ScriptBlock { Start-Website -Name Web-Entwicklung };
}
elseif($environment.Equals('Integration'))
{
    Invoke-Command -Session $session -ScriptBlock { Stop-Website -Name Web-Integration };
    copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "Web-Integration\_PublishedWebsites\Web-Integration")) -Recurse -Force -Destination "\\InternetServer-01\D$\WebSites\Integration";
    Write-Host('CleanUp xml and pdb files');
    Get-ChildItem -Path "\\InternetServer-01\D$\WebSites\Integration" -Recurse -Force -Include '*.pdb', '*.xml' | Remove-Item -Force;
    Invoke-Command -Session $session -ScriptBlock { Start-Website -Name Web-Integration };
}
elseif($environment.Equals('Production'))
{    
    Invoke-Command -Session $session -ScriptBlock { Stop-Website -Name Web-Produktion };
    copy-Item -Path (Get-Item -Path (Join-Path -Path $buildPath -ChildPath "Web-Produktion\_PublishedWebsites\Web-Produktion")) -Recurse -Force -Destination "\\InternetServer-01\D$\WebSites\Production";
    Write-Host('CleanUp xml and pdb files');
    Get-ChildItem -Path "\\InternetServer-01\D$\WebSites\Integration" -Recurse -Force -Include '*.pdb', '*.xml' | Remove-Item -Force;
    Get-Item -Path "\\InternetServer-01\D$\WebSites\Production" -Recurse;
    Invoke-Command -Session $session -ScriptBlock { Start-Website -Name Web-Produktion };
}
}

Aufgrung dessen, dass der Windows Server 2012R2 bereits die Module für die Administration des IIS mittels Powershell instaliert hat, wird hier eine Remote-Session eröffnet, damit dann das Kommando remote ausgelöst werden kann. (ACHTUNG: Der Benutzer muss hierfür und auch für alle anderen Aktionen die entsprechende Berechtigung auf dem Server haben).

Fazit

Mit Powershell lassen sich mehr oder weniger einfache Verteilmechanismen etablieren, die einem zum Anderen eine gewisse Flexibilität geben und zum Anderen sehr gut an die eigenen Bedürfnisse angepasst werden können.

ASP.NET MVC 5 Paging selber implementiert

Bei meinem aktuellen Projekt, wollte ich das Paging in einer MVC Applikation selber, ohne Mithilfe der NuGet PagedList for MVC, realisieren.

Zuerst der Reihe nach

  1. Wie wird die erste Seite aufgerufen?
  2. Wie werden dann die folgenden Seiten aufgerufen?

Wie wird die erste Seite aufgerufen?

Zuerst schauen wir uns den HTML Markup des Linkes an, bei welchem wir zur entsprechenden Seite navigieren.


Wie ihr seht ist dass ein ganz normaler Querystring über http

Die Seite wird dann über folgende ActionMethode aufgerufen, wie auch die Seiten die dann folgen. Zum Beispiel Seite 2 etc.

Wie werden dann die folgenden Seiten aufgerufen?

            int toalPageCount = (context.Set<Skater>().Where(skater => skater.IsActive && skater.IsSEV).OrderBy(skater => skater.Lastname).Count() / 10);
            int pageCounter = 0;

            Dictionary<int, List<SkaterDTO>> pages = new Dictionary<int, List<SkaterDTO>>();
            List<SkaterDTO> DTO = new List<SkaterDTO>();                        

            if (selectedPage == 1)
            {
                context.Set<Skater>().OrderBy(skater => skater.Lastname).Where(skater => skater.IsActive && skater.IsSEV).Take(10).ToList().ForEach(skater =>
                {
                    var vm = new SkaterDTO(skater);
                    DTO.Add(vm);
                });
                pages.Add(toalPageCount, DTO.ToList());
                pageCounter++;                    
            }
            else if (selectedPage > 1)
            {
                if (selectedPage == toalPageCount)
                {
                    context.Set<Skater>().OrderByDescending(skater => skater.Lastname).Where(skater => skater.IsActive && skater.IsSEV).Take(10).ToList().ForEach(skater =>
                    {
                        var vm = new SkaterDTO(skater);
                        DTO.Add(vm);
                    });
                }
                else
                {
                    context.Set<Skater>().OrderBy(skater => skater.Lastname).Where(skater => skater.IsActive && skater.IsSEV).Skip(selectedPage * 10).Take(10).ToList().ForEach(skater =>
                    {
                        var vm = new SkaterDTO(skater);
                        DTO.Add(vm);
                    });
                }
                pages.Add(toalPageCount, DTO.ToList());
                pageCounter++;                                        
            }
                       

            return PartialView("Skaters", pages);

Die HTML Seite für die Darstellung des Resultates sieht dann wie folgt aus:

@model System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<EislaufSektionWebUI.DTO.SkaterDTO>>

@{
    ViewBag.Title = "Läufer(innen)";
    Layout = "~/Views/Shared/_LayoutPage.cshtml";
}

@Html.ActionLink("Zurück", "Welcome", "Home")

<table class="table table-responsive table-bordered table-hover">

        <thead>
            <tr>
                <th>
                    Vorname
                </th>
                <th>
                    Name
                </th>
                <th>
                    Bestandene Tests
                </th>
                <th>
                    SEV
                </th>
                <th>
                    Geburtsdatum
                </th>
            </tr>
        </thead>
        <tbody>
            @{               
                var currentPage = int.Parse(HttpContext.Current.Request.QueryString["selectedPage"]);
                foreach (var skater in Model[currentPage-1].ToList())
                {
                    <tr>
                        <td>
                            @skater.Firstname

                        </td>
                        <td>
                            @skater.Lastname
                        </td>
                        <td>
                            @skater.CertificationLevel
                        </td>
                        <td>
                            @skater.IsSEV
                        </td>
                        <td>
                            @skater.DateOfBirth
                        </td>
                    </tr>
                }
            }
        </tbody>
    </table>

<nav>
    <ul class="pagination">
        <li>
            <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
        @{
            foreach (var key in Model.Keys)
            {
                var number = key + 1;
                <li>
                    <a href="/Person/GetSkaters?selectedPage=@number">@number</a>
                </li>
            }
        }
        <li>
            <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    </ul>
</nav>

Die Twitter Bootstrap „pagination“ Links werden dann wie folgt generiert:

<nav>
    <ul class="pagination">
        <li>
            <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
        @{
            foreach (var key in Model.Keys)
            {
                var number = key + 1;
                <li>
                    <a href="/Person/GetSkaters?selectedPage=@number">@number</a>
                </li>
            }
        }
        <li>
            <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    </ul>
</nav>

Ich hoffe euch hat der Beitrag gefallen und freue mich über Rückmeldungen oder konstruktive Kritik.

Reverse Engineering mit Visual Studio 2010

Wenn man sich gewöhnt ist zuerst Klassen zu erstellen und dann ein Model haben möchte, dann kann man schon ein wenig in Verzweiflung versinken. Nun ist es aber mit den Tools:

    • Visual Studio 2010 Ultimate
    • Visual Studio 2010 Feature Pack

möglich bereits erstellten Code rückwärts zu modellieren. Damit wir das Ganze Schritt für Schritt durchführen können, ist dieser Betrag wie folgt unterteilt:

        1. Erstellung einer Dummy Lösung mit einem manuell erstellten Klassenmodell
        2. Erstellen eins ModellProjektes

Erstellung des Beispiel Projektes

Wir halten es ganz einfach und wählen in den Projektvorlagen eine Windows Class Library aus. Wir fügen folgende Klassen hinzu:

        • Person
        • Address
        • Phone
        • PhoneType

Schlussendlich sieht das Diagramm dann wie folgt aus:

Klassen Diagramm mit dem Visual Studio Standard Generator

Nun müssen wird das Build-Directory anpassen, dass kann in ein x-beliebiges Verzeichnis sein, aber nur für das Beispiel hier.

Output Directory des Builds.

Als nächster Schritt erstellen wir uns ein Modell Projekt.

Das Modell Projekt

Nun wählen wir aus den Projektvorlagen, die Vorlage aus dem Bereich Modelling und erstellen uns eine leere Lösung. Danach fügen wir uns ein Klassendiagramm über den entsprechenden Menüpunkt der Solution hinzu.

Nun müssen wir dafür sorgen dass der Architektur Explorer ersichtlich ist. Ist dieser nicht auffindbar, kann man ihn wie folgt sichtbar machen:

  1. Auswahl Menu-Option Architektur
  2. Auswahl Fenster /Windows
  3. Selektion des Architektur Explorer

Architektur Explorer zum Vorschein bringen.

Der Architektur Explorer ist dann am unteren Rand von Visual Studio ersichtlich.

Architektur Explorer

Damit wir nun auch das vorher erstellte Projekt importieren können gehen wir wie folgt vor:

  1. Option Select Files… wählen
  2. Im öffnenden Explorer Fenster zum Pfad hinnavigieren, welchen wir vorhing bei der Beispiel DLL als Output Verzeichnis angegeben haben such und die DLL auswählen.

Nachdem wir unsere DLL selektiert haben sieht der Architecture Explorer so aus:

Architektur Explorer nach Auswahl unseres Beispielprojektes

Nun können wir beginnen die Klassen in ein Klassen Diagramm des Modelprojektes reinzuziehen und haben unser „Reverse Engineering“ erfolgreich durchgefüht.

Importierte Klassen im Klassendiagramm eines Modell Projektes

Nun können wir die notwendigen Anpassungen, falls wir mit unserem Modell nicht ganz zufrieden sind, vornehmen und den Code wieder generieren lassen.

Fazit

Es stellt sich nun die Frage, waren meine Google Anfragen so unpräzise oder ist es so einfach dass man es nicht wirklich dokumentieren braucht? Nun ich hoffe trotz der Trivialität des Vorgangs, dem einen oder anderen ein wenig Zeit mit der Suche im Web erspart zu haben.

Für Anregungen und Kritik bin ich offen. Hat der Beitrag gefallen, so würde ich mich über einen Kick freuen.

kick it on dotnet-kicks.de

Mein erstes Mal….

21. August 2011 3 Kommentare

an der See # Party in Kreuzlingen war super und ich werde auf jeden fall, sollte sie auch nächstes Jahr statt finden wieder hingegen

Wieso denn? Ganz einfach man sieht dort wirklich alle die in der Community aktiv sind und mit denen man per Facebook, Twitter oder irgendeinem Social Tool in Kontakt steht und kann ein wenig fachsimpeln oder auch über Gott und die Welt reden. Schon fast familiäre Stimmung

Welche Session’s habe ich den besucht?

Da die Autofahr ziemlich reibungslos verlief, trudelten ich und mein Fahrer bereits um 07.45 Uhr in Kreuzlingen ein. Ein bisschen früh für den Einlass.

Um 08.25 Uhr blickten wir noch mal rein und konnten uns dann die Badges für SFr. 110.– (was ich für einen sehr günstigen Preis halte) abholen.

Begrüssungsfazit

War nicht so show geladen wie an den Techdays und dass macht die Veranstaltung auch so sympathisch! Weiter so Jungs!

Keynote

Die Keynote war mal ein ganz anderes Thema als, C#, Silverlight und dergleichen. Es ging um den Stress den man sich selber machen kann, oder der durch äussere Faktoren ausgelöst wird. Sehr interessant fand ich dann auch wie sich der Wandel in der IT-Branche vollzogen hat (bis auf ein paar Namensänderungen der Ziele und Verschiebung unter den Top 15 Themen gabs keine grossen Wandel).

Nun ja, da ich meine Mail’s erst am Morgen und dann wieder am Abend kontrolliere und mein Handy so oder so auf lautlos eingestellt ist, hält sich mein Stressfaktor zum Glück in Grenzen.

Danach mal den Plan hervorgenommen und die Session’s gemerkt. Lustigerweise hatte ich 4 mal die Gelegenheit im gleichen Raum die Vorlesungen zu geniessen, was wiederum der Suche für die Örtlichkeit der nächsten Session, erheblich vereinfacht.

Die Sessions

Beruflich habe ich eigentlich immer mit ASP.NET WebForms zu tun. Da auch ich im Wandel bin habe ich die Sessions die sich mit ASP.NET befassten aussen vor gelassen und richtetet meinen Fokus eher Silverlight, XAML, Workflow Foundation.

XAML Deep Dive – Mehr als nur WPF

Dieser Vortrag war sehr lehrreich. Ich fand es super, dass die Einsatzmöglichkeiten von XAML, auch ausserhalb von WPF /Silverlight /Workflow Foundation verwendet werden kann und es ein offener Standard ist. Mein Fazit zu dieser Session: Gut

Falls man die Folien nicht herunterladen kann, findet man auf XAML – Mehr als nur eine einfache Beschreibungssprache einen sehr guten Blogartikel.

Windows Communication Foundation 4.0 – Die Neuerungen

Die Session hat sich mit den Neuerungen der Windows Communication Foundation 4.0 befasst und deren Änderungen die eingeflossen sind. Die Codebeispiele, liefen zu 80%. Es war für mich in dieser Hinsicht schade dass nicht alles funktioniert hat, aber einen positiven Teil kann man dem Ganzen auch abgewinnen: So qualifiziert und auch hohes Fachwissen die Speaker auch habe, auch sie sind Menschen denen Fehler passieren können und das ist sicherlich auch ein guter Aspekt. Schön fand ich wie die einzelnen WCF Neuerungen vorgeführt worden sind. Der Router blieb mir besonders, wegen Performanceeinschränkunen wenn man nicht alles bachtet im Gedächtnis und ich denke dass man dann diesen auch eher seltener einsetzen wird.

Mein Fazit zu dieser Session: Gut (Ich wusste gar nicht das hochdeutsch eine gleiche Geschwindigkeit wie Französisch an den Tag legen kann 🙂 )

Accessebility

Auf diese Session habe ich mich besonders gefreut, zumal man den Jürgen mal live sehen konnte. Die Aspekte unter welchen man eine barriere freie Webseite baut sind sehr gut dargestellt worden. Auch die anschliessende Diskussion und Fragerunde war sehr aufschluss- und lehrreich. Was habe ich für mich mitgenommen? Am besten Back to the roots, die Webseite in purem HTML erstellen und dynamische Inhalte soweit es geht per CSS zu erstellen. Eine weitere Erkenntnis von mir auch ist dass ASP.NET WebForms eher weniger dazu geeignet ist mit den Boardmitteln einen solche barriere freie Webseite zu erstellen, da muss man eben bei der Generierung der Controls auf der Seite Einfluss nehmen und so kann man in ASP.NET MVC das Ziel einer barriere freien optimaler erreichen.

Mein Fazit zu dieser Session: Gut (ein paar Einstiegslacher lockerten das ganze ein wenig auf (obwohl es wohl Insiderlacher von Jürgen und Karsten waren)).

User Interface Pattern mit Silverlight

Eigentlich hätte ich es mir sparen können diese Session zu besuchen…. Dachte ich zumindest in den ersten 5 Minuten. Aber weit gefehlt: Denn es ist immer wieder gut wenn man die Do’s und Dont’s der UI-Erstellung auf erfrischende Art präsentiert bekommt. Der Sprecher war sehr versiert und auch die Fokusierung von Inhalten durch das menschliche Auge hat, hat mir einen anderen Einblick gegeben.

Rein theoretisch hätte man aber nicht unbedingt Silverlight nehmen müssen.

Mein Fazit zu dieser Session: Gut

Workflow Foundation 4.0

Das Ziel war eine Getting Started Session zu machen die einen Einblick in die Workflow Fondatin 4.0 bieten soll. Dieser Einblick ist nur teilweise geglückt. Dies hat zum einen damit zu tun, dass Features die selbstverständlich sind, also das suchen von Namepsaces à la Expression Blend, nicht wirklich neu waren. Es hätte mir auch mehr gefallen, wenn man eventuell nicht dass klassische Hellow World Beispiel genommen hätte, sonder ein wenig einen kleinen Geschäftsfall erstellt hätte.

Mein Fazit zu dieser Session: Schlecht

Schlusswort

Ich finde es war ein gelungeren Anlass und es hätte auch paar mehr Entwickler kommen können. Meiner Meinung hat ausser berufliche Besuch an einer Koferenz nicht’s mit Geek zu tun sondern mit Interesse an der Arbeit die man macht. Ein Koch der leidenschaftlich kocht, der wird auch zuhause noch gerne kochen und sich auch ausserhalb der Arbeitszeit weiter bilden, weil es ihm Spass macht. Wenn man das nun so auf die Entwickler abmüntzen möchte, dann könnte man es überspitzt sagen, dass diese den Job gar nicht gerne machen (ich weiss es ist überspitzt, aber ich denke dass entspricht so dem Wahrheit).

Auch möchte ich erwähnen dass die geübte Kritik an den Sessions keinesfalls persönlich gemeint sind. Ich selber könnte nicht vor so vielen reden ohne Schweissperlen zu entwickeln, also jedem der vor so vielen Leuten redet, der ist schon, unabhängig von der Kritik, ein Gewinner.

Es würde mich sehr freuen, wenn auch nächstes Jahr wieder eine See # Party statt finden und vielleicht ein wenig mehr Entwickler den Weg dorthin finden würden.

Kategorien:Allgemein

Blog merge zwischen Live Space und WordPress

4. Oktober 2010 1 Kommentar

Nachdem ich die Gratis-Services von Microsoft mal durchgelesen habe ist mir beim Login des Space aufgefallen, dass ab März 2011 keine Blogeinträge mehr gemacht werden können. Somit habe ich den Ratschlag wahrgenommen und meinen Blog auf WordPress migriert 🙂

Infos zu allen Gratis-Services sind hier zu finden.

Kategorien:Allgemein

Definiere Kundenfreundlichkeit…

Gerne. Seit gut ein paar Tagen ist die Hausmesse BEA bei uns im Gange. Der eine oder der andere bietet dort seine Waren fiel und es wird um Kunden geworben was das Zeug hält. Da ich heute die Zeit gefunden habe, neben Karussel und anderen Kinder freundlichen Jahrmarktsattraktionen, ein paar meiner favorisierten Themengebiete anzuschauen, war mein Weg auch in die Halle der Unterhaltungselektronik und des Internets nicht unvermeidbar. Also man schlenderte mit schwangerer Freundin und mit einem Militär-T-Shirt (Olivegrün) und ein ein paar Elfenbeinfarbenen kurzen Hosen durch die Stände. Man kam an Kilchenmann vorbei (keiner scherte sich einen Dreck um die zwei Personen die da eventuell an einem Kauf eines Geräte interessiert waren). Weiter ging es zu Meier Sound and Vision (perse ein sau teurer Laden). Keiner wollte was von uns wissen, lieber drei Verkäufer um einen potentiellen Käufer, als dass man die Greifarme nach Neukunden ausgerichtet hätte.

Nächster Halt Sunrise: Komisch das gleiche Bild wie schon vorher. Wieso? Keine Ahnung. Desillusioniert und mit wenig Motivation besuchte ich den Swisscom-Stand. Dort wurde man freundliche von Scrat (der Star aus Ice Age) begrüsst.

DSC00075

Nachdem man an dieser netten Gestalt vorbei ging, dachte man ach, dass wird wohl der einzige sein der dich bemerkt. Nein, beim begutachten von Digital-Kameras wurde ich mehrfach von Swisscom-Mitarbeitern freundlich gegrüsst, mit dem Satz: “Kann ich Ihnen helfen”… Bafff. Man sagt immer dass der Monopolist sich einen Dreck um die Kunden schürt? Komisch Cablecom, sunrise und Konsorten mögen zwar günstiger sein als der ehemalige Monopolist, aber der Kontakt zum Kunden findet nur noch elektronisch statt und man hat fast keine Chance mit den Mitarbeitern zu reden. Für mich steht klar: Service hat seinen Preis und der ist bei der Swisscom wohl berechtigt (ich hoffe dass wirkt sich dann auch aus wenn man ein wenig länger Kunde ist). Auf jeden Fall werde ich Natel-, Internet- und Festnetzvertrag zu 99% wieder bei Swisscom abschliessen und habe dann nicht immer eine automatische Mail oder eine halb patzige Antwort eines genervten Service-Mitarbeiters.

Kategorien:Allgemein

Muss es denn immer ein C# Programm sein?

Ab und an sieht man immer wieder, für ganz einfache Task, die das Computermanagement betreffen, wie liest man dies und jenes aus dem PC aus. Grundsätzlich kann dies auch ohne eine kompilierte Exe gemacht werden. Bitte nicht falsch verstehen, ich stehe voll und ganz hinter C#, für manche Sachen finde ich aber ein wenig Overdosed.

Wenn man zum Beispiel die verfügbaren WMI-Klassen haben möchte, dann reicht es in der Powershell (Windows XP und VISTA, Windows 7) folgende Zeile einzugeben. Hier als Beispiel lasse ich mir alle WMI-Klassen die etwas mit dem Prozessor zu tun haben ausgeben.

   1: Get-WmiObject -query "Select * from meta_class" | Select-String -pattern "Processor"

Resultat:

   1: cimv2:CIM_Processor
   2: cimv2:Win32_Processor
   3: cimv2:Win32_ComputerSystemProcessor
   4: cimv2:CIM_AssociatedProcessorMemory
   5: cimv2:Win32_AssociatedProcessorMemory
   6: cimv2:Win32_PerfFormattedData_Counters_PerProcessorNetworkActivityCycles
   7: cimv2:Win32_PerfRawData_Counters_PerProcessorNetworkActivityCycles
   8: cimv2:Win32_PerfFormattedData_Counters_PerProcessorNetworkInterfaceCardActivity
   9: cimv2:Win32_PerfRawData_Counters_PerProcessorNetworkInterfaceCardActivity
  10: cimv2:Win32_PerfFormattedData_Counters_ProcessorInformation
  11: cimv2:Win32_PerfRawData_Counters_ProcessorInformation
  12: cimv2:Win32_PerfFormattedData_PerfOS_Processor
  13: cimv2:Win32_PerfRawData_PerfOS_Processor

Dies lässt sich auch für anderen Klassen wie Harddisk machen. Wenn wir also den Prozessor auslesen wollen, dann reicht folgende Scriptzeile, die dann auch gleich ein File erstellt.

   1: Get-WmiObject -Class Win32_Processor | out-file -FilePath C:\Temp\Processor.txt

Somit hat man in einem Zweizeiler die benötigten Informationen ausgelesen, also ein wenig kürzer als mit managed Code. Für Scripts auszuführen muss aber in der PowerShell die ExecutionPolicy auf trusted (empfohlen) oder unrestricted (nur für Testzwecke in einem abgeschotteten System) zu setzen.

Kategorien:Allgemein