Le blog technique

Toutes les astuces #tech des collaborateurs de PI Services.

#openblogPI

Retrouvez les articles à la une

Script Powershell – Desinstallation d’application

 

Le script suivant prends en paramètre un nom de machine et un nom d’application (apparaissant dans Ajout-suppression de programme), desinstalle l’application si elle est trouvée, affiche les resultats et les inscris dans un fichier de log.

 

 

Param(
[Parameter(Mandatory = $true)][string]$computername=(read-host -Prompt "entrez le nom de la machine"),
[Parameter(Mandatory = $true)][string]$application=(read-host -Prompt "entrez le nom exact de l’application"),
[string]$credential="administrator"
)

$logfile="c:\result.txt"
$now=(get-date).ToString()

$appuninstall=Get-WmiObject -ComputerName $computername -Class win32_product -Credential $credential | where-object {$_.name -eq $application}

if ($appuninstall -eq $null)
{
write-host "Application $application non trouvée" -ForegroundColor yellow -BackgroundColor black
write-host "Resultat inscris dans $logfile" -ForegroundColor yellow -BackgroundColor black
Out-file $logfile -Append -InputObject "$now — Application $application non trouvée sur $computername"
exit
}

foreach ($app in $appuninstall)
{
  write-host "…debut desinstallation…" -ForegroundColor yellow -BackgroundColor black
  $app.uninstall()| Tee-Object -Variable uninstallresult
if ($uninstallresult.ReturnValue -eq 0)
    {
    write-host "Desinstallation OK pour $computername" -ForegroundColor green -BackgroundColor black
    write-host "Resultat inscris dans $logfile" -ForegroundColor green -BackgroundColor black
    Out-file $logfile -Append -InputObject "$now — Desinstallation OK pour $computername"
    }
    else
    {
    write-host "Desinstallation KO pour $computername" -ForegroundColor red -BackgroundColor black
    Out-file $logfile -Append -InputObject "$now — Desinstallation KO pour $computername"
    write-host "Resultat inscris dans $logfile" -ForegroundColor red -BackgroundColor black
    }
}

BlogEngine.NET en Haute-Disponibilité

 

Présentation de BlogEngine.NET

BlogEngine.NET est une plateforme de blog open-source développé en C#, elle permet entre-autres la gestion des auteurs, des posts et ne requiert ni base de donnée ni installation.

Toutes les fonctionnalités ici.

Contexte

Pour la configuration de serveurs WEB en Haute-Dispo, il est possible de créer entre les serveurs une réplication des dossiers de BlogEngine à l’aide de DFS-R.

Suite à la mise en place de la réplication DFS-R entre les deux serveurs Web, une latence d’environ une heure lors de l’ajout (ou la modification) d’un post à partir d’un serveur et la visualisation sur le second est apparue.

Cette latence n’est pas due à DFS-R car au niveau du système il est visible que le post (enregistré au format XML) a correctement été répliqué.

Explication

Afin d’assurer un temps de réponse optimal, BlogEngine dispose d’un cache interne qui est mis à jour automatiquement.

Résolution

Pour de palier à ce problème il suffit de modifier la page default.aspx.cs située à la racine du répertoire de BlogEngine en ajoutant au début de la fonction Page_Load() la commande BlogEngine.Core.Post.Reload() comme ceci :

image

Ce qui permettra à chaque fois que l’utilisateur se connecte sur la page Accueil, de recharger le cache.

SCOM 2007 : Hériter des tâches depuis un MP parent

Ou comment séparer la définition de l’affichage des tâches.

Voici un problème qui m’a été posé par un de nos clients : comment réutiliser des tâches définies dans un premier Management Pack dans un ou plusieurs autres MP, sans avoir à les recoder à chaque fois ? Après recherche, voici la solution qui a été retenue.

Prenons un exemple simple : via la console Authoring, créons dans un nouveau management pack une tâche console qui lance la calculatrice Windows.

clip_image002

Une fois enregistré non-scellé, le code xml de ce management pack très basique est le suivant :

<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Manifest>
    <Identity>
      <ID>MP_ExempleTask</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>MP_ExempleTask</Name>
    <References>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <ModuleTypes>
      <ProbeActionModuleType ID="calcType" Accessibility="Public" Batching="false" PassThrough="false">
        <Configuration />
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <ProbeAction ID="PA" TypeID="System!System.CommandExecuterProbe">
                <ApplicationName><![CDATA[%WINDIR%\System32\calc.EXE]]></ApplicationName>
                <WorkingDirectory />
                <CommandLine>/ALL</CommandLine>
                <TimeoutSeconds>30</TimeoutSeconds>
                <RequireOutput>true</RequireOutput>
                <Files />
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="PA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
        <InputType>System!System.BaseData</InputType>
      </ProbeActionModuleType>
    </ModuleTypes>
  </TypeDefinitions>
  <Presentation>
    <ConsoleTasks>
      <ConsoleTask ID="Task.LocalCalc" Accessibility="Internal" Enabled="true" Target="System!System.Entity" RequireOutput="true" Category="MonitoringObject">
        <Application>%systemroot%\system32\calc.exe</Application>
        <WorkingDirectory />
      </ConsoleTask>
    </ConsoleTasks>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="FRA" IsDefault="false">
      <DisplayStrings>
        <DisplayString ElementID="MP_ExempleTask">
          <Name>MP Exemple Task</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Task.LocalCalc">
          <Name>Ouvrir Calculatrice</Name>
          <Description />
        </DisplayString>
        <DisplayString ElementID="MP_ExempleTask">
          <Name>MP Exemple Task</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

La suite de la manœuvre implique d’utiliser un éditeur de texte : il va falloir séparer les parties « manifest », « défintion » et « affichage » de votre management pack.

Le manifest est le code compris entre les balises <Manifest></Manifest> (surligné plus haut en vert) :

<Manifest>
    <Identity>
      <ID>MP_ExempleTask</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>MP_ExempleTask</Name>
    <References>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>

La partie définition est l’ensemble du code compris entre les balises <TypeDefinitions>[…]</TypeDefinitions> (surligné plus haut en bleu). C’est cette partie qui contient le code de « ce que font » les tâches à proprement parler :

<TypeDefinitions>
    <ModuleTypes>
      <ProbeActionModuleType ID="calcType" Accessibility="Public" Batching="false" PassThrough="false">
        <Configuration />
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <ProbeAction ID="PA" TypeID="System!System.CommandExecuterProbe">
                <ApplicationName><![CDATA[%WINDIR%\System32\calc.EXE]]></ApplicationName>
                <WorkingDirectory />
                <CommandLine>/ALL</CommandLine>
                <TimeoutSeconds>30</TimeoutSeconds>
                <RequireOutput>true</RequireOutput>
                <Files />
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="PA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
        <InputType>System!System.BaseData</InputType>
      </ProbeActionModuleType>
    </ModuleTypes>
  </TypeDefinitions>

La partie “affichage” est quant à elle celle qui est comprise entre les balises <Presentation>[…]</LanguagePacks> (surlignée plus haut en rouge). C’est cette partie qui se charge de faire apparaitre les tâches dans la console SCOM :

<Presentation>
    <ConsoleTasks>
      <ConsoleTask ID="Task.LocalCalc" Accessibility="Internal" Enabled="true" Target="System!System.Entity" RequireOutput="true" Category="MonitoringObject">
        <Application>%systemroot%\system32\calc.exe</Application>
        <WorkingDirectory />
      </ConsoleTask>
    </ConsoleTasks>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="FRA" IsDefault="false">
      <DisplayStrings>
        <DisplayString ElementID="MP_ExempleTask">
          <Name>MP Exemple Task</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Task.LocalCalc">
          <Name>Ouvrir Calculatrice</Name>
          <Description />
        </DisplayString>
        <DisplayString ElementID="MP_ExempleTask">
          <Name>MP Exemple Task</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>

Vous avez isolé ces deux parties? Bien, nous allons pouvoir passer à la suite : il faut maintenant construire deux management packs séparés, et ce toujours à l’aide d’un éditeur de texte.
En toute logique, le premier contiendra la partie définitions et le second la partie affichage… ainsi que quelques subtilités :

Pour le premier, c’est assez simple. Créons un fichier texte que nous nommerons par exemple mp1.xml et copions-y la partie « définition » préalablement extraite, précédée du manifest, le tout encadré par les balises <ManagementPack> nécessaires à la conformité de tout MP :

<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Manifest>
    <Identity>
      <ID>MP1</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>MP1</Name>
    <References>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <ModuleTypes>
      <ProbeActionModuleType ID="calcType" Accessibility="Public" Batching="false" PassThrough="false">
        <Configuration />
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <ProbeAction ID="PA" TypeID="System!System.CommandExecuterProbe">
                <ApplicationName><![CDATA[%WINDIR%\System32\calc.EXE]]></ApplicationName>
                <WorkingDirectory />
                <CommandLine>/ALL</CommandLine>
                <TimeoutSeconds>30</TimeoutSeconds>
                <RequireOutput>true</RequireOutput>
                <Files />
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="PA" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
        <InputType>System!System.BaseData</InputType>
      </ProbeActionModuleType>
    </ModuleTypes>
  </TypeDefinitions>
</ManagementPack>

Notez que j’ai également modifié l’ID et le Nom de ce MP, qui s’appelle désormais “MP1”.

Une fois ce fichier XML achevé, il faudra le sauvegarder en tant que Management Pack scellé et noter sa clé publique ; autrement il ne sera pas possible de l’importer dans les MP qui devront y faire appel, puisqu’on ne peut pas hériter d’un MP non scellé.

Passons ensuite au MP2 : il contient également le Manifest (auquel j’ai apporté quelques modifications, détaillées plus bas), suivi cette fois uniquement de la partie affichage :

<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Manifest>
    <Identity>
      <ID>MP2</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>MP2</Name>
    <References>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
<Reference Alias="MP1">
<ID>TaskMP1</ID>
<Version>1.0.0.0</Version>
<PublicKeyToken>0823A712C344907</PublicKeyToken>
      </Reference>

    </References>
  </Manifest>
<Presentation>
    <ConsoleTasks>
      <ConsoleTask ID="Task.LocalCalc" Accessibility="Internal" Enabled="true" Target="System!System.Entity" RequireOutput="true" Category="MonitoringObject">
        <Application>%systemroot%\system32\calc.exe</Application>
        <WorkingDirectory />
      </ConsoleTask>
    </ConsoleTasks>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="FRA" IsDefault="false">
      <DisplayStrings>
        <DisplayString ElementID="MP_ExempleTask">
          <Name>MP Exemple Task</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Task.LocalCalc">
          <Name>Ouvrir Calculatrice</Name>
          <Description />
        </DisplayString>
        <DisplayString ElementID="MP_ExempleTask">
          <Name>MP Exemple Task</Name>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

Comme vous pouvez le voir dans la partie surlignée, le MP2 hérite du MP1.

Nous avons donc désormais un MP1.mp (MP1 scellé) et un MP2.xml, qu’il ne reste plus qu’à importer dans la console SCOM l’un après l’autre : les tâches stockées dans le MP1 et appelées dans le MP2 apparaissent bien.

Il sera par la suite possible d’appeler de la même façon les tâches définies dans le MP1 dans autant de management packs « enfants » que nécessaire.