Import NuGet Packages to F# Interactive Scripts

Yes, it’s been a long time (exactly one year, but that’s a coincidence) since my last blog post. The main reason was that in the last year I learnt F# and slowly I have the feeling that I have understood the language and especially the paradigm shift that comes with F#.

I jump over the usual homage of why F# is a wonderful language – that’s material for a plethora of blog posts - and come straight to the motivation of this blog post.

If you are like me and you learn by trying things out you probably love the interactive and iterative nature of F#. Just create a new fsx (F# Interactive) file and start hacking until you have a working prototype. You don’t even have to save the file!
I actually have a folder full of F# scripts with my experimentations in them.

One pain point though is that F# interactive does not have support for NuGet package management. You can reference the library files manually but that’s very cumbersome.

There exists an older blog post from Daniel Mohl where he suggests how to add NuGet support to F# Interactive, but his solution requires the VS Object Model and doesn’t support loose fsx files (without the creation of a F# project).

So I wrote my own “PackageManagement.fsx” file which can be initialized with F# Interactive:

And here is the script code: https://gist.github.com/toburger/9786275

It depends on the NuGet.Core.dll which you can get from here and you must define your target NuGet packages directory, where the packages are downloaded and from where they are referenced (you can define the “NugetLibDir” environment variable so you can use the same script on multiple machines). I ignore the versioning of the packages (I always download the latest stable release), but you can enable it by setting the boolean parameter “useSideBySidePaths” on line 11 to true.

So how to work with this script?

The main command is “ipr” which stands for “install package and references”, which downloads the package with all its dependencies and adds the references to the clipboard, so the only thing you have to do is to paste the references on top of your script file.

Just enter ipr “package name”;; in the f# Interactive REPL (don’t forget the two semicolons) and it will try it’s best to download and reference the packages.

There are also commands to update and uninstall packages or to simply copy the references without trying to download the latest package.

Limitations:

I try my best to find the best matching references for the framework version in which F# interactive runs, but this matching is not bullet proof and unfortunately the NuGet lib doesn’t provide a way to get the best matching references automatically (at least I didn’t found any practical way).

The script should also work without VS and should work on Mono but I don’t have tested it so please feel free to contact me or edit the file if you have any problems.


Actually there is now a suggestion on fslang uservoice with a propose to natively support NuGet packages: http://fslang.uservoice.com/forums/245727-f-language/suggestions/5670137–package-directive-to-import-nuget-packages-in-f

Tagged , ,

Easy monitoring of a folder with pswatch

pswatch is a easy to use little module for PowerShell to montitor a folder for changes.

You can choose if you want to monitor file additions, changes, renames or deletions. You can also monitor file sin subfolders.

Based on this monitoring you can further add scripting to automatically run other commands (see example on github).

I further customized the output to include the time of the occurrence of the event:

watch $env:Temp -includeDeleted | % { $_ | Add-Member ScriptProperty Time { Get-Date } -PassThru }

This adds a dynamic Time property which automatically updates itself when a new file change event is happening.

Tagged , ,

Reset your login credentials for „Visual Studio Tools for Git“

If you change your login credentials for one of the git hosting services (github, bitbucket, …) and you try to pull, fetch or push you probably receive the same error as in the screenshot below:

I struggled a while with the problem until I found the solution.

You have to reset the credentials in the Windows Credential store.

Sorry, I have to translate the text on the fly because I have a German version of Windows 7.

Go to your user account settings and click on “manager your own credentials”:

Pick the credentials for e.g. git:https://bitbucket.org and click on edit:

You should now be able to work with your git remote again:

Hope this helps!

Tagged , , , , ,

Bildschirm deaktivieren, sobald der Computer gesperrt wird

Wie sinnvoll ist ein Bildschirm, wenn man den Computer gesperrt hat?

Über die Energieoptionen kann natürlich konfiguriert werden, wann der Bildschirm deaktiviert wird, aber wenn man eine kurze Zeitspanne aktiviert und man gerade einen Text (oder hoffentlich meinen Blog) durchliest, dann ist das eher störend, wenn plötzlich der Bildschirm ausgeht. Andere Möglichkeit wäre den Bildschirm einfach abzuschalten, aber das ist bei mehreren Bildschirmen (wie hat man früher eigentlich produktiv mit nur einem Bildschirm arbeiten gekonnt?) umständlich und man vergisst es gerne.

Eine andere Möglichkeit ist den Bildschirm automatisch zu deaktivieren, wenn man ihn gerade nicht benötigt. Das beste Beispiel ist wohl, wenn man kurz AFK ist und man seine Arbeitsstation sperrt. Heißt so viel wie: ich werde jetzt mal nichts am Computer machen!

Als Programmierer habe ich mir natürlich gleich mal überlegt ein kleines Programm zu schreiben, das mir das erledigen könnte… Hmm… Das Programm läuft im Hintergrund und klinkt sich in die Message Loop ein und wenn der Computer die Lock Message schickt den Computer sperren…
Halt! Stopp!

Seit Windows Vista gibt es eine viel einfachere Möglichkeit dies zu erledigen. Alles was man dazu benötigt ist der Aufgabenplaner (Task Scheduler) und ein kleines Utility namens NirCmd.

Fangen wir bei NirCmd an:

Es ist ein kleines aber feines Tool, welches bestimmte Windows-Befehle ausführt, welche normalerweise nur über ein User-Interface zugänglich sind. Einer dieser Befehle ist den Monitor auszuschalten.

Wenn jemand den Systembefehl kennt, welcher zum Deaktivieren des Monitors verwendet wird bitte mir mitteilen, ich habe ihn leider nicht gefunden.
Der Systembefehl hätte den Vorteil, dass kein Third-Party Tool verwendet werden muss.
Was mir an NirCmd jedoch gefällt: es kann eine Warteizeit gesetzt werden und erst danach wird das Kommando ausgeführt.

Bei mir sieht das Kommando folgendermaßen aus:

"c:\Program Files\nircmd\nircmd.exe" cmdwait 5000 monitor off

Der Aufgabenplaner von Windows ab Vista:

Seit Vista verfügt Windows über einen sehr mächtigen Aufgabenplaner. Es können “Trigger” definiert werden, wann eine Aufgabe abläuft. Ein einfacher Trigger wäre einmal täglich. Aber auch komplexere Trigger sind möglich. Und genau einer dieser komplexeren Trigger benötigen wir: “Bei Arbeitsstationssperre”.
Unter den Aktionen kann man dann einstellen, was gemacht werden soll: in unserem Fall soll das oben beschriebene Kommando ausgeführt werden.

Zusammenfassung:

  1. Aufgabenplaner starten
  2. Zur Aufgabenplanungsbibliothek wechseln (oder, was ich gerne Mache, in einen Unterordner, welchen ich für meine persönlichen Aufgaben extra erstellt habe)
  3. Aktionen à Neue Aufgabe erstellen…
  4. Unter Allgemein einen Namen eingeben
  5. Unter Trigger den Trigger auswählen “Bei Arbeitsstationssperre”
  6. Unter Aktionen den NirCmd Befehl eintragen
  7. Bei den Bedingungen können alle Checkboxen entfernt werden (ich hab zwar einen Stand-PC aber bei einem mobilen Computer ist es ja auch durchaus sinnvoll, dass der Befehl ausgeführt wird, wenn der Computer vom Stromnetz getrennt ist).
  8. Das Dialogfeld mit OK bestätigen.
  9. Den Computer sperren ([Win]+L) und sich von seiner Funktionsweise überzeugen! J

ACHTUNG!

Wie ich leider feststellen musste hat NirCmd – zumindest auf meinem Rechner – die Eigenart, sich ausgerechnet dann NICHT zu beenden, wenn man den Parameter “monitor off” übergibt.

Um diese Aufgabe dennoch öfters als einmal ausführen zu können (die Aufgabe wird im Aufgabenplaner immer als ausgeführt angezeigt) muss man etwas hacken:

  1. Bei den Einstellungen der Aufgabe einstellen, dass neue Instanzen parallel ausgeführt werden sollen
  2. Vor der Aktion NirCmd den Monitor abschalten zu lassen folgenden Befehl einfügen
    "C:\Program Files\nircmd\nircmd.exe" killprocess nircmd
    

    Dies löscht den vorherigen “Zombie”

Leider bleibt immer ein NirCmd-Prozess übrig, aber ich kann damit leben.

Eventuell kann man den Prozess einfach händisch beenden, oder man erstell eine weitere Aufgabe, welche beim Aufheben der Arbeitsstationssperre ausgeführt wird und dort wird der killprocess Befehl eingefügt.

PowerShell: Set-Content mit Binärwerten

Ich stoße in PowerShell-Scripts immer wieder auf folgenden Befehl:

[System.IO.File]::WriteAllBytes(<pfad>, <wert>)

Nichts dass daran irgendetwas falsch wäre, es gibt jedoch eine PowerShell-freundlichere Möglichkeit Binärwerte in eine Datei zu schreiben, und zwar mit folgendem Befehl:

Set-Content -Path ... -Value ... -Encoding Byte

Dies hat den Vorteil, dass der Pfad richtig aufgelöst wird und man kann dadurch den Binärwert über die PowerShell Pipeline übergeben.

Beispiel aus der Praxis: Das Auslesen des Profilbildes eines ActiveDirectory-Benutzers und anschließendem Speichern als Datei

Import-Module ActiveDirectory
(Get-ADUser TBurger -Property thumbnailPhoto).thumbnailPhoto | Set-Content TBurger.jpg -Encoding Byte

„eval“-Äquivalent in PowerShell

Heute hatte ich ein vermeintlich einfaches Problem zu lösen:

Ich sollte eine Textdatei mit PowerShell auslesen, welche wiederum PowerShell-Variablen enthält (z.B. $datum, $_.Name, …).

Content.txt:

Hier ist normaler Text
$date

Ergebnis:

Hier ist normaler Text
08/23/2012 09:53:12

Ein einfaches

Get-Content

funktioniert hier nicht, da hierbei die Variablen nicht interpretiert werden und der Text wird so ausgegeben, wie er in der Textdatei steht.

Die Lösung ist, die Methode ExpandString auszuführen, welche in der PowerShell über

$ExecutionContext.InvokeCommand.ExpandString

aufrufbar ist.

$date = Get-Date
$content = Get-Content .\Content.txt    # PowerShell 3 Tipp: -Raw liest die Datei in einem String aus, normalerweise wird ein String-Array ausgelesen.
$content = $ExecutionContext.InvokeCommand.ExpandString($content)

Und schon hat man das gewünschte Resultat. J

Sehr praktisch wenn man z.B. Emails mit einem Body-Template verschicken will.

Man kann sogar so weit gehen, dass man ganze PowerShell-Kommandos ausführen kann (im Prinzip verhält sich der Text wie Text aus einem “Here-String“):

$(get-date)

eval is evil

Wie auch bei eval gilt: Vorsicht, was man einliest, da prinzipiell jedes Kommando im Kontext der ausführenden PowerShell-Instanz ausgeführt wird kann man sehr böse Dinge anstellen!

PowerShell Cmdlet zum Auslesen der Anmeldeinformationen aus der “Windows Anmeldeinformationsverwaltung”

Will man PowerShell-Operationen automatisieren benötigt man gelegentlich Anmeldeinformationen, welche dann irgendwie im Script zur Verfügung gestellt werden müssen. Normalerweise erledigt man dies über Get-Credential, welches allerdings immer eine Benutzerabfrage bedingt und in einem automatisch ablaufenden Script nutzlos ist.

Der einfachste (aber auch unsicherste) Weg ein Passwort auszulesen ist folgender:

$password = ConvertTo-SecureString <plaintextpassword> -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential <username>, $password

Dass dies nicht der bevorzugte Weg ist, sieht man am Umstand, dass der Paramter –Force angegeben werden muss, da ansonsten folgender Fehler ausgegeben wird: “Nur-Text-Eingaben können vom System nicht geschützt werden.”
Und wenn man (hoffentlich) etwas nachdenkt, ist dieses Verhalten auch vollkommen verständlich, denn wer will schon seine Passwörter im Klartext in einer Textdatei hinterlegen.
Auf der anderen Seite ist es doch immer wieder praktisch Logininformationen eines Systems zu ermitteln, indem man Dateien mit den klingenden Namen config.(php|asp|*), connection.(php|asp|*), usw.. durchstöbert. Zwinkerndes Smiley

Nun gibt es zwei Möglichkeiten Passwörter sicher zu hinterlegen

  1. Das Password wird verschlüsselt im Script selbst hinterlegt oder in einer Datei ausgelagert.
  2. Die Anmeldeinformationen werden im “Windows Credential Manager” (das ist die englische Bezeichnung für die Windows Anmeldeinformationsverwaltung) hinterlegt.

Methode 1: PowerShell “out-of-the-box”

Das Password wird in eine Date gespeichert:

// Die Login-Informationen werden abgefragt
$credential = Get-Credential
// Das Password wird in einer Datei gespeichert
$credential.Password | ConvertFrom-SecureString | Set-Content <file>

Das Auslesen des Passwortes wird dann folgendermaßen erledigt:

$password = Get-Content <file> | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential(<username>, $password)

Dieses PSCredential kann man dann den Cmdlets übergeben, welche die Anmeldeinforationen benötigen (z.B. Enter-PSSesssion <server> –Credential $credential).

Zu beachten ist, dass diese Methode nur funktioniert, wenn das Passwort auf demselben Computer ausgelesen wird, auf welchem es auch erstellt wurde, da für die Verschlüsselung/Entschlüsselung der MachineKey verwendet wird.

Damit die Methode über mehrere Computer funktioniert, kann man entweder den MachineKey der Computer angleichen (!) oder ConvertFrom-SecureString und ConvertTo-SecureString einen –Key oder -SecureKey übergeben, welcher dann wiederum sicher aufbewahrt werden sollte, und da man dies mit Methode 1 endlos wiederholen müsste, würde sich Methode 2 anbieten. Zwinkerndes Smiley

Methode 2: “Windows Anmeldeinformationsverwaltung”

Informationen zur Windows Anmeldeinformationverwaltung (englisch: Windows Credential Manager) findet man hier: http://windows.microsoft.com/de-DE/windows7/What-is-Credential-Manager

Hinterlegt werden diese Anmeldeinformationen über Systemsteuerung/Benutzerkonten/Anmeldeinformationsverwaltung. Dabei wird eine Internet- oder Netzwerkadresse (welche später als Schlüssel dient) das Login und das Passwort hinterlegt.

Leider bietet PowerShell keine Möglichkeiten diese Anmeldeinformationen nativ auszulesen. Aus diesem Grund habe ich ein PowerShell Cmdlet erstellt, welches diese Aufgabe übernimmt.

Die Datei findet man hier:

Die Verwendung gestaltet sich dann wie folgt:

$credential = .\Get-CredentialFromWindowsCredentialManager.ps1 <internet- oder netzwerkadresse>
Enter-PSSession <server> –Credential $credential

Die Anmeldeinformationen sind lokal und Benutzerbezogen, das heißt natürlich, sie sind bei Bedarf für ein weiteres Benutzerkonto oder auf einem weiteren Rechner ebenfalls im Windows Credential Manager des jeweiligen Benutzerkontos zu hinterlegen.

Tagged , , ,

dynamic^2 oder ”variable Variablen”

(Irgendwie mag Windows Live Writer kein ² in der Überschrift…) Erzürnt

Seit .NET 4 gehört C# (und natürlich VB.Net) zu dem Kreis der dynamisch typisierten Sprachen. Dies ermöglicht die DLR, die Dynamic Language Runtime.
D.h. man kann Variablen “spät binden” (late binding), d.h. sie werden erst zur Laufzeit in ihren konkreten Typ materialisiert.
Das erlaubt einem eine hohe Flexibilität für verschiedenste Szenarien, wie z.B. beim COM Interop, der Kommunikation mit anderen dynamischen Sprachen für .NET (IronPython, IronRuby, IronJS, Phalanger, …) oder einfach in Situationen in denen der konkrete Typ erst zur Laufzeit bekannt ist (Reflection, XML, …).

Ich möchte jetzt nicht weiter auf die Grundlagen eingehen, da es inzwischen genügend Dokumentation dazu gibt. Einfach mal in die MSDN Doku reinschauen.

Basierend auf dem Beispiel aus der Doku mit dem DynamicDictionary möchte ich auf eine kleine Erweiterung eingehen: variable Variablen.
PHP Programmierer wissen vielleicht was ich meine. In PHP ist es beispielsweise möglich folgendes zu schreiben:

$variableName = "age";
$obj = new stdClass();
$obj->{$variableName} = "31";

echo $obj->age;

Also die Variable (bzw. den Member) variabel zu halten.

In C# ist das Out of the Box nicht möglich. Durch zwei Erweiterungsmethoden kann diese “dynamische Dynamik” aber leicht nachgereicht werden:

public static object GetMember(this object obj, string memberName)
{
    var binder = Binder.GetMember(
        CSharpBinderFlags.None, memberName, obj.GetType(),
        new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
    var getterSite = CallSite<Func<CallSite, object, object>>.Create(binder);
    return getterSite.Target(getterSite, obj);
}

public static void SetMember(this object obj, string memberName, object value)
{
    var binder = Binder.SetMember(CSharpBinderFlags.None, memberName, obj.GetType(),
        new CSharpArgumentInfo[] {
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)
        });
    var setterSite = CallSite<Func<CallSite, object, object, object>>.Create(binder);
    setterSite.Target.Invoke(setterSite, obj, value);
}

Somit ist es auch in C# möglich folgendes zu schreiben:

string variableName = "Age";
dynamic obj = new DynamicDictionary();
((object)obj).SetMember(variableName, 31);

Console.WriteLine(obj.Age);

Das Unboxing mittels ((object)obj).SetMember/GetMember… ist dabei notwendig, da es sich um eine Erweiterungsmethode handelt und diese für dynamische Objekte nicht aufgelöst werden.

Alternativ könnte man auch schreiben:

DynamicObjectExtensions.SetMember(
obj, variableName, 31);

Interessant ist, dass die beiden Befehle komplett unterschiedlichen IL Code generieren. Wo bei ersterem Befehl der Methodenaufruf SetMember steht, wird bei zweiterem Befehl SetMember wiederum dynamisch aufgerufen, was einen kleinen Performanceoverhead bedeutet. Man kann diesen jedoch wieder verschwinden lassen, indem man einfach obj nach object castet:

DynamicObjectExtensions.SetMember(
(
object)obj, variableName, 31);
Tagged , , ,

tobiburger:

Musste erst kürzlich ein PowerShell-Script über eine Batch-Datei aufrufen, welche sich im selben Ordner befindet. Mit folgendem Befehl kann dies gemacht werden:

 @echo off
 powershell.exe -File "%~dp0\<psscript>.ps1"

Innerhalb des PowerShell-Scriptes kann nun wiederum auf den relativen Pfad verwiesen werden:

 $parentPath = Split-Path -Parent $MyInvocation.MyCommand.Definition

Originally posted on Miscellaneous IT Pimpery:

The %~dp0 (that’s a zero) variable when referenced within a Windows batch file will expand to the drive letter and path of that batch file.

View original 129 more words

PowerPivot OData Feeds filtern

Wenn jemand PivotTabellen erstellen möchte, welche sich über mehrere unabhängige Datenquellen verteilen ist PowerPivot ein geniales Werkzeug.

SharePoint kann über die REST-Schnittstelle eingebunden werden, welches das OData Protokoll implementiert. Dazu muss lediglich die WCF Data Services Bibliothek – die Implementierung von OData über WCF – installiert werden. Diese Schnittstelle ist über http://<sharepoint_server>/_vti_bin/listdata.svc erreichbar.

Eigentlich dachte ich, dass dieses Protokoll voll und ganz von PowerPivot unterstützt wird (zumindest wird einem das immer so erklärt). Leider gibt es einen Bereich, welcher nicht unterstützt wird:
Das Vorfiltern der Daten über den QueryString ist leider nicht möglich. Dies ist dann nützlich, wenn man vermeiden möchte, dass die komplette Liste ausgelesen wird (und anschließend in der Excel-Tabelle gespeichert wird). Die Excel Datei kann so gut und gerne 20 bis 50 MB und größer werden, je nach Anzahl an Elementen.

OData bietet für das Filtern, Sortieren und Selektieren QueryString-Parameter an.
Um z.B. alle Buchungen aus dem Jahr 2012 zu filtern kann folgendes geschrieben werden:
…/listdata.svc/Buchungen?$filter=year(Erhalten) eq 2012

Leider mag PowerPivot QueryStrings ganz und gar nicht! Und mit ganz und gar nicht meine ich, dass diese einfach ignoriert werden. Dass ich nicht der Einzige mit diesem Problem ist sieht man an folgendem Bug Report: https://connect.microsoft.com/SQLServer/feedback/details/724823/import-odata-feed-datasource-into-powerpivot-without-filter

Da ich aber nicht so lange warten wollte, bis dieses Feature in PowerPivot Einzug findet habe ich eine Quick & Dirty Lösung zusammengebastelt, welche funktioniert, aber nicht wirklich schön ist.

Eigentlich sind mir zwei Lösungen eingefallen, die Eine greift in die IIS-Konfiguration von SharePoint ein (der geneigte Leser soll selbst entscheiden, ob dies eine gute Lösung ist), die Andere dient als Gateway zum OData-Feed von SharePoint.
Die zweite Lösung ist etwas komplexer – nicht sehr viel komplexer – aber genug, um aus dem Artikel zwei zu machen. Ich habe zurzeit nicht vor auf diese Lösung genauer einzugehen, es sei den ein Leser ist an der zweiten Lösung interessiert, dann werde ich einen weiteren Blog-Eintrag posten.

Quick & Dirty Lösung: Eingriff in die IIS-Konfiguration von SharePoint

Okay, das Ändern der IIS-Konfiguration von SharePoint ist eigentlich ein absolutes NoGo (außer in den von der SharePoint Dokumentation ausdrücklich erlaubten Fällen), die Lösung hat sich aber als recht einfach und wirkungsvoll erwiesen.

Ich bediene mich hier einfach dem URL Rewriting Modul, welches einem im IIS ab Version 7 zur Verfügung steht (muss aber nachinstalliert werden: http://www.iis.net/download/URLRewrite). Eine “User-friendly URL” Rule später funktioniert das Ganze auch schon. Zu beachten ist allerdings, dass der Webserver-Prozess recycelt wird (nicht der App-Pool, geht also etwas schneller), nachdem Änderungen am URL-Rewriting vorgenommen wurden, das Ganze ist in Produktion also mit Vorsicht zu genießen.

Die URL-Regel in meinem Fall sieht beispielsweise so aus:
image

Im Grunde wird nichts Anderes gemacht, als dass die URL
http://portal/projects/buchungsportal/_vti_bin/listdata/BuchungenKundeImJahr/2012
über einen URL Match
^projects/buchungsportal/_vti_bin/listdata/BuchungenKundeImJahr/([^/]+)/?$
umgeleitet wird zu
projects/buchungsportal/_vti_bin/listdata.svc/Buchungen?$filter=InhaltstypID%20eq%20’0x010100F72541062D58004C81F84CFC226B954702007BDDD584C443764C8A87B2F22748C1AF’%20and%20year(Erhalten)%20eq%20{R:1}

Das Jahr ist also variabel und wird in {R:1} eingefügt, der Inhaltstyp ist immer derselbe, muss also nicht über die URL bestimmt werden (könnte aber ohne Weiteres gemacht werden).

Ein rascher Test mit PowerPivot beweist, dass das Rewriting funktioniert:
image

image

Es kommen auch wirklich nur die Buchungen zurück, welche nach der InhaltstypID und dem Jahr gefiltert wurden.

Tagged
Follow

Get every new post delivered to your Inbox.

Join 36 other followers