13 januari 2013

PowerShell

-nerd-alert!-

Ah, keuzes. Voor een klant werd ik gevraagd een import te doen vanuit een CSV bestand naar de database-applicatie waarin ben gespecialiseerd, Commence.

Dat begon heel simpel, maar werd al snel akelig complex. Commence, zo moet u weten, is niet erg gangbaar.  Een van de redenen daarvoor is dat het niet ODBC-compliant is. Que? Het is niet standaard. Je kunt er niet, zoals met MySQL, of MS SQL Server, of MS Access een 'verbinding' mee maken en leuke dingen met queries doen. Het heeft zelfs geen fatsoenlijke importfunctie. Commence Is Gewoon Bestwel Raar. Het is ook geweldig, maar niet als je het wilt koppelen aan een ander systeem.

Wel heeft het een API. Que? Een API is een manier om via het ene programma met het andere programma te praten. Zei ik dat Commence raar was? Nee, dan heb je de API niet bestudeerd! Klopt, hè? Gelukkig kan ik er na 14 jaar mee lezen en schrijven (ha, een kostelijke nerdwoordspeling). Die vaardigheid deel ik met een man of 5 hooguit in Nederland. Het is heerlijk om hyperspecialist te zijn in een applicatie die bijna niemand kent. Pft.

Nu goed, een ingewikkelde import dus. Klant levert een nogal complex CSV bestand aan. Aan mij de taak om de gegevens ervan in een aantal tabellen te frommelen, en deze ook nog een beetje kloppend aan elkaar te knopen. Oh wacht, de klant levert het niet aan. Ik moet het zelf gaan ophalen van een internet locatie. 'Is er een fijne webservice via REST of SOAP of zo?' zult u vragen. Neen, die is er niet. CSV het is, en die CSV moet via het antieke maar fijne FTP worden opgehaald. Daar heb je gelukkig programmaatjes voor, maar ik bouw liever niet nog een extra stap in, dus het liefst haal ik het bestand zelf even op.

Tot zover de inleiding.

Ik moet dus 2 dingen oplossen:
  1. CSV bestand ophalen
  2. CSV bestand verwerken
Ik kan deze uitdaging op een heleboel manieren aanvliegen. Zei ik 'aanvliegen'? Kastijd mij! Vreselijk woord, vreselijke zin. Sowwy.

Eén ervan is met VBScript. Daar ben ik behoorlijk goed in. VBScript is echter niet zo goed met internet. Een hoop dingen kunnen wel, maar zijn erg omslachtig. En VBScript is met zoals dat zo mooi heet 'deprecated'. Dat wil zeggen dat het nog wel bestaat, maar dat het uitgefaseerd zal gaan worden. Een soort computer-Sanskriet, zo u wilt.

Een mooi moment om mij eens te verdiepen in iets meer contemporains. Dat kan een 'echte' programmeertaal zijn. Ik spreek VB6 want ik ben oud, en een woordje C#.NET. Maar de klant wil een 'quick-and-dirty' oplossing, dus dat is geen optie. Dus wordt het een gescripte oplossing. Eentje die door Windows 'native' wordt ondersteund. PHP en Python en zo nog een paar vallen dus af. Blijven over VBScript, JavaScript en PowerShell.

Ik beheers JavaScript wel een beetje, maar ik voel me er niet zo in thuis. Eenvoudige taken zoals string-manipulaties en datum-manipulaties zijn er al snel overdreven complex in. Vind ik. En daarvan ga ik er veel nodig hebben. En JavaScript is verdomd moeilijk te lezen.

Blijft over PowerShell. Nooit wat mee gedaan, maar bijzonder krachtig, omdat je ermee direct toegang hebt tot .NET. Que? .NET is kort door de bocht een collectie van krachtige gereedschappen waarmee je van alles kunt doen. Het ophalen van een bestandje via FTP is met .NET een peulenschil vergeleken met VBScript. Ook heeft het krachtige instrumenten om gegevens heen en weer te smijten. Interessant genoeg om eens een keer mee te stoeien.

Zo gezegd, zo gedaan. Met frisse moed opende ik PowerShell ( Start | powershell). Ik kreeg een fijne DOS-prompt-achtige omgeving te zien. Dat ging hem niet worden, zelfs in DOS schreef ik geen BAT files via de command-prompt. Gelukkig bestaan er ook GUI omgevingen, en ik installeerde het fijne gratis PowerGUI.

First things first: eens kijken hoe we met Commence kunnen communiceren.

In VBScript gaat dat alsvolgt:

Set cmc = CreateObject("Commence.DB")

In PowerShell schrijf je:

$cmc = New-Object -ComObject Commence.DB

So far, so good.

Nu even de naam opvragen van de actieve database.

In VBScript doe je dat met:

naam = cmc.Name

In PowerShell doe je dat met

$naam = $cmc.Name

Maar wacht. Wat blijkt? De object-variable $cmc in PowerShell weet niets van Commence. Dat is gek! Want als ik doe:

$ie = New-Object -ComObject InternetExplorer.Application

dan krijg ik netjes alle eigenschappen en methoden van Internet Explorer te zien als ik '$ie.' typ.

Wat blijkt? (Lang verhaal dat ik u zal besparen) Wanneer ik het equivalent van cmc.Name in VBScript wil doen in PowerShell, dan moet ik schrijven:

$naam = [System.__ComObject].InvokeMember("Name",[System.Reflection.BindingFlags]::GetProperty,$null,$cmc,$null)

Ik sta dus voor de volgende keus: kies ik voor VBScript:

Set cmc = CreateObject("Commence.DB")
naam = cmc.Name

Of kies ik voor PowerShell:

$cmc = New-Object -ComObject Commence.DB
$naam = [System.__ComObject].InvokeMember("Name",[System.Reflection.BindingFlags]::GetProperty,$null,$cmc,$null)

Als ik mij was, dan wist ik het wel. Dan maar computer-Sanskriet :)


Geen opmerkingen: