Outlook attachments automatisch opslaan (met PowerShell)

Als leerkracht vraag ik vaak aan mijn leerlingen om mij een aantal bestanden door te mailen.  Resultaat: van elke leerling krijg ik een mail met daarin telkens een aantal bestanden.  Voor ik die bestanden kan nakijken moet ik dus mail per mail openen en de bijlagen ergens opslaan op mijn harde schijf.  Dat kan best een tijdrovend werkje zijn als je een groot aantal leerlingen hebt.

Dat moest sneller kunnen dacht ik … 🙂

Het script hieronder zoekt in de map “Postvak IN” naar de map “Mail leerlingen”. Alle mails in die map worden bekeken; als een mail bijlagen bevat worden die opgeslagen in de map “e:\bestanden”.  Eerst wordt in die map een submap aangemaakt met de naam van de persoon die de mail heeft verstuurd (de naam van de leerling dus). Alle bestanden van die leerling worden in die map geplaatst, de bestandsnamen van de bijlagen worden behouden maar aangevuld met de datum waarop het script de bestanden uit Outlook heeft gehaald en op de harde schijf heeft geplaatst. (formaat jjjjMMdd; vb. 20160725)

Knipsel

Nu moet ik enkel nog de mails van de leerlingen in de submap “Mail leerlingen” plaatsen, script uitvoeren en ik krijg alle bestanden netjes geordend op mijn harde schijf.

knipsel2

Wil je het scriptje of een aangepaste versie ervan, aarzel niet om mij te contacteren 🙂

Getallen converteren Decimaal naar Octaal, Hex, Binair

Een oefeningetje die we in de lessen technologische opvoeding allemaal wel hebben moeten maken? Getallen omzetten van het ene talstelsel naar het andere. Nu nog makkelijker met Powershell (zonder de ingebouwde functies)

cls
$i = Read-Host("Geef een getal tussen 0 en heeel veel :")
while ($stelsel -ne "2" -and $stelsel -ne "8" -and $stelsel -ne "16")
{
  $stelsel = Read-Host("Wil je converteren naar Binair (2), Octaal (8) of Hexadecimaal (16) ?")
}
$hexArray = @("0", "1","2","3","4","5","6","7","8","9","A","B","C","D","E","F")

$reststring = ""
while ($i -gt 0)
{
  $reststring = $hexArray[$i % $stelsel] + " " + $reststring
  $i = [Math]::Truncate($i / $stelsel)
}
  Write-Host "=>" $reststring "<="

Logfiles roteren met Powershell

In een typische shared hosting omgeving krijg je binnen de map van de gebruiker een locatie waar log bestanden worden weggeschreven.   Als hoster heb je dan een groot aantal (liefst Knipogende emoticon) mappen met in elk van die mappen een map “logs” waarin al snel (alles samen) duizenden log files staan.  Het volgende Powershell script overloopt alle mappen (zeg maar alle klanten) en neemt alle log bestanden die minstens 7 dagen oud zijn, steekt die in een zip bestandje met als naam JAAR-WEEKINJAAR.ZIP en verwijdert die file vervolgens.   Het script is makkelijk aanpasbaar om dit bvb. maandelijks te doen ipv wekelijks.

$TargetFolder = "c:Sites"
$Now = Get-Date
$ArchiveFrom = $Now.AddDays(-7)

$mappen = get-childitem -Path $TargetFolder
          | Where {$_.psIsContainer -eq $true}
foreach ($map in $mappen)
{
  $mapuse = "$TargetFolder$maplog"
  if (Test-Path ($mapuse))
  {
    $logbestanden = dir -Recurse $mapuse | Where {($_.LastWriteTime -le "$ArchiveFrom")
            -and ($_.extension -eq ".log")}
    $bestandsnaam = get-date -uFormat %Y-%V
    $zipfile = "$mapuse$bestandsnaam.zip"
    echo $zipfile
    set-content "$zipfile" ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))

    (dir $zipfile).IsReadOnly = $false
    $shellApplication = new-object -com shell.application
    $zipPackage = $shellApplication.NameSpace($zipfile)
    foreach ($logfile in $logbestanden)
    {
            $zipPackage.CopyHere($logfile.FullName)
            Start-sleep -milliseconds 1000
            Remove-Item $file | out-null

    }
  }
}

Bij vragen of opmerkingen, hoor ik graag van u !

Foto’s sorteren met PowerShell op basis van EXIF informatie

Misschien heb je het zelf ook ooit eens voorgehad en dan weet je hoe onprettig het is: Je hebt duizenden foto’s van jaren ver netjes onderverdeeld in mapjes en submapjes en om een of andere reden krijg je ze allemaal netjes onder elkaar met een nietszeggende naam in één map. Met het powershell scriptje hieronder kan je alvast die vele duizenden bestanden terug in mapjes plaatsen op basis van het tijdstip waarop ze genomen werden.  Tenminste voor zover de bestanden EXIF informatie bevatten (elk deftig toestel van de laatste 5 jaar plaatst dit in elk foto die gemaakt wordt).

Om dit scriptje te kunnen uitvoeren heb je wel de image module nodig die je als onderdeel van het PowerShellPack vindt. Downloaden kan hier : http://archive.msdn.microsoft.com/PowerShellPack  Controleren of je de module hebt kan met dit commando (psimagetools)

Get-Module -ListAvailable
De module inladen (kan eventueel als eerste lijntje in het script toegevoegd worden) kan met het commando
Import-Module PSImageTools
En dan is dit het scriptje die de bestanden maand per maand in mapjes plaatst
$bestanden = get-childitem "d:testps" |
                          where {$_.extension -eq ".jpg"}
foreach ($bestand in $bestanden)
{
  $datum = ((Get-Image $bestand | Get-ImageProperty).dt);
  $maand = $datum.month
  $jaar = $datum.year;

  if (!(Test-Path "d:testps$jaar-$maand"))
  {
     md $jaar-$maand;
  }
  Move-Item $bestand "d:testps$jaar-$maand";
}


IIS 7 scripting met PowerShell

Het configureren van een website in IIS 7 en alles daarrond kan flink wat van je tijd opslopren als je dat telkens volgens een uniforme wijze wil gedaan hebben. Gelukkig kunnen we een aardig stukje scripten. Anno 2011 gaat dat bijzonder eenvoudig met behulp van Powershell en de nodige snap-in’s.

Zie hier een scriptje dat op een voor de eindgebruiker eenvoudige wijze een propere website configureert.  Er wordt een website aangemaakt, in een eigen app pool ondergebracht, er wordt een map voorzien om de IIS logs in te plaatsen (LOGS), een map waarin de website kan schrijven (DATA), plaats voor een eventuele Access DB …


# Enkele Variabelen

$basis = "c:webserver"
$defaultpass = "*********"
$ftpsite = "FTP General"

# Inladen van de belangrijkste module van dit script WebAdministration
 Import-Module WebAdministration

# Domeinnaam opvragen en indien nodig converteren naar upper case
 do
 {
    $domain = Read-Host "Domein ? (geen http:// of www) "
 } while (Test-Path("$basis$domain"))
 $domain = $domain.ToUpper()

# Filesysteem klaarmaken voor onze nieuwe website
 md "$basis$domain"
 md "$basis$domainWWW"
 md "$basis$domainLOGS"
 md "$basis$domainDATA"
 md "$basis$domainDB"

# Application pool aanmaken en de .NET versie instellen op 4
 New-WebAppPool -Name $domain
 $AppPool = Get-Item "IIS:AppPools$domain"
 $AppPool.managedRuntimeVersion = "v4.0"
 $AppPool.Enable32BitAppOnWin64 = "true"
 $AppPool | Set-Item

# Website aanmaken met 2 hostheaders (domain + www.domain), 
juiste app pool gebruiken, logs juist plaatsen
 New-WebSite -Name $domain -Port 80 -HostHeader $domain
    -PhysicalPath "$basis$domainwww"
 Set-ItemProperty "IIS:Sites$domain" ApplicationPool $Domain
 New-ItemProperty "IIS:Sites$domain" -name bindings
    -value (@{protocol="http";bindingInformation="*:80:WWW.$domain"})
 Set-ItemProperty "IIS:Sites$domain" -name logFile.directory
    -value "$basis$domainlogs"

# Gebruiker aanmaken met default password
$objOu = [ADSI]"WinNT://localhost"
$objUser = $objOU.Create("User", $domain)
$objUser.setpassword($defaultpass)
$objUser.SetInfo()

# Modify rechten voor de Gebruiker op de root van de hosting
$acl = Get-Acl "$basis$domain"
$permission = "$domain","Modify","ContainerInherit, 
    ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.
    FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$basis$domain"

# Lees en uitvoer rechten voor de App Pool gebruiker op de 
# root van de hosting
$acl = Get-Acl "$basis$domain"
$permission = "IIS AppPool$domain","ReadAndExecute","ContainerInherit, 
    ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.
    FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$basis$domain"

# Modify rechten voor de App Pool gebruiker op de DB en DATA map
$acl = Get-Acl "$basis$domainDATA"
$permission = "IIS AppPool$domain","Modify","ContainerInherit, 
    ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.
    FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$basis$domainDATA"

# Modify rechten voor de App Pool gebruiker op de DB en DATA map
$acl = Get-Acl "$basis$domainDB"
$permission = "IIS AppPool$domain","Modify","ContainerInherit, 
    ObjectInherit", "None", "Allow"
$accessRule = New-Object System.Security.AccessControl.
    FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
$acl | Set-Acl "$basis$domainDB"

# FTP Virtuale map aanmaken (virtuel map naam = gebruikersnaam = 
#    direct binnenkomen in deze map)
New-WebVirtualDirectory -Site "$ftpsite" -Name "$domain"
    -PhysicalPath "$basis$domain"

# Op niveau van de FTP site (niet op de virtuele map) geven we de user
# toestemming op de FTP site te lezen/schrijven (NTFS rechten beperken de rest)
Add-WebConfiguration -Filter /System.FtpServer/Security/Authorization
    -Value (@{AccessType="Allow"; Users="$domain";
        Permissions="Read, Write"})
    -PSPath IIS: -Location "$ftpsite"


Bij vragen of problemen met dit script hoor ik graag van u.

Powershell scripts digitaal ondertekenen

Out-of-the-box is uitvoeren van PowerShell scriptjes niet toestaan uit veiligheidsoverweging. Tijdens “de speeltijd” is dit makkelijk aan te passen met het PowerShell commando “Set-ExecutionPolicy”. Er zijn 4 verschillende execution policy’s nl.”Restricted” (default), “AllSigned”, “RemoteSigned” en “Unrestricted”.

In de standaard policy is scripts uitvoeren dus totaal onmogelijk. Wanneer de policy gewijzigd wordt naar “Unrestricted” dan kunnen alle scripts probleemloos uitgevoerd worden. Wordt de policy ingesteld op “AllSigned” kunnen alleen digitaal ondertekende scripts uitgevoerd worden en tenslotte als er geopteerd wordt voor “RemoteSigned” dan kunnen scripts op de lokale harde schijf sowieso uitgevoerd worden terwijl scripts vanop webpagina’s, e-mail etc … enkel uitgevoerd worden als ze digitaal ondertekend zijn.

Om na te gaan in welke modus je computer nu staat maak je gebruik van het commando “Get-ExecutionPolicy”

 1: PS C:UsersDDITDocuments> Get-ExecutionPolicy
 2: Restricted

 

En om in een test fase hier geen “last” meer van te hebben bedien je je van het commando

 1: Set-ExecutionPolicy -ExecutionPolicy Unrestricted

Voor het uitvoeren van het commando “Set-ExecutionPolicy” zijn wel administrator rechten nodig ! Maar zoals gezegd is deze oplossing sowieso enkel geschikt binnen development en testing doeleinden en niet echt op productie machines. We gaan onze scripts digitaal ondertekenen. We kunnen dat doen met aangekocht certificaten bij GlobalSign of Thawte maar we kunnen ook onze eigen certificaten uitschrijven. Die zijn technisch gezien perfect evenwaardig met de commerciële alternatieven …

We beginnen met ons “Root” certificaat te maken, we promoveren ons als het ware tot een soort GlobalSign. Op servers waar onze scripts moeten uitgevoerd worden zal dit root certificaat moeten toegevoegd worden aan de vertrouwde basis certificaten.

Certificaten maken kan met het gratis programmaatje “makecert.exe” dat oa. in de Windows SDK te vinden is. Als developper of sysadmin heb je die wellicht sowieso op je computer staan anders => http://msdn.microsoft.com/en-us/windowsserver/bb980924.aspxHet root certificaat dat je aanmaakt zal je kunnen beveiligen met een wachtwoord.

makecert
-n "CN=DDIT Root Cert"  <= naam van het root cert
-a sha1  <= hashing algoritme (kon md5 geweest zijn ook)
-eku 1.3.6.1.5.5.7.3.3  <= doel van het certificaat
-r  <= self signed
-sv root.pvk root.cer  <= bestandsnaam voor het certificaat + private key
-ss Root  <= de cert store waarin het cert geplaatst wordt
-sr localMachine <= de cert store location (default is Current User en we willen het cert toch voor iedereen op onze computer :)).

 

Nu gaan we op basis van ons net gemaakt root certificaat een certificaat maken om onze code mee te ondertekenen. Dit certificaat is wat je zou krijgen van GlobalSign / Thawte.

makecert
-pe  <= zorgt ervoor dat het certificaat geëxporteerd kan worden
-n "CN=PowerShell Dieter"  <= Naam van het certificaat
-ss MY  <=
-a sha1  <= Hashing algoritme
-eku 1.3.6.1.5.5.7.3.3  <= doel van het certificaat (code signing)
-iv root.pvk  <= Private key file van het root certificaat
-ic root.cer <= Root certificaat

 

Voor het aanmaken van het certificaat heb je het paswoord nodig van het root certificaat. Tijd om even te controleren in de GUI jQuery1520729151956219397_1312664369995 Start een MMC module en voeg de “Certificaten” module toe. ( mmc => Bestand, Module toevoegen of verwijderen => Certificaten => Mijn Gebruikersaccount). We vinden ons root certificaat

3

en ons zelf uitgeschreven certificaat

2

Set-AuthenticodeSignature
.GetRunningProcess.ps1  <= te ondertekenen file
@(Get-ChildItem cert:CurrentUserMy -codesigning)[0] <= handtekening

 

Na het uitvoeren van bovenstaand commando is de script file uitgebreid met je digitale handtekening. Mission Accomplished !!

1

Als je er nu voor zorgt dat de executionpolicy op AllSigned staat kan je het script uitvoeren … maar … je krijgt een melding dat het script getekend is door een onbekend iemand … Het volstaat om één keer “A” te antwoorden. Je code certificaat wordt dan ook toegevoegd aan de “Trusted Publishers”

4

Dit alles werkt nu op die ene computer waarop we de hele tijd gewerkt hebben. Als we ons script gaan uitvoeren op een andere computer waar de executionpolicy ingesteld staat op AllSigned zal ons script niet uitgevoerd worden omdat de uitgever van het certificaat niet gekend is (dat is ook logisch het root cert in kwestie bestaat nog maar net :)). Om dat probleem op te lossen moet je je zelf gemaakt root certificaat exporteren en importeren op de doel computer. Dit zijn zaken die je NIET hoeft te doen als je een certificaat koopt. De root certificaten van oa. GlobalSign, Thawte, VeriSign zitten standaard in de verschillende Windows omgevingen …

  1. MMC Module openen
  2. Module toevoegen/Verwijderen
  3. Certificaten
  4. Vertrouwde basiscertificeringsinstanties => Certificaten
  5. Rechtermuisklik op dit root certificaat => Alle Taken => Exporteren
  6. 2 x VOLGENDE => bestandslocatie + naam kiezen
  7. VOLTOOIEN
  1. Herhaal de stappen 1 – 4 maar nu op de doelcomputer
  2. Rechtermuisklik => Alle Taken => IMPORTEREN
  3. Kies het CER bestand
  4. Zorg ervoor dat het bestand geïmporteerd wordt in de “Vertrouwde basiscertificeringsinstanties”.