In meinem letzten Projekt war eine meiner Aufgaben, ein Script zu erstellen, das eine definierte Verzeichnisstruktur erstellt und einem bestimmten User die notwendigen Zugriffrechte darauf gibt.
Weiterhin sollte das Script dann im IIS eine Website mit einem eigenen AppPool in diesem Verzeichnis erstellen.

Ich hatte mich entschieden, das Script mit Powershell zu erstellen, da es hier schon fertige Module von Microsoft gibt, um den IIS zu verwalten, ohne das man dies über WMI machen müsste.

Um dieses Modul allerdings zu verwenden, muss man es in Powershell erst einmal importieren. Das macht man ganz einfach mit foldener Codezeile.

1
Import-Module -Name WebAdministration

Damit das Module importiert werden kann, muss der IIS mit den Management Services installiert sein. Will man prüfen, ob das Modul auch wirklich installiert ist, so kann man das mit folgendem Code machen und im negativen Fall den Benutzer darauf hinweisen.

1
2
3
4
if ((get-module -name WebAdministration -erroraction silentlycontinue) -eq $false) {
Write-Host "The Powershell module for WebAdministration is not installed! Please check your IIS installation!" -f Red
return
}

Die Website erstellt man dann mit folgendem Code

1
2
3
4
5
6
7
$integrated = 0
New-WebAppPool -Name $appPoolName
Set-ItemProperty IIS:AppPools\$appPoolName managedRuntimeVersion v4.0
Set-ItemProperty IIS:AppPools\$appPoolName managedPipelineMode $integrated
New-Website -Name $webServiceName -PhysicalPath $directoryPath -ApplicationPool $appPoolName
Remove-WebBinding -Name $webServiceName
New-WebBinding -Name $webServiceName -IPAddress "*" -Port $port -HostHeader $webServiceName

Seit IIS7 ist es so, das der AppPool nicht mehr wie früher mit dem Account NetworkService läuft sondern es dafür eigene IIS AppPool Identities gibt. Wenn man einen neuen AppPool erstellt, läuft dieser unter dem Benutzer IIS AppPools\AppPoolname. Es müssen diesem Benutzer noch die Zugriffsrechte auf das Verzeichnis gegeben werden. Normalerweise sollten diesem Benutzer nur auf bestimmte Verzeichniss, wie das Log-Verzeichnis Schreibrechte gegeben werden. Auf die anderen Verzeichniss reichen Lesezugriffsrechte. Auch hierfür hat die Powershell schon die notwendigen Commandlets an Board.

1
2
3
4
5
6
$acl = Get-Acl -Path $directory
$userAccount = New-Object System.Security.Principal.NTAccount("IIS AppPool", $userName)
$permission = $userAccount, $right, "ContainerInherit,ObjectInherit", "None", "Allow"
$right = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($right)
Set-Acl -AclObject $acl -Path $directory

Die meisten Codebeispiele erstellen die Permission mit der folgenden Codezeile

1
$permission = $userAccount, $right

Das hat aber den Nachteil, das sich diese Berechtigung nicht auf neue Unterordner veerbt. Deswegen ist die erste Variante in den meisten Fällen sicher die zu bevorzugende.

Comment and share

LinqPerformanceTips

in develop

In my latest project I learned some thinks about the performance of Linq when you often query in-memory repositories. Linq is very easy to use and with that you can very quick implement the methods that you need for an repository. But sometimes it’s useful to think a little bit more how often a method will be called. In my latest project I had the situation to call the GetById method for more than 20.000 times. And my in-memory repository had more than 700 items. In my first attempt I have used the SingleOrDefault method to return the correct item. But this was not fast enough. My function has needed more than 2 seconds in sum. My second attempt was, to convert the items into a Dictionary with the id as key and use this dictionary in the GetById function. And this was so much faster. It needs just 220 ms for all calls and this was the performance that I needed.

To generate a dictionary very quick, you can use an extension method from the System.Linq namespace. With the following code you can do this very easy

1
items.ToDictionary(i => i.Id);

The same experience I made with the query for any items with the same key. The Linq function SelectMany was in summary to slow. In this situation you can’t use a dictionary because the key isn’t unique. But Linq has also an Extension method to solve this problem. With the ToLookup function you can generate a very fast lookup table.

1
items.ToLookup(i => i.{PropertyToLookup});

Comment and share

In my current project I have got some .csf files with the requirement to import these files
to my project as base data to use it as inmemory repository.

The best solution was these single line of code in powershell.

1
Get-Content -path $inputFile | ConvertFrom-Csv -Delimiter ';' | ConvertTo-Json | Out-File $outputFile

You can download the complete powershell script from my gist repository at github.

Comment and share

Jan Baer

I’m a passionated Softwaredeveloper from Munich.


Softwaredeveloper


Germany