Conditionele setup in Visual Studio 2008

Het bouwen en testen van een installatieset kost altijd meer tijd dan
gewenst. Het samenstellen van een gemiddelde installatie kan per project rustig
op een week werk uitmonden. Naast dat geduldig samenstellen van de uit te rollen programmaonderdelen, de dialogen en vereiste voorinstallaties (prerequisites) ben je ook enorm veel tijd kwijt met het correct aftesten op de verschillende OS-en waarop het moet landen.

Visual Studio levert tooling voor het samenstellen van een installatie in de
vorm van projecten en een wizard. Er zijn commerciële producten die veel verder
gaan met het bieden van gemak en functionaliteit maar de installer van MS komt
best wel een eindje. Je moet alleen geduld hebben om te puzzelen.

Vandaag heb ik de kans gehad om me te verdiepen in het conditioneel
installeren van registry-instellingen. Dit gaat ook op voor programmaonderdelen
en ‘custom actions’.

een militair verkleed als varen,gras, etc.

Stap 1: Start een solution in VS2008

Maak een nieuw WinForm project aan. Inhoudelijk is dit niet relevant maar we
moeten iets te installeren hebben 😉

Voeg een extra Setup Wizard project toe aan het eerste project:

Nieuw setup project

Behoudt de standaard keuzes maar voeg wel het eerste project toe:

Setup Wizard

Hercompileer alles en laat de setup samenstellen (rechtermuis- klik op het
setup project – Rebuild). Je kunt deze gerust een keer installeren en
de-installeren. Alle geïnstalleerde onderdelen worden weer netjes
verwijderd.

Stap 2: Voeg een dialoog voor de gebruikerskeuze toe

Bovenaan in de solution explorer is enigszins verstopt de toegang tot een
aantal schermen aanwezig. Hier kan oa. voor het onderhoud van de toe te voegen
scherm, registry sleutels en programma onderdelen gekozen worden:

Solution Explorer - dialogs

Kies binnen het setup project voor de user
interface editor. Kier hierbinnen voor het toevoegen van een extra
dialoog:

Add dialog

Vervolgens kan uit een aantal schermen
gekozen worden. Wij kiezen voor Checkboxes (A):

Checkboxes (A)

Plaats deze bij voorkeur in het Start blokje, vlak na het Welkom scherm.

Binnen VS2008 is dit scherm niet visueel. Alleen via de properties kan het
voorkomen veranderd worden. Er staan standaard vier checkboxen op. Schakel de laatste drie uit (visible = false) en vink de eerste standaard aan (Value =
Checked). Pas wat teksten aan en vul de property waarde met
CHECKBOXADDKEY:

Dialog Properties

Build opnieuw het Setup project en zie dat
inderdaad het scherm netjes getoond wordt:

Bekijk het maar

Stap 3: De magie…

Ok, het scherm is gebouwd; de keuze is gemaakt. Nu moet dit toegepast gaan
worden. Open de registry Editor en voeg een sleutel en waarde toe.

Hier wordt HKEY_CURRENT_USER | Bla | BLABla | BlaBlaBla
toegevoegd:

Registry sleutel toevoegen

En als extraatje wordt op een condition opgegeven die verwijst naar de
checkbox op het door ons toegevoegde dialoog met als property
CHECKBOXADDKEY:

Voeg de conditie toe

Build het Setup project voor de laatste keer en doorloop de installatie
succesvol (laat ons vinkje actief).

Open de Windows Registry Editor (regedit) en navigeer naar onze toegevoegde
sleutel:

Now you see me, now you don't...

De-installeer de setup en installeer deze vervolgens nogmaals maar nu zonder
het vinkje en zie dat de registry sleutel ditmaal niet aangemaakt wordt.

Conclusie

Het is kinderspel geworden om de gebruiker (beperkte) invloed op het verloop
van de installatie te laten uitoefenen. Het is niet mogelijk om de checkbox
conditioneel aan of uit te vinken maar voor de meeste doeleinden is de hierboven
beschreven functionaliteit meer dan voldoende.

Advertentie

VSTO is voor mannen met borsthaar

Echt waar.

Visual Studio Tools for Office oftewel VSTO oftewel visto mag
er dan nog zo gelikt uitzien met al die fraaie gold plating in de vorm
van Ribbons of Task Panes; bij de basis is het nog steeds die goeie, oude
ole-automation.

Natuurlijk heeft VSTO een aantal sterke punten die het heel interessant maken
om voor bedrijfsapplicaties te gebruiken. Die visuele zaken in Office 2007
zorgen voor een lage instap en versnelde productiviteit. Iedereen die Office
kent, kan sneller overweg met een OBA (Office Business Application) dan met een maatwerk applicatie waarvoor een beginnende medewerker dagen tot weken op cursus moet. Voor een medewerker die net iets meer dan het minimumloon mag kosten, ga je geen training van honderden euro’s per dag organiseren.

There are some ??? google can not answer. Uithangbord voor de kerk Church of God

Goedkoop is de sleutel tot VSTO. Wat we dus verwachten is dat OBA applicaties
snel en eenvoudig te bouwen zijn, en je zou verwachten dat dit met
ontwikkelomgevingen zoals Visual Studio 2008 ook wel zo zou zijn. Maar dan
VSTO…

Als je op het web op zoek gaat naar de achilleshiel van VSTO, dan wordt
meestal de installatie van zo’n applicatie op Vista genoemd. Het is inderdaad
lastig om bv. een succesvolle installatie voor een Excel add-in te produceren,
maar het is niet ondoenlijk. Voor VSTO is een installatie blijkbaar een klusje
voor de administrator dus wil Vista in Elevated Mode draaien. Hiervoor moet je
in verhouding alleen maar ‘droog achter de oren’ zijn.

Maar je hebt pas echt borsthaar nodig als je tegen de DOM (Document Object
Model) aan wilt programmeren. Dit is iets wat we rond het millennium achter ons lieten toen we webapplicaties in managed code gingen bouwen.  En dit is dus het gebied waarbij je Excel.WorkBook, Excel.WorkSheet, Excel.Range etc. met
bedrijfslogica probeert te combineren om zo aardige functionaliteit aan de
gebruiker te kunnen aanbieden.

Een voorbeeld:

Sinds enige tijd zijn wij bezig om in Excel 2007 een prachtige OBA te bouwen.
Dit gaat voorspoedig maar toen besloten we om te achterhalen in welke Excel.Name de actief geselecteerde cel staat.

Een Excel.Name (what in the name…) is een alternatieve benaming voor een
cel of een aantal aaneengesloten cellen (X rijen maal Y kolommen groot). Zo kan
je een cel met daarin 6,0 gewoon LaagBtw noemen en later daarmee doorrekenen (=LaagBtw*BrutoArtikelPrijs).

Om dus te controleren of de cel in een name staat kom je uit bij Excel.Range.
Een Range is een willekeurig aantal cellen, zoals een Excel.Name en de actieve
selectie van de gebruiker. Excel biedt de mogelijkheid om overlap bij twee
ranges te registreren en dat gaan we dus gebruiken.

Laten we de MSDN er eens op naslaan:

expression.Intersect(Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
Arg7,
Arg8,
Arg9,
Arg10,
Arg11,
Arg12,
Arg13,
Arg14,
Arg15,
Arg16,
Arg17,
Arg18,
Arg19,
Arg20,
Arg21,
Arg22,
Arg23,
Arg24,
Arg25,
Arg26,
Arg27,
Arg28,
Arg29,
Arg30)

Dit ziet er lelijk uit maar we gaan gewoon stug door (in .Net 4.0 wordt het
mogelijk om 28 van de 30 parameters weg te laten, iets wat al wel bij VB.Net
werkt):

Range activeRange = Globals.ThisAddIn.Application.ActiveCell;
Range nameRange = ExtractRange("aaa");
Range intersection = Globals.ThisAddIn.Application.Intersect(
  activeRange, nameRange,Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing);

if (intersection != null)
{
  MessageBox.Show("Overlap!");
}
else
{
  MessageBox.Show("Helaas...");
}

Hierbij gebruiken we een handige methode om een Excel.Name op naam te zoeken en naar een Excel.Range om te zetten:

private static Range ExtractRange(string rangeName)
{
  Name name = null;
  try
  {
    // haal de name op
    name = (Name) Globals.ThisAddIn.Application.
               Names.Item(rangeName, Type.Missing, Type.Missing);
  }
  catch (Exception)
  {
    return null;
  }

  if (name == null) { return null; } // escape
  // haal de range op
  Range range = name.RefersToRange;
  return range;
}

Na het compileren kan dit getest worden in Excel. We benoemen op het
worksheet van een workbook een aantal cellen met de Name “aaa” en
selecteren een andere cel er iets naast of juist er binnen.

En inderdaad, het aftesten van de overlap werkt fraai.

Maar toen deze code omgesmeed werd naar echte code kregen we op een gegeven moment de volgende foutmelding:

Schermafdruk van een COM foutmelding bij VSTO

Geen verdere uitleg, geen hint en inderdaad, Google heeft niet overal een
antwoord op (-2146827284 geeft geen hit). Ook de MSDN en de schaarse boeken over dit onderwerp bleven in gebreke.

Uiteindelijk zijn we eruit gekomen door weer naar de basis te gaan, dus
bovenstaande code uit een test applicatie. En wat bleek? Om een intersection te
mogen uitvoeren, moeten de twee ranges op dezelfde Excel.WorkSheet geplaatst
zijn. Gelukkig kan van een Excel.Range de Excel.WorkSheet opgevraagd worden
waarop deze is geplaatst dus komen we tot de volgende code:

/// <summary>
/// Extracts the intersection.
/// </summary>
/// <param name="range1">The range1.</param>
/// <param name="range2">The range2.</param>
/// <returns></returns>
public static Excel.Range ExtractIntersection(Range range1, Range range2)
{
  if (range1.Worksheet != range2.Worksheet)
  {
    return null; // not placed on the same WorkSheet
  }

  Range intersection = (Range) Globals.ThisAddIn.Application.Intersect(
    range1, range2, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing);
  if (intersection != null)
  {
    return intersection;
  }
  else
  {
    return null;
  }
}

En als je bedenkt dat VSTO dus schaars gedocumenteerd is met helpteksten bij
de methodes en dat alles run-time via Transparant Proxies werkt waardoor debuggen moeizaam is, dan mag je ook wel wat haar op je rug hebben.

StarWars Wookie met haar

Microsoft: als OBA jullie redding moet zijn voor SaS (Software and Services; Office op de client, diensten vanuit het netwerk/internet/cloud), zorg dan dat VSTO zich echt managed gedraagt. Of is dit de ware reden waarom C# 4.0 hernieuwde aandacht voor COM Interop toont?