<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Laurent VAN ACKER's Blog : IIS, PowerShell, ASP.Net ...</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/lavanack/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/lavanack/feed.xml</link>
    <description>Premier Field Engineer | Microsoft France</description>
    <lastBuildDate>Wed, 24 Apr 2019 13:45:08 GMT</lastBuildDate>
    <language>fr_FR</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Nouveau blog / New blog location</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/nouveau-blog-new-blog-location</link>
      <pubDate>Wed, 24 Apr 2019 14:45:07 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=2255</guid>
      <description><![CDATA[Bonjour, le blog est maintenant disponible sur https://www.laurentvanacker.com/Hello, the blog is...]]></description>
      <content:encoded><![CDATA[<p><br></p><p>Bonjour, le blog est maintenant disponible sur <a title="https://www.laurentvanacker.com/" href="https://www.laurentvanacker.com/">https://www.laurentvanacker.com/</a></p><p>Hello, the blog is now available at <a title="https://www.laurentvanacker.com/" href="https://www.laurentvanacker.com/">https://www.laurentvanacker.com/</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Exclusions antivirus pour IIS / Antivirus exclusions for IIS</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/exclusions-antivirus-pour-iis-antivirus-exclusions-for-iis</link>
      <pubDate>Tue, 27 Nov 2018 11:02:00 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=2235</guid>
      <description><![CDATA[English versionDans le cadre d’un audit IIS ou d’un IIS RaaS, l’un des points de vérification et la...]]></description>
      <content:encoded><![CDATA[<p><div id="fr-FR"><a href="#en-US">English version</a></div><p align="justify">Dans le cadre d’un audit IIS ou d’un <a href="https://go.microsoft.com/fwlink/?LinkID=393865">IIS RaaS</a>, l’un des points de vérification et la présence d’un antivirus et le cas échéant de sa configuration. Un antivirus peut être un allié précieux dans la sécurisation de votre serveur&nbsp; mais peut également être votre pire ennemi en termes de performances</p><p align="justify">Une configuration inappropriée (souvent par défaut) réduira significativement la performance de votre serveur. Je propos dans cette article de lister quelques bonnes pratiques et de voir les exclusions à mettre en pkace pour optimiser votre serveur. Bien sûr toutes ces reommendations doivent être replacées dans votre contexte et discutées avec votre équipe sécurité ou votre <a href="https://fr.wikipedia.org/wiki/Responsable_de_la_s&eacute;curit&eacute;_des_syst&egrave;mes_d%27information">RSSI</a>.</p><p align="justify">Les emplacements spécifiés ici sont les emplacements par défaut (il est parfois recommandé d’utiliser un autre emplacement : fichiers de logs, contenu web ..) </p><p align="justify"><strong>Solution Anti-Virus </strong></p><p align="justify">Les anti-virus, utiles dans la prévention des malwares et autres virus sur vos serveurs Web, peuvent également fonctionner en mode de détection et de suppression. Il est recommandé de disposer d’un antivirus sur les serveurs de production pour analyser régulièrement les dossiers de contenu et le système en général, à la recherche de programmes malveillants qui pourraient s'y trouver. L'antivirus doit toutefois être configuré avec soin afin d'éviter toute surcharge inutile du système. L’absence d’anti-virus offre un avantage en termes de performances mais rendre votre système vulnérable aux attaques et aux logiciels malveillants.</p><p align="justify"><strong>Scan en temps réel</strong></p><p align="justify">Un scan en temps réel assure une protection continue du serveur contre le contenu mal intentionné qui pourrait affecter votre système. Toutefois, il est recommandé de le configurer de manière approprié afin de réduire la surcharge associée sur les serveurs.</p><p align="justify"><b>Scan en lecture</b></p><p align="justify">L'analyse en temps réel rajoute une surcharge parfois non négligeable sur votre serveur. L'une des optimisations possibles consiste à désactiver l'analyse en lecture. Toutefois, la problématique d’une clé USB branchée (ou tout lecteur amovible) sur le serveur demeure. Elle pourrait être la source d’exécution de programmes potentiellement dangereux et ceux-ci ne seraient pas interceptés par l’anti-virus. Il est donc recommandé de ne pas connecter de périphériques externes aux serveurs pour atténuer ce problème.</p><p align="justify"><strong>Scan en écriture</strong></p><p align="justify">L'une des principales actions pouvant rendre un serveur vulnérable, est l'introduction de logiciels malveillants dans le système. Cette opération est généralement réalisée en copiant le contenu infecté sur le serveur. Effectuer un scan en temps réel des écritures sur le serveur vous aidera à protéger le serveur contre de tels vecteurs d’attaque (intentionnels ou non). Etant donné que les écritures ne sont pas fréquentes dans les dossiers de contenu et les dossiers système, il est recommandé de l'activer sur ces emplacements.</p><p align="justify"><strong>Exclusions</strong></p><ul><li><div align="justify"><b>Worker processes</b></div></li></ul><p>Le contenu web est servi par les processus des “Application Pools”. Ils sont appelés “worker processes” (w3wp.exe). Si vous êtes confiant dans le contenu généré par votre code vous pouvez ajouter ces binaires&nbsp; dans les exclusions de votre antivirus :<ul><ul><li><strong><em>64-bit worker process : %SYSTEMROOT%\system32\inetsrv\w3wp.exe</em></strong></li><li><strong><em>32-bit worker process : </em></strong><strong><em>%SYSTEMROOT%\SysWOW64\inetsrv\w3wp.exe</em></strong></li></ul></ul><p><br><ul><li><div align="justify"><b>Fichiers de Log</b></div></li></ul><p align="justify">L’un des répertoires les plus actifs sur un serveur Web d’un point de vue écriture est le répertoire des logs des applications et sites hébérgés sur le serveur. Idéalement, ces emplacements doivent être déplacés sur un disque/partition en dehors du dissque système. Il est d’ailleurs recommandé d’exclure ces répertoire du scan en écriture en temps réel afin de ne pas surcharger inutilement le serveur.<ul><ul><li><strong><em>Default Logging Location : %SYSTEMDRIVE%\Inetpub\Logs\LogFiles</em></strong></li><li><strong><em>Default FREB Logging Location : %SYSTEMDRIVE%\inetpub\logs\FailedReqLogFiles</em></strong></li><li><strong><em>Default HTTP.SYS Logging Location : %WINDIR%\System32\LogFiles\HTTPERR</em></strong></li></ul></ul><p><br></p><ul><li><div align="justify"><b>Temporary Compressed Files</b></div></li></ul><p align="justify">Le répertoire IIS Temporary Compressed Files est constamment utilisé en écriture par le le worker process lors de la gestion du contenu statique. La surcharge engendrée sur le système peut être réduite en excluant les écritures sur ce dossier (en particulier sur un système déjà chargé).<p align="justify"><strong><em>%SYSTEMDRIVE%\Inetpub\temp\IIS Temporary Compressed Files</em></strong><p align="justify"><strong><br></strong></p><ul><li><div align="justify"><strong>Temporary ASP.NET Files</strong></div></li></ul><p align="justify">Lorsque vous utilisez ASP.NET, le dossier “Temporary ASP.NET Files” est utilisé par .NET Framework pour stocker la sortie compilée des pages servies par l'application. En fonction de la configuration de l'application et de son utilisation, ce dossier risque de générer beaucoup de trafic en écriture. La surcharge induite pourrait être réduite en excluant les écritures sur ce répertoire dans la configuration de la solution anti-virus.<ul><ul><li><strong><em>Default folder for x86 compiled ASP.Net Code : %WINDIR%\Microsoft.NET\Framework\{version}\Temporary ASP.NET Files</em></strong></li><li><strong><em>Default folder for x64 compiled ASP.Net Code : %WINDIR%\Microsoft.NET\Framework64\{version}\Temporary ASP.NET Files</em></strong></li></ul></ul><p><br></p><ul><li><div align="justify"><b>Temporary ASP Files</b></div></li></ul><p align="justify">Lors de l’utilisation de code ASP classique (vs. .Net), le répertoire “ASP Compiled Templates” est utilisé pour stocker les pages compilées servies par l’application. En fonction de la configuration de l'application et de son utilisation, ce dossier risque de générer beaucoup de trafic en écriture. La surcharge induite pourrait être réduite en excluant les écritures sur ce répertoire dans la configuration de la solution anti-virus.<ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\temp\ASP Compiled Templates</em></strong></li></ul></ul><p><br><ul><li><strong>Répertoires d’installation des binaires IIS</strong></li></ul><strong></strong><p>Les binaires IIS binaries sont localisés dans les deux répertoires suivants : <br></p><ul><ul><li><em><strong>64-bit binaries : %WINDIR%\System32\Inetsrv<br></strong></em></li><li><em><strong>32-bit binaries : %WINDIR%\SysWOW64\Inetsrv</strong></em></li></ul></ul><p><strong><br></strong></p><ul><li><strong>Répertoire de Configuration IIS </strong></li></ul><strong></strong><p align="justify">IIS7 + utilise un système de configuration basé sur XML pour stocker les paramètres IIS qui remplace la métabase utilisée dans IIS 6.0 et versions antérieures. Ce nouveau système de configuration a été introduit avec ASP.NET et repose sur un système hiérarchique de système de gestion qui utilise des fichiers * .config. Les fichiers de configuration pour IIS 7 et versions ultérieures se trouvent dans votre dossier% WinDir% \ System32 \ Inetsrv \ Config.<br></p><strong><em></em></strong><ul><ul><li><strong><em>%WINDIR%\System32\Inetsrv\Config</em></strong></li></ul></ul><p><br></p><ul><li><strong>Schema pour la Configuration IIS </strong></li></ul><p>Le schéma des paramètres IIS constitue la base de la configuration d'IIS 7.0. La plupart des propriétés de métabase que vous utilisiez dans les versions précédentes d'IIS ont été converties en éléments ou en attributs dans le schéma.</p><ul><ul><li><strong><em>%WINDIR%\System32\Inetsrv\Config\Schema</em></strong></li></ul></ul><p><br></p><ul><li><strong>Emplacement du contenu (par défaut) </strong></li></ul><p align="justify">Par défaut le contenu de vos sites est stocké dans le répertoire ci-dessous (Il est d’ailleurs recommandé de le mettre sur un disque, une paritition ou une LUN dédiée)<br></p><em></em><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\WWWRoot</em></strong></li></ul></ul><p><br></p><ul><li><strong>Default History Location<br></strong></li></ul><p align="justify">This folder keeps a running history of changes to your configuration files. This history is especially useful for recovering from mistakes made when manually editing your configuration files.</p><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\History</em></strong></li></ul></ul><p><br></p><ul><li><strong>Emplacement des backup de configuration (par défaut)</strong></li></ul><p align="justify">Depuis IIS 7, vous pouvez créer et gérer les sauvegardes de vos configurations en utilisant l’outil Appcmd.exe. Par défault, ces sauvegardes sont stockés dans des sous-répertoires de %SystemDrive%\Inetpub\History.<br></p><ul><ul><li><strong><em>%WINDIR%\System32\Inetsrv\backup</em></strong></li></ul></ul><p><br></p><ul><li><strong>Emplacement de l’isolation de configuration (par défaut)</strong></li></ul><p align="justify">L’isolation des Application Pool est une nouvelle fonctionnalité apparue avec IIS7. Un fichier de configuration dédié à chaque application pool est automatiquement crée lors du démarrage de chaque Application Pool. L’emplacement par défaut de ces fichiers est :<br></p><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\temp\appPools</em></strong></li></ul></ul><p><br></p><ul><li><strong>Répertoires de pages d’erreur (par défaut)</strong></li></ul><p align="justify">IIS7+ stocke les pages d’erreurs personalisées dans <br></p><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\custerr</em></strong></li></ul></ul><p align="justify"><strong><br></strong></p><p><strong>Lectures recommandées</strong><p><a href="https://support.microsoft.com/fr-fr/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni">Recommandations d’analyse antivirus pour les ordinateurs d’entreprise qui exécutent des versions de Windows prises en charge</a></p><p><a href="https://support.microsoft.com/fr-fr/help/817442/a-0-byte-file-may-be-returned-when-compression-is-enabled-on-a-server">Un fichier de 0 octet peut être renvoyé lorsque la compression est activée sur un serveur qui exécute IIS</a></p><p><a href="https://support.microsoft.com/en-us/help/821749/antivirus-software-may-cause-iis-to-stop-unexpectedly">Antivirus software may cause IIS to stop unexpectedly</a></p><p><hr><div id="en-US"><a href="#fr-FR">Version française</a></div><div></div><p><br></p><p>In the context of IIS audit or <a href="https://go.microsoft.com/fwlink/?LinkID=393865">IIS RaaS</a>, one of the verification points is the presence of an antivirus and, if applicable, its configuration. This can be a valuable ally in securing your server but can also be your worst enemy in terms of performance. </p><p>An inappropriate configuration (often by default) will significantly slow down your IIS server. I propose in this article to list some good practices and see the exclusions to set up to optimize your server. Of course all these recommendations must be put in context and discussed with your security team or <a href="https://en.wikipedia.org/wiki/Chief_information_security_officer">CISO</a></p><p>The locations specified here are the default locations (Sometimes it is a best practices to use alternate location : log files, web content …)</p><p align="justify"><b>Anti-Virus Solution </b><p align="justify">Anti-Virus solutions can help in preventing malware from infecting web servers, and can also work in a detection and removal mode when appropriate. It is recommended to have an Anti-Virus solution on the production servers to regularly scan the content folders and the system in general, for any malware that might have made it on there. The anti-virus when present, however, needs to be configured carefully so as to avoid adding unnecessary overhead to the system while protecting it. Not having an anti-virus solution altogether, while providing a performance benefit potentially, can also make the web servers susceptible to unknown malware attacks.<p align="justify"><b>Real-time Scanning</b><p align="justify">Having the antivirus solution monitor the servers in real-time provides for constant protection of the web server from malformed content that might make it to the system by accident or intentionally. However, if and when this is enabled, it is recommended to be configured in a way that reduces the overhead associated with it on the servers.<p align="justify"><b>Read Operation Scan</b><p align="justify">When real-time scanning is enabled on the web server, care has to be taken to not add overhead to the system due to the scanning operations. One of the optimizations that can be done is to disable reads from being scanned. However, this does entertain the possibility that any removable disk drives attached to the system, can run potentially harmful programs and these would not be caught by the Anti-virus program. It is recommended to not attach external devices to the servers to mitigate this problem.<p align="justify"><b>Write Operation Scan</b><p align="justify">One of the primary actions that can cause web servers to become vulnerable is the introduction of malware into the system, and that is usually accomplished by copying the infected content to the server. By having an anti-virus scan writes to the server in real-time will help in protecting the server from such attack vectors (intended and unintended). Since writes do not happen frequently on the content folders and system folders, it is recommended to have this turned ON in those locations primarily to protect the server while reducing the overhead involved due to its usage.<p align="justify"><strong>Exclusions</strong><ul><li><div align="justify"><b>Worker processes</b></div></li></ul><p>Your web content is served by the processes of the Application Pools. They are called worker processes (w3wp.exe). If you are confident in the content generated by your code you can add the binaries in the exclusions of your antivirus solution :<ul><ul><li><strong><em>64-bit worker process : %SYSTEMROOT%\system32\inetsrv\w3wp.exe</em></strong></li><li><strong><em>32-bit worker process : </em></strong><strong><em>%SYSTEMROOT%\SysWOW64\inetsrv\w3wp.exe</em></strong></li></ul></ul><p><br><ul><li><div align="justify"><b>Log Files</b></div></li></ul><p align="justify">One of the busiest folders on a web server from a write perspective is the log file folder for the applications and sites running on the server. Typically, these locations are recommended to be away from the system drive, so it is recommended to exclude these folders from real-time write scanning to prevent unnecessary overhead on the system while not potentially adding vulnerabilities to it. <ul><ul><li><strong><em>Default Logging Location : %SYSTEMDRIVE%\Inetpub\Logs\LogFiles</em></strong></li><li><strong><em>Default FREB Logging Location : %SYSTEMDRIVE%\inetpub\logs\FailedReqLogFiles</em></strong></li><li><strong><em>Default HTTP.SYS Logging Location : %WINDIR%\System32\LogFiles\HTTPERR</em></strong></li></ul></ul><p><br></p><ul><li><div align="justify"><b>Temporary Compressed Files</b></div></li></ul><p align="justify">IIS Temporary Compressed Files folder on the web server is constantly being written to by the worker process in the process of serving static content. System overhead can be reduced if write actions into this folder are not constantly scanned by the anti-virus solution, especially on a busy system.<ul><ul><li><p><strong><em>%SYSTEMDRIVE%\Inetpub\temp\IIS Temporary Compressed Files</em></strong></p></li></ul></ul><p align="justify"><strong><br></strong></p><ul><li><div align="justify"><strong>Temporary ASP.NET Files</strong></div></li></ul><p align="justify">When using ASP.NET, the Temporary ASP.NET Files folder is used by the .NET Framework to store the compiled output of the pages that are being served by the application. Depending on how the application is configured, and the usage of the application, this folder would potentially see a lot of write traffic, and it would lessen the overhead on the system if the write actions to this folder are not scanned in real-time by the anti-virus solution.<ul><ul><li><strong><em>Default folder for x86 compiled ASP.Net Code : %WINDIR%\Microsoft.NET\Framework\{version}\Temporary ASP.NET Files</em></strong></li><li><strong><em>Default folder for x64 compiled ASP.Net Code : %WINDIR%\Microsoft.NET\Framework64\{version}\Temporary ASP.NET Files</em></strong></li></ul></ul><p><br></p><ul><li><div align="justify"><b>Temporary ASP Files</b></div></li></ul><p align="justify">When using classic ASP, the ASP Compiled Templates folder is used to store the compiled output of the pages that are being served by the application. Depending on how the application is configured, and the usage of the application, this folder would potentially see a lot of write traffic, and it would lessen the overhead on the system if the write actions to this folder are not scanned in real-time by the anti-virus solution.<ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\temp\ASP Compiled Templates</em></strong></li></ul></ul><p><br><ul><li><strong>IIS binaries Installation Folder</strong></li></ul><strong></strong><p>All IIS binaries are located in two folders<br></p><ul><ul><li><em><strong>64-bit binaries : %WINDIR%\System32\Inetsrv<br></strong></em></li><li><em><strong>32-bit binaries : %WINDIR%\SysWOW64\Inetsrv</strong></em></li></ul></ul><p><strong><br></strong></p><ul><li><strong>IIS Configuration Folder</strong></li></ul><strong></strong><p align="justify">Internet Information Services (IIS) 7 and later use an XML-based configuration system for storing IIS settings which replaces the metabase that was used in IIS 6.0 and earlier. This new configuration system was introduced with ASP.NET and is based on a hierarchical system of management system that uses *.config files. The configuration files for IIS 7 and later are located in your %<em>WinDir</em>%\System32\Inetsrv\Config folder.<br></p><strong><em></em></strong><ul><ul><li><strong><em>%WINDIR%\System32\Inetsrv\Config</em></strong></li></ul></ul><p><br></p><ul><li><strong>Schema for the IIS Configuration</strong></li></ul><p>The IIS settings schema provides the basis for IIS 7.0 configuration. Most of the metabase properties you used in previous versions of IIS have been converted into elements or attributes in the schema. </p><ul><ul><li><strong><em>%WINDIR%\System32\Inetsrv\Config\Schema</em></strong></li></ul></ul><p><br></p><ul><li><strong>Default Content Location</strong></li></ul><p align="justify">By default the web content is stored in the listed folder (it is a best practices to use a dedicated disk/partition/LUN to host the web content)<br></p><em></em><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\WWWRoot</em></strong></li></ul></ul><p><br></p><ul><li><strong>Default History Location<br></strong></li></ul><p align="justify">This folder keeps a running history of changes to your configuration files. This history is especially useful for recovering from mistakes made when manually editing your configuration files.</p><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\History</em></strong></li></ul></ul><p><br></p><ul><li><strong>Default Backup Location</strong></li></ul><p align="justify">In IIS 7+, you can create and manage configuration backups by using the Appcmd.exe tool. By default, the configuration backups that you create by using the Appcmd.exe tool are located in subfolders in the %SystemDrive%\Inetpub\History directory.<br></p><ul><ul><li><strong><em>%WINDIR%\System32\Inetsrv\backup</em></strong></li></ul></ul><p><br></p><ul><li><strong>Default Configuration Isolation Path</strong></li></ul><p align="justify">AppPool isolation is a new feature in IIS7. A dedicated AppPool configuration file gets automatically created before a new Application Pool is started. The default location of these files is<br></p><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\temp\appPools</em></strong></li></ul></ul><p><br></p><ul><li><strong>Default Folder for Error pages</strong></li></ul><p align="justify">IIS7+ stores Custom Error Pages in <br></p><ul><ul><li><strong><em>%SYSTEMDRIVE%\Inetpub\custerr</em></strong><br>
</li></ul></ul><p><strong><br></strong><p><strong>Recommended Reading</strong> <p><a href="https://support.microsoft.com/kb/822158">Virus scanning recommendations for Enterprise computers that are running currently supported versions of Windows</a><p><a href="https://support.microsoft.com/en-us/help/817442/a-0-byte-file-may-be-returned-when-compression-is-enabled-on-a-server">A 0-byte file may be returned when compression is enabled on a server that is running IIS</a><p><a href="https://support.microsoft.com/en-us/help/821749/antivirus-software-may-cause-iis-to-stop-unexpectedly">Antivirus software may cause IIS to stop unexpectedly</a><p><br><p>Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>PowerShell : Array vs. ArrayList Performance.</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/powershell-array-vs-arraylist-performance</link>
      <pubDate>Mon, 11 Dec 2017 16:49:00 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=2136</guid>
      <description><![CDATA[English version
En février 2017 je twittais cet article : PowerShell – Array vs. ArrayList...]]></description>
      <content:encoded><![CDATA[<p><a href="#en-US">English version</a></p>
<p>En février 2017 je <a href="https://twitter.com/lavanack/status/832245707218231297" target="_blank" rel="noopener">twittais</a> cet <a href="https://stealthfield.wordpress.com/2015/08/21/powershell-array-vs-arraylist-performance/" target="_blank" rel="noopener">article</a> : <a href="https://stealthfield.wordpress.com/2015/08/21/powershell-array-vs-arraylist-performance/" target="_blank" rel="noopener">PowerShell – Array vs. ArrayList Performance</a> (dont je ne suis pas l’auteur). Cet article établissait une comparaison sur la performance (en termes de temps d’exécution) lors de l’ajout de 100 000 éléments dans un tableau PowerShell en comparaison avec la même opération dans une ArrayList (object .Net : System.Collections.ArrayList). Le résultat étant largement en faveur de la ArrayList : En effet les tableaux sont des objets de taille fixe et le fait de rajouter un élement dans un tableau équivaut à recréer un nouveau tableau de taille n+1 et de recopier le contenu existant dans cette nouvelle structure (Autant dire que c’est une opération coûteuse).</p>
<p>Je ne suis donc demandé à quel point la performance décroit (d’un point de vue des tableaux PowerShell) en fonction du nombre des éléments à ajouter. J’ai donc créé un petit script PowerShell qui ajoute jusquà 100 000 élements dans un tableau (en partant de 0 et par pallier de 100). De manière à ne pas perturber le script je l’ai lancé sur une VM <a href="https://portal.azure.com" target="_blank" rel="noopener">Azure</a> vierge (Standard A3 : 4 Cœurs, mémoire 7 Go).</p>
<p>Je vous laisse juge des résultats ci-dessous (Le fichier Excel des résultats est également disponible <a href="https://msdnshared.blob.core.windows.net/media/2017/11/ArrayVsArrayList.xlsx" target="_blank" rel="noopener">ici</a>).</p>
<p align="center"><strong></strong></p>
<h4 align="center"><strong>Comparaison des temps d’exécution</strong></h4>
<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/image181.png"><img width="804" height="404" title="image" class="aligncenter" style="border-width: 0px;padding-top: 0px;padding-right: 0px;padding-left: 0px;margin-right: auto;margin-left: auto;float: none" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/12/image_thumb172.png" border="0"></a></p>
<p><br></p>
<p>La courbe orange (Tableau PowerShell) inque clairement que plus on ajoute des éléments dans un tableau plus le temps augmente (de manière exponentielle – On atteint 24 minutes pour 100 000 élements).</p>
<p>Notez au passage la courbe bleue au niveau des abscisses (X = Nombre d’élements; Y= Temps exprimé en ticks soit 0.0001 ms) qui correspond au temps d’un point de vue ArrayList</p>
<p><br></p>
<h4 align="center"><span style="font-weight: bold">Zoom : Temps d’exécution côté ArrayList</span></h4>
<p align="center"><a href="https://msdnshared.blob.core.windows.net/media/2017/12/image182.png"><img width="804" height="398" title="image" style="border-width: 0px;margin: 0px;padding-top: 0px;padding-right: 0px;padding-left: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/12/image_thumb173.png" border="0"></a></p>
<h4 align="center"><span style="font-weight: bold"></span></h4>
<p align="left">Si on zoome sur la courbe bleue (ArrayList) on constate que l’évolution est linéaire (ce que ne laisse pas deviner la première courbe). On atteint moins de 2 secondes (!) pour 100 000 élements.</p>
<h4 align="center"><span style="font-weight: bold">Ecart</span></h4>
<p align="center"><a href="https://msdnshared.blob.core.windows.net/media/2017/12/image183.png"><img width="804" height="397" title="image" style="border-width: 0px;margin: 0px;padding-top: 0px;padding-right: 0px;padding-left: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/12/image_thumb174.png" border="0"></a></p>
<p align="center">
<p>L’écart Array vs. ArrayList lui aussi grandit en fonction du nombre d’élements. On constate donc que plus le nombre d’élements à ajouter et grand et plus les tabelaux sont a proscrire (on pouvait déjà tirer cette conclusion du premier graphique).</p>
<p>En conclusion : Bannissez l’utilisation des tableaux en PowerShell pour des structures de grandes tailles.</p>
<p><hr>
<div id="en-US"><a href="#fr-FR">Version française</a></div><div><br></div>
<div></div>
<p>In February 2017 I <a href="https://twitter.com/lavanack/status/832245707218231297" target="_blank" rel="noopener">twitted</a> this <a href="https://stealthfield.wordpress.com/2015/08/21/powershell-array-vs-arraylist-performance/" target="_blank" rel="noopener">article</a> : <a href="https://stealthfield.wordpress.com/2015/08/21/powershell-array-vs-arraylist-performance/" target="_blank" rel="noopener">PowerShell – Array vs. ArrayList Performance</a> (I am not the author). This article compares performance (in terms of execution time) when adding 100,000 items into a PowerShell array as compared to the same operation in an ArrayList (object .Net: System.Collections.ArrayList) . The result is largely in favor of the ArrayList: Indeed arrays are objects of fixed size and the fact of adding an element in a table is equivalent to recreate a new table with the size n + 1 and copy the existing content in this new structure (which means that it is an expensive operation).</p>
<p>So I'm wondering how much the performance decreases (from a PowerShell tables perspective) depending on the number of elements to add. So I created a little PowerShell script that adds up to 100,000 elements in a table (from 0 to 100). So as not to disturb the script I launched it on a blank Azure VM (Standard A3: 4 cores, 7 GB memory)</p>
<p>I leave you judge of the results below (The Excel file of the results is also available <a href="https://msdnshared.blob.core.windows.net/media/2017/11/ArrayVsArrayList.xlsx" target="_blank" rel="noopener">here</a>).</p>
<p align="center"><strong></strong></p>
<h4 align="center"><font style="font-weight: bold">Comparison of execution times</font></h4>
<p><a href="https://msdnshared.blob.core.windows.net/media/2017/12/image181.png"><img width="804" height="404" title="image" class="aligncenter" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/12/image_thumb172.png" border="0"></a></p>
<p><br></p>
<p>The orange curve (PowerShell Table) clearly indicates that the more elements are added to a table the more time increases (exponentially - 24 minutes for 100,000 elements).</p>
<p>Note in passing the blue curve at the abscissa (X = number of elements, Y = time expressed in ticks or 0.0001 ms) which corresponds to the time from an ArrayList point of view</p>
<p><br></p>
<h4 align="center"><span style="font-weight: bold">Zoom : Execution time from an ArrayList point of view</span></h4>
<p align="center"><a href="https://msdnshared.blob.core.windows.net/media/2017/12/image182.png"><img width="804" height="398" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/12/image_thumb173.png" border="0"></a></p>
<h4 align="center"></h4>
<p align="left">If we zoom in on the blue curve (ArrayList) we see that the evolution is linear (which is not to be guessed by the first curve). We reach less than 2 seconds (!) for 100,000 elements.</p>
<h4 align="center"><span style="font-weight: bold">Gap</span></h4>
<p align="center"><a href="https://msdnshared.blob.core.windows.net/media/2017/12/image183.png"><img width="804" height="397" title="image" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/12/image_thumb174.png" border="0"></a></p>
<p align="center">
<p>The difference Array vs. ArrayList also grows according to the number of elements. So we see that the more elements to add and larger and the more tables are to be avoided (we could already draw this conclusion from the first graph).<br>
In conclusion: Ban the use of tables in PowerShell for large structures.</p>
<p><br></p>
<p style="text-align: justify">
<p style="text-align: justify">Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>Perfmon Log Translator (PLT)</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/plt</link>
      <pubDate>Wed, 17 May 2017 15:59:00 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1966</guid>
      <description><![CDATA[Go to English version L’utilisation de PAL a déjà été couverte dans un article d’Arnaud Lheureux qui...]]></description>
      <content:encoded><![CDATA[<p><a href="#en-us" name="fr-fr">Go to English version</a></p> <p align="justify">L’utilisation de PAL a déjà été couverte dans un <a title="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/" href="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/">article</a> d’<a href="https://blogs.technet.microsoft.com/arnaud/">Arnaud Lheureux</a> qui est disponible <a title="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/" href="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/">ici</a> (L’article est en français. Pour toute autre langue je vous invite à consulter <a title="https://pal.codeplex.com/" href="https://pal.codeplex.com/">Performance Analysis of Logs (PAL) Tool</a>)</p> <p align="justify">Le principal problème dans l’utilisation de <a title="https://pal.codeplex.com/" href="https://pal.codeplex.com/">PAL</a> vient de systèmes d’exploitation non installés en anglais (en-us). En effet l’outil se base sur les noms anglais des compteurs. Ce qui rend l’analyse de données (*.blg) issus d’un serveur non anglophone impossible. <a title="https://pal.codeplex.com/releases/view/21261" href="https://pal.codeplex.com/releases/view/21261">Perfmon Log Translator (PLT)</a> est là pour pallier à ce problème. <a href="https://pal.codeplex.com/releases/view/21261">I</a>l assure la traduction de compteurs en anglais (grâce à une correspondance des noms de compteurs inclus dans des fichiers XML - un fichier par langue). Malheureusement beaucoup de compteurs sont absents des fichiers XML fournis. J’ai donc décidé de pallier, en partie, à ce problème. Quand je dis en partie, je me suis limité à l’OS, IIS et ASP.Net. Mais comme vous le verrez par la suite, il est très simple d’étendre la traduction à d’autres rôles ou fonctionnalités du système d’exploitation et à d’autres langues. <strong>Si vous souhaitez juste récupérer mes fichiers XML de traduction c’est </strong><a href="https://msdnshared.blob.core.windows.net/media/2017/05/PLT.zip"><strong>ici</strong></a><strong> que cela se passe (Pour les cultures suivantes : et-EE, hr-HR, lt-LT, sv-SE, tr-TR, en-GB, lv-LV, sr-Latn-RS, es-MX, fr-CA, ro-RO, sk-SK, sl-SI, pt-PT, es-ES, fi-FI, fr-FR, cs-CZ, da-DK, de-DE, hu-HU, pl-PL, pt-BR, it-IT, nb-NO, nl-NL)</strong>. Dans tous les cas je vous invite quand même à lire la suite de l’article. </p> <p align="justify">Ces fichiers ont été générés grâce au <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> suivant et dont le code est également affiché en bas de page. Le principe est simple. Je liste les compteurs (et leur ID) sur un OS installé en anglais (avec IIS et ASP.Net) que je mémorise dans un fichier CSV(*). Ensuite grâce au pack de langues (notamment dispo sur <a href="https://my.visualstudio.com">https://my.visualstudio.com</a> et <a title="https://www.microsoft.com/Licensing/servicecenter" href="https://www.microsoft.com/Licensing/servicecenter">https://www.microsoft.com/Licensing/servicecenter</a>) je bascule en français et je recommence. L’ID ne changeant pas, je fais la correspondance via cet ID. Attention toutefois, un même compteur n’a pas le même ID en fonction de la version de Windows Server (je ne connais pas la raison). Il est donc nécessaire d’exécuter le <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> sur tous les OS qui vous intéressent. Si vous souhaitez étendre à d’autres rôles/fonctionnalités, vous les installez sur votre OS (via des machines virtuelles ou <a href="https://azure.microsoft.com">Azure</a>) et faites tourner le <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> dans chaque langue qui vous intéresse. A la fin vous obtiendrez un fichier XML par langue avec un suffixe correspondant à la version de l’OS (par exemple fr-FR_PFL_10.0.xml). Le suffixe sert à identifier l’OS source (10.0 étant la version du noyau de Windows Server 2016) et à ne pas écraser un fichier d’un autre OS. Ensuite vous copiez votre fichier dans le répertoire de <a title="https://pal.codeplex.com/releases/view/21261" href="https://pal.codeplex.com/releases/view/21261">PLT</a> en supprimant le suffixe. En effet dans PAL le nom est simplement fr-FR_PFL.xml (pour la correspondance Français ==&gt; Anglais). </p> <p align="justify">(*)Le fichier CSV joue un rôle important car :</p> <ul> <li> <div align="justify">S’il n’existe pas il sera créé à la première utilisation (sur un OS anglais normalement , mais pas forcément). Autrement les compteurs qu’il contient (quelquesoit la langue) seront importés en mémoire</div> <li> <div align="justify">Il est propre à chaque OS (il utilise le même suffixe que les fichiers XML pour identifier l’OS source)</div> <li> <div align="justify">Il est unique (pour un même OS) quelquesoit la ou les langues utilisées </div> <li> <div align="justify">il est donc de ce fait incrémental (vous pouvez rajouter d’autres packs de langues pour un OS) et refaire tourner le <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> directement dans cette nouvelle langue (il faut toutefois qu’il ait tourné au moins une fois sur un OS anglais)</div></li></ul> <p><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/012717_1333_Fusionnerde1.png">  <p><a href="#fr-FR" name="en-us">Aller à la version française</a></p> <p>The PAL usage has already been covered in an <a title="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/" href="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/">article</a> of <a href="https://blogs.technet.microsoft.com/arnaud/">Arnaud Lheureux</a> which is available <a title="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/" href="https://blogs.technet.microsoft.com/arnaud/2015/07/22/analyse-de-performances-de-serveurs-windows/">here</a> (The article is written in the french language. For any other language, I invite you to read&nbsp; <a title="https://pal.codeplex.com/" href="https://pal.codeplex.com/">Performance Analysis of Logs (PAL) Tool</a>)</p> <p align="justify">The main problem with the <a title="https://pal.codeplex.com/" href="https://pal.codeplex.com/">PAL</a> usage comes from non-english (en-us) operating systems. Indeed, this tool uses only english performance counters. That makes the analysis of data (* .blg) from a non-English server impossible. <a title="https://pal.codeplex.com/releases/view/21261" href="https://pal.codeplex.com/releases/view/21261">Perfmon Log Translator (PLT)</a> is there to overcome this problem. It ensures the translation english counters (via the matching of the counter names of included in XML files - one file per language). Unfortunately many counters are missing from the supplied XML files. So I decided to partially address this problem. When I say in partially, I focus only to the OS, IIS and ASP.Net. But as you will see later, it is very simple to extend the translation to other roles or functionalities of the operating system and to other languages. <strong>If you just want to retrieve my translation XML files this is <a href="https://msdnshared.blob.core.windows.net/media/2017/05/PLT.zip">here</a> (For the following cultures : et-EE, hr-HR, lt-LT, sv-SE, tr-TR, en-GB, lv-LV, sr-Latn-RS, es-MX, fr-CA, ro-RO, sk-SK, sl-SI, pt-PT, es-ES, fi-FI, fr-FR, cs-CZ, da-DK, de-DE, hu-HU, pl-PL, pt-BR, it-IT, nb-NO, nl-NL)</strong>. Nevertheless, I invite you to read the rest of the article.</p> <p align="justify">These files were generated by the following <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> and whose code is also displayed at the bottom of the page. The principle is pretty simple. I list the counters (and their ID) on an english OS (with IIS and ASP.Net) that I store in a CSV file(*). Then I install the relevant language pack (especially available on <a href="https://my.visualstudio.com">https://my.visualstudio.com</a> and <a href="https://www.microsoft.com/Licensing/servicecenter)">https://www.microsoft.com/Licensing/servicecenter)</a> I switch to French and I start again. The ID does not change, I do the correspondence via this ID. Be careful though, the same counter does not have the same ID depending on the version of Windows Server (I do not know the reason). It is therefore necessary to run the <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> on all the OSes you are interested in. If you want to extend to other roles / features, install them on your OS (via virtual machines or <a href="https://azure.microsoft.com">Azure</a>) and run the <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> in each language you are interested in. At the end you will get an XML file per language with a suffix corresponding to the version of the OS (for example fr-FR_PFL_10.0.xml). The suffix is ​​used to identify the source OS (10.0 being the kernel version of Windows Server 2016) and not to overwrite a file from another OS. Then you copy your file to the <a title="https://pal.codeplex.com/releases/view/21261" href="https://pal.codeplex.com/releases/view/21261">PLT</a> directory by deleting the suffix. Indeed in PAL the name is simply en-FR_PFL.xml (for the French correspondence ==&gt; English).</p> <p align="justify">(*)The CSV file plays an important role because:</p> <ul> <li>If it does not exist it will be created at the first use (on an English OS normally, but not necessarily). Otherwise the counters it contains (regardless language) will be imported into memory  <li>It is unique for each OS (it uses the same suffix as the XML files to identify the source OS)  <li>It is unique (for the same OS) regardless of the language(s) used  <li>It is therefore incremental (you can add other language packs for an OS) and redo the <a href="https://msdnshared.blob.core.windows.net/media/2017/05/Get-PLTPerformanceCounters.ps1_.txt">script</a> directly with this new language (it must however have run at least once on an English OS)  <div align="justify">&nbsp;</div></li></ul> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:85314b0b-651e-48e5-a61c-64616543be62" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 762px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000">requires -version 3</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Compare</span><span style="color: #000000">-</span><span style="color: #000000">PLTFile
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">The directory where are stored the generated XML File</span><span style="color: #008000">
</span><span style="color: #000000">        [Alias('Directory', 'Path')]
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">
    )

    </span><span style="color: #800080">$PLTFiles</span><span style="color: #000000">=</span><span style="color: #000000">Get</span><span style="color: #000000">-</span><span style="color: #000000">ChildItem </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> </span><span style="color: #000000">*</span><span style="color: #000000">_PFL.xml </span><span style="color: #008080">-File</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Recurse </span><span style="color: #000000">|</span><span style="color: #000000"> Group</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Name </span><span style="color: #000000">-</span><span style="color: #000000">AsHashTable </span><span style="color: #000000">-</span><span style="color: #000000">AsString

    </span><span style="color: #800080">$Differences</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName 'System.Collections.ArrayList'
    </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$XMLFile</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$PLTFiles</span><span style="color: #000000">.Keys)
    {
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Processing $XMLFile ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        </span><span style="color: #800080">$HT</span><span style="color: #000000">=@</span><span style="color: #000000">{}
        </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentXMLFile</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$PLTFiles</span><span style="color: #000000">[</span><span style="color: #800080">$XMLFile</span><span style="color: #000000">])
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Processing $($CurrentXMLFile.FullName) ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$OS</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentXMLFile</span><span style="color: #000000">.Directory.Name)
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Operation System : $OS</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$CurrentXMLFile : $($CurrentXMLFile.FullName)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            [xml] </span><span style="color: #800080">$XMLContent</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">Content </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentXMLFile</span><span style="color: #000000">.FullName)
            </span><span style="color: #800080">$LanguageNodes</span><span style="color: #000000">=</span><span style="color: #800080">$XMLContent</span><span style="color: #000000">.SelectNodes(</span><span style="color: #800000">&quot;</span><span style="color: #800000">/Counters/Counter</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
            </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$LanguageNodes</span><span style="color: #000000">)
            {
                </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$HT</span><span style="color: #000000">.ContainsKey(</span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.en))
                {
                    </span><span style="color: #800080">$Data</span><span style="color: #000000">=</span><span style="color: #800080">$HT</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.en]
                    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$Data</span><span style="color: #000000">.Value </span><span style="color: #008080">-ne</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.org)
                    {
                        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Difference found for [$($CurrentLanguageNode.en)] in $XMLFile ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$($CurrentLanguageNode.en)]: [$OS]$($CurrentLanguageNode.org) vs. [$($Data.OS)]$($Data.Value)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                        </span><span style="color: #800080">$CurrentDifference</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName PSObject </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">@</span><span style="color: #000000">{ EN </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.en; Locale </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$XMLFile</span><span style="color: #000000"> </span><span style="color: #008080">-replace</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">_PFL.xml</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;&quot;</span><span style="color: #000000">); OS1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$OS</span><span style="color: #000000">; Value1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.org; OS2 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Data</span><span style="color: #000000">.OS; Value2 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Data</span><span style="color: #000000">.Value}
                        </span><span style="color: #800080">$null</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Differences</span><span style="color: #000000">.Add(</span><span style="color: #800080">$CurrentDifference</span><span style="color: #000000">)
                    }
                }
                </span><span style="color: #0000FF">else</span><span style="color: #000000">
                {
                    </span><span style="color: #800080">$Data</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName PSObject </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">@</span><span style="color: #000000">{ OS </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$OS</span><span style="color: #000000">; Value </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.org }
                    </span><span style="color: #800080">$HT</span><span style="color: #000000">.Add(</span><span style="color: #800080">$CurrentLanguageNode</span><span style="color: #000000">.en, </span><span style="color: #800080">$Data</span><span style="color: #000000">)
                }
            }
        }   
    }
    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$Differences</span><span style="color: #000000">
}

</span><span style="color: #0000FF">function</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">PLTLangFile
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">The directory where are stored the generated XML File</span><span style="color: #008000">
</span><span style="color: #000000">        [Alias('Directory', 'Path')]
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">
    )
    </span><span style="color: #800080">$PLTFiles</span><span style="color: #000000">=</span><span style="color: #000000">Get</span><span style="color: #000000">-</span><span style="color: #000000">ChildItem </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> </span><span style="color: #000000">*</span><span style="color: #000000">_PFL.xml </span><span style="color: #008080">-File</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Recurse </span><span style="color: #000000">|</span><span style="color: #000000"> Group</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Directory </span><span style="color: #000000">-</span><span style="color: #000000">AsHashTable

    </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$Directory</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$PLTFiles</span><span style="color: #000000">.Keys)
    {
        </span><span style="color: #800080">$XMLFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Join</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$Directory</span><span style="color: #000000">.FullName) </span><span style="color: #000000">-</span><span style="color: #000000">ChildPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">PLT-lang.xml</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Generating $XMLFile ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.XMl.XmlTextWriter </span><span style="color: #000000">-</span><span style="color: #000000">ArgumentList (</span><span style="color: #800080">$XMLFile</span><span style="color: #000000">, [System.Text.Encoding]</span><span style="color: #000000">::</span><span style="color: #000000">UTF8)
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Formatting </span><span style="color: #000000">=</span><span style="color: #000000"> [ System.Xml.Formatting]</span><span style="color: #000000">::</span><span style="color: #000000">Indented
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Indentation </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000">
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.IndentChar </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">`t</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteStartDocument()
        </span><span style="color: #008000">#</span><span style="color: #008000">Adding a comment to have the date of the generation</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteComment(</span><span style="color: #800000">&quot;</span><span style="color: #800000">Generated (UTC): $(Get-Date -Format 'U')</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteStartElement('languages')
        </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentPLTFile</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$PLTFiles</span><span style="color: #000000">[</span><span style="color: #800080">$Directory</span><span style="color: #000000">])
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Adding locale : $($CurrentCulture.DisplayName)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$CurrentCulture</span><span style="color: #000000">=</span><span style="color: #000000">[cultureinfo]</span><span style="color: #000000">::</span><span style="color: #000000">GetCultureInfo(</span><span style="color: #800080">$CurrentPLTFile</span><span style="color: #000000">.BaseName  </span><span style="color: #008080">-replace</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">_PFL</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;&quot;</span><span style="color: #000000">)
            </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteStartElement('language')
            </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteElementString('displayName',</span><span style="color: #800080">$CurrentCulture</span><span style="color: #000000">.DisplayName)
            </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteElementString('fileName', </span><span style="color: #800080">$CurrentCulture</span><span style="color: #000000">.Name</span><span style="color: #000000">+</span><span style="color: #800000">&quot;</span><span style="color: #800000">_PFL.xml</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
            </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteEndElement()
        }
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteEndElement()
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteEndDocument()
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Flush()
        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Close()
    }
}


</span><span style="color: #0000FF">function</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">ProcessedLanguage
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">The directory where are stored the generated XML File</span><span style="color: #008000">
</span><span style="color: #000000">        [Alias('Directory', 'Path')]
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">
    )
    </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (Get</span><span style="color: #000000">-</span><span style="color: #000000">ChildItem </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">*-*.xml</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #008080">-File</span><span style="color: #000000">).BaseName </span><span style="color: #008080">-replace</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">_.*$</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;&quot;</span><span style="color: #000000">
    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000">
}

</span><span style="color: #008000">#</span><span style="color: #008000">Getting Performance counter data from the local registry</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">The directory where are stored the generated XML File</span><span style="color: #008000">
</span><span style="color: #000000">        [Alias('Directory', 'Path')]
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">,
        </span><span style="color: #008000">#</span><span style="color: #008000">Switch to force the performance data collection event if this language has already been processed</span><span style="color: #008000">
</span><span style="color: #000000">        [</span><span style="color: #0000FF">Switch</span><span style="color: #000000">]</span><span style="color: #800080">$Force</span><span style="color: #000000">
    )

    </span><span style="color: #008000">#</span><span style="color: #008000">Getting the current UI culture</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> ([cultureinfo]</span><span style="color: #000000">::</span><span style="color: #000000">CurrentUICulture).Name
    </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">ProcessedLanguage </span><span style="color: #000000">-</span><span style="color: #000000">Directory </span><span style="color: #800080">$FullName</span><span style="color: #000000">
    </span><span style="color: #0000FF">if</span><span style="color: #000000"> ((</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">notin </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000">) </span><span style="color: #008080">-or</span><span style="color: #000000"> (</span><span style="color: #800080">$Force</span><span style="color: #000000">))
    {

        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">notin </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000">)
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[New] $CurrentUICulture will be processed</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> (</span><span style="color: #800080">$Force</span><span style="color: #000000">)
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[Force] $CurrentUICulture will be processed</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #008000">#</span><span style="color: #008000">Hashtable for storing the performance counter data. The Index is the key</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">{}
        </span><span style="color: #008000">#</span><span style="color: #008000">Getting all performance counters</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$RegistryPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (Get</span><span style="color: #000000">-</span><span style="color: #000000">ItemProperty </span><span style="color: #000000">-</span><span style="color: #000000">Path 'Registry</span><span style="color: #000000">::</span><span style="color: #000000">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage' </span><span style="color: #000000">-</span><span style="color: #000000">Name Counter).Counter
        </span><span style="color: #800080">$PerformanceCountersNumber</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$RegistryPerformanceCounters</span><span style="color: #000000">.Count

        </span><span style="color: #0000FF">for</span><span style="color: #000000">(</span><span style="color: #800080">$i</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">2</span><span style="color: #000000">; </span><span style="color: #800080">$i</span><span style="color: #000000"> </span><span style="color: #008080">-lt</span><span style="color: #000000"> </span><span style="color: #800080">$PerformanceCountersNumber</span><span style="color: #000000">; </span><span style="color: #800080">$i</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> </span><span style="color: #000000">2</span><span style="color: #000000">)    
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">Getting the performance counter index</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$CurrentIndex</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$RegistryPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$i</span><span style="color: #000000">]
            </span><span style="color: #008000">#</span><span style="color: #008000">Getting the performance counter name</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$CurrentPerformanceCounterName</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$RegistryPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$i</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">]
            </span><span style="color: #800080">$PercentComplete</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (</span><span style="color: #800080">$i</span><span style="color: #000000">/</span><span style="color: #800080">$PerformanceCountersNumber</span><span style="color: #000000">)
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Progress </span><span style="color: #000000">-</span><span style="color: #000000">Activity </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$i/$PerformanceCountersNumber] Retrieving $CurrentUICulture - $('{0:D4}' -f [int]$CurrentIndex) : $CurrentPerformanceCounterName</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Status ('Processing {</span><span style="color: #000000">0</span><span style="color: #000000">:p0}' </span><span style="color: #008080">-f</span><span style="color: #000000"> </span><span style="color: #800080">$PercentComplete</span><span style="color: #000000">) </span><span style="color: #000000">-</span><span style="color: #000000">PercentComplete (</span><span style="color: #800080">$PercentComplete</span><span style="color: #000000">*</span><span style="color: #000000">100</span><span style="color: #000000">)
            </span><span style="color: #008000">#</span><span style="color: #008000">Only counter with a valid name</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #0000FF">if</span><span style="color: #000000"> ((</span><span style="color: #800080">$CurrentPerformanceCounterName</span><span style="color: #000000">) </span><span style="color: #008080">-and</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentPerformanceCounterName</span><span style="color: #000000">.Length </span><span style="color: #008080">-gt</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">))
            {
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Getting Performance Counter with Index $('{0:D4}' -f [int]$CurrentIndex) : [$CurrentPerformanceCounterName]</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #800080">$CounterObject</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName PSObject </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">@</span><span style="color: #000000">{
                    </span><span style="color: #008000">#</span><span style="color: #008000">the index of the counter</span><span style="color: #008000">
</span><span style="color: #000000">                    Index </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentIndex</span><span style="color: #000000">
                    </span><span style="color: #008000">#</span><span style="color: #008000">The name of the counter in the current locale, culture. Ie : en-US, fr-FR ...</span><span style="color: #008000">
</span><span style="color: #000000">                    </span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentPerformanceCounterName</span><span style="color: #000000">
                }
                </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.Add(</span><span style="color: #800080">$CurrentIndex</span><span style="color: #000000">,</span><span style="color: #800080">$CounterObject</span><span style="color: #000000">)
            }
        }
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Progress </span><span style="color: #000000">-</span><span style="color: #000000">Completed </span><span style="color: #000000">-</span><span style="color: #000000">Activity 'Performance Counters Collection Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object 'Performance Counters Collection Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
    }
    </span><span style="color: #0000FF">else</span><span style="color: #000000">
    {
        </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[Skip] $CurrentUICulture has already been processed</span><span style="color: #800000">&quot;</span><span style="color: #000000">
    }
    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">
}

</span><span style="color: #008000">#</span><span style="color: #008000">Importing performance counter data from a specified CSV file</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Import</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)][ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Leaf
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">CSV file full name</span><span style="color: #008000">
</span><span style="color: #000000">        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">
    )
    </span><span style="color: #008000">#</span><span style="color: #008000">Hashtable for storing the performance counter data. The Index is the key</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">{}
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Importing the Performance Counters from $FullName</span><span style="color: #800000">&quot;</span><span style="color: #000000">
    </span><span style="color: #008000">#</span><span style="color: #008000">Importing performance counter data with a valid Index</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Import</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Encoding 'UTF8'  </span><span style="color: #000000">|</span><span style="color: #000000"> Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript {
        </span><span style="color: #800080">$_</span><span style="color: #000000">.Index
    }
    </span><span style="color: #800080">$Counter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">
    </span><span style="color: #008000">#</span><span style="color: #008000">Going through the imported performance counter data</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentImportedPerformanceCounter</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000">)
    {
        </span><span style="color: #800080">$Counter</span><span style="color: #000000">++</span><span style="color: #000000">
        </span><span style="color: #800080">$PercentComplete</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (</span><span style="color: #800080">$Counter</span><span style="color: #000000">/</span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000">.Count) 
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Progress </span><span style="color: #000000">-</span><span style="color: #000000">Activity </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$Counter/$($ImportedPerformanceCounters.Count)] Importing Performance Counter with Index $('{0:D4}' -f [int]$CurrentImportedPerformanceCounter.Index)</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Status ('Processing {</span><span style="color: #000000">0</span><span style="color: #000000">:p0}' </span><span style="color: #008080">-f</span><span style="color: #000000"> </span><span style="color: #800080">$PercentComplete</span><span style="color: #000000">) </span><span style="color: #000000">-</span><span style="color: #000000">PercentComplete (</span><span style="color: #800080">$PercentComplete</span><span style="color: #000000">*</span><span style="color: #000000">100</span><span style="color: #000000">)
        </span><span style="color: #008000">#</span><span style="color: #008000">If the counter with the current index has not been alreay imported</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #000000">!</span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.ContainsKey(</span><span style="color: #800080">$CurrentImportedPerformanceCounter</span><span style="color: #000000">.Index))
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">We add it to the Hashtable</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.Add(</span><span style="color: #800080">$CurrentImportedPerformanceCounter</span><span style="color: #000000">.Index, </span><span style="color: #800080">$CurrentImportedPerformanceCounter</span><span style="color: #000000">)
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Importing Performance Counter with Index $('{0:D4}' -f [int]$($CurrentImportedPerformanceCounter.Index)) : $CurrentImportedPerformanceCounter</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">else we raise a non-terminating error</span><span style="color: #008000">
</span><span style="color: #000000">            Write</span><span style="color: #000000">-</span><span style="color: #000000">Error </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentImportedPerformanceCounter.Index) was already imported</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
    }
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Progress </span><span style="color: #000000">-</span><span style="color: #000000">Completed </span><span style="color: #000000">-</span><span style="color: #000000">Activity 'Performance Counters Import Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object 'Performance Counters Import Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">
}

</span><span style="color: #008000">#</span><span style="color: #008000">Exporting performance counter data into a specified CSV file</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Export</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateNotNullOrEmpty()][ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path (Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent) </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">CSV file full name</span><span style="color: #008000">
</span><span style="color: #000000">        [Alias('FilePath')]
        [String]</span><span style="color: #800080">$Path</span><span style="color: #000000">,
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateNotNullOrEmpty()]
        [hashtable]</span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">
    )
    </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.Values </span><span style="color: #000000">|</span><span style="color: #000000">
    Sort</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Index </span><span style="color: #000000">|</span><span style="color: #000000">
    Select</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Index, </span><span style="color: #000000">*</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ErrorAction Ignore </span><span style="color: #000000">|</span><span style="color: #000000">
    Export</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path  </span><span style="color: #800080">$Path</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Force </span><span style="color: #000000">-</span><span style="color: #000000">NoTypeInformation </span><span style="color: #000000">-</span><span style="color: #000000">Encoding 'UTF8'
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">The Performance Counters are exported to $Path</span><span style="color: #800000">&quot;</span><span style="color: #000000">
}

</span><span style="color: #008000">#</span><span style="color: #008000">Merging the imported and the local performance counter </span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Merge</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        </span><span style="color: #008000">#</span><span style="color: #008000">The imported performance counter</span><span style="color: #008000">
</span><span style="color: #000000">        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateNotNullOrEmpty()]
        [hashtable]</span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000">,
        </span><span style="color: #008000">#</span><span style="color: #008000">The local performance counter</span><span style="color: #008000">
</span><span style="color: #000000">        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateNotNullOrEmpty()]
        [Alias('LocalPerformanceCounters')]
        [hashtable]</span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000">,
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateNotNullOrEmpty()]
        </span><span style="color: #008000">#</span><span style="color: #008000">The current UI culture</span><span style="color: #008000">
</span><span style="color: #000000">        [String]</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">,
        </span><span style="color: #008000">#</span><span style="color: #008000">Switch to force the performance data if a counter with the same index already exists</span><span style="color: #008000">
</span><span style="color: #000000">        [</span><span style="color: #0000FF">Switch</span><span style="color: #000000">]</span><span style="color: #800080">$Force</span><span style="color: #000000">
    )
    </span><span style="color: #008000">#</span><span style="color: #008000">We work from the imported data</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000">
    </span><span style="color: #008000">#</span><span style="color: #008000">Going through the current localized performance counter</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000">.Values)
    {
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[Merge] Processing Performance Counter with Index $('{0:D4}' -f [int]$($CurrentCulturePerformanceCounterValue.Index)) : $CurrentCulturePerformanceCounterValue</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">If the index of the current localized counter already exists in the imported counter: we can match the counter in different locales</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index])
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">If the counter name for the current culture is unknow, we add it to the hastable (the index is the key)</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #008080">-not</span><span style="color: #000000"> (</span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index].PSObject.Properties[</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">]))
            {
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Updating the Performance Counter with Index $('{0:D4}' -f [int]$($CurrentCulturePerformanceCounterValue.Index)) with $CurrentUICulture=$($CurrentCulturePerformanceCounterValue.$CurrentUICulture)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index] </span><span style="color: #000000">|</span><span style="color: #000000"> Add</span><span style="color: #000000">-</span><span style="color: #000000">Member </span><span style="color: #000000">-</span><span style="color: #000000">MemberType NoteProperty </span><span style="color: #000000">-</span><span style="color: #000000">Name </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentUICulture</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Value </span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">
                </span><span style="color: #008000">#</span><span style="color: #008000"> $MergedPerformanceCounters[$CurrentCulturePerformanceCounterValue.Index].PSObject.Properties[$CurrentUICulture]=$CurrentCulturePerformanceCounterValue.$CurrentUICulture</span><span style="color: #008000">
</span><span style="color: #000000">            }
            </span><span style="color: #008000">#</span><span style="color: #008000">If the counter name for the current culture is empty or null, we upate it in the hastable (the index is the key)</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> ((</span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index].PSObject.Properties[</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">] </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">) </span><span style="color: #008080">-or</span><span style="color: #000000"> (</span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index].PSObject.Properties[</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">].Length </span><span style="color: #008080">-le</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">))
            {
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Updating $CurrentUICulture for the Performance Counter with Index $('{0:D4}' -f [int]$($CurrentCulturePerformanceCounterValue.Index)) because the previous value was null or empty</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #008000">#</span><span style="color: #008000">$ImportedPerformanceCounters[$CurrentCulturePerformanceCounterValue.Index].$CurrentUICulture=$CurrentCulturePerformanceCounterValue.$CurrentUICulture</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index].</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">
            }
            </span><span style="color: #008000">#</span><span style="color: #008000">else (valid counter name) we update only if -force is specified</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> (</span><span style="color: #800080">$Force</span><span style="color: #000000">)
            {
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Updating $CurrentUICulture for the Performance Counter with Index $('{0:D4}' -f [int]$($CurrentCulturePerformanceCounterValue.Index)) because -Force was explicit specified</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index].</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000">
            }
        }
        </span><span style="color: #008000">#</span><span style="color: #008000">else if it is a new counter</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Setting the Performance Counter with Index $('{0:D4}' -f [int]$($CurrentCulturePerformanceCounterValue.Index)) with $CurrentUICulture=$($CurrentCulturePerformanceCounterValue.$CurrentUICulture)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">[</span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">.Index] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentCulturePerformanceCounterValue</span><span style="color: #000000">
        }
    }
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object 'PLT Files Merge Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000">
}

</span><span style="color: #008000">#</span><span style="color: #008000">creting a PLT file for all merged data</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">PLTFile
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateNotNullOrEmpty()]
        [hashtable]</span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">,
        </span><span style="color: #008000">#</span><span style="color: #008000">Output directory : where to store the generated PLT file (XML format)</span><span style="color: #008000">
</span><span style="color: #000000">        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)][ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path (Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent) </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        [Alias('Path')]
        [String]</span><span style="color: #800080">$OutputDir</span><span style="color: #000000">,

        </span><span style="color: #008000">#</span><span style="color: #008000">Switch to force XML file generation event if the file already exists</span><span style="color: #008000">
</span><span style="color: #000000">        [</span><span style="color: #0000FF">Switch</span><span style="color: #000000">]</span><span style="color: #800080">$Force</span><span style="color: #000000">
    )
    </span><span style="color: #008000">#</span><span style="color: #008000">Getting the source OS version </span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$OSVersion</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> [Environment]</span><span style="color: #000000">::</span><span style="color: #000000">OSVersion.Version.Major.ToString()</span><span style="color: #000000">+</span><span style="color: #000000">'.'</span><span style="color: #000000">+</span><span style="color: #000000">[Environment]</span><span style="color: #000000">::</span><span style="color: #000000">OSVersion.Version.Minor.ToString()
    </span><span style="color: #008000">#</span><span style="color: #008000">Hashtable for XMLWriter where the locale is the key and the value if the XML content</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$XMLWriters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">{}
    </span><span style="color: #800080">$Languages</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (</span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.Values </span><span style="color: #000000">|</span><span style="color: #000000">
        Get</span><span style="color: #000000">-</span><span style="color: #000000">Member </span><span style="color: #000000">-</span><span style="color: #000000">MemberType NoteProperty </span><span style="color: #000000">|</span><span style="color: #000000">
        Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript {
            </span><span style="color: #000000">@</span><span style="color: #000000">('Index', 'en</span><span style="color: #000000">-</span><span style="color: #000000">us') </span><span style="color: #008080">-notcontains</span><span style="color: #000000"> </span><span style="color: #800080">$_</span><span style="color: #000000">.Name
    }).Name
    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #008080">-not</span><span style="color: #000000">(</span><span style="color: #800080">$Force</span><span style="color: #000000">))
    {
        </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">ProcessedLanguage </span><span style="color: #000000">-</span><span style="color: #000000">Directory </span><span style="color: #800080">$OutputDir</span><span style="color: #000000">
        </span><span style="color: #800080">$Languages</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Languages</span><span style="color: #000000">  </span><span style="color: #000000">|</span><span style="color: #000000"> Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript { </span><span style="color: #800080">$ProcessedLanguages</span><span style="color: #000000"> </span><span style="color: #008080">-notcontains</span><span style="color: #000000"> </span><span style="color: #800080">$_</span><span style="color: #000000"> }
    }
    </span><span style="color: #008000">#</span><span style="color: #008000">for each non en-us languages</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$Languages</span><span style="color: #000000">)
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">For each performance counter data </span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.Values </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object `
        </span><span style="color: #000000">-</span><span style="color: #0000FF">Begin</span><span style="color: #000000"> {
            </span><span style="color: #008000">#</span><span style="color: #008000">Before processing the first item in the collection we build an XMLWriter for the current language and store it in the Hashtable</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$Counter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">
            </span><span style="color: #800080">$Languages</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> { 
                </span><span style="color: #008000">#</span><span style="color: #008000">Adding a prefix to identify the source OS</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.XMl.XmlTextWriter </span><span style="color: #000000">-</span><span style="color: #000000">ArgumentList (</span><span style="color: #000000">$</span><span style="color: #000000">(Join</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$OutputDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ChildPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($_)_PFL_$($OSVersion).xml</span><span style="color: #800000">&quot;</span><span style="color: #000000">), [System.Text.Encoding]</span><span style="color: #000000">::</span><span style="color: #000000">UTF8)
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Formatting </span><span style="color: #000000">=</span><span style="color: #000000"> [ System.Xml.Formatting]</span><span style="color: #000000">::</span><span style="color: #000000">Indented
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Indentation </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000">
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.IndentChar </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">`t</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteStartDocument()
                </span><span style="color: #008000">#</span><span style="color: #008000">Adding a comment to have the date of the generation</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteComment(</span><span style="color: #800000">&quot;</span><span style="color: #800000">Generated (UTC): $(Get-Date -Format 'U')</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
                </span><span style="color: #008000">#</span><span style="color: #008000">Adding a comment to have the OS Version because a same performance counter index may vary with the OS</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteComment(</span><span style="color: #800000">&quot;</span><span style="color: #800000">OS Version : $((Get-WmiObject -Class win32_operatingsystem).caption)</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteStartElement('Counters')
                </span><span style="color: #800080">$XMLWriters</span><span style="color: #000000">.Add(</span><span style="color: #800080">$_</span><span style="color: #000000">, </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">)
            }
        } `
        </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> { 
            </span><span style="color: #008000">#</span><span style="color: #008000">For every performance data</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$Counter</span><span style="color: #000000">++</span><span style="color: #000000">
            </span><span style="color: #800080">$PercentComplete</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (</span><span style="color: #800080">$Counter</span><span style="color: #000000">/</span><span style="color: #800080">$PerformanceCounters</span><span style="color: #000000">.Count) 
            </span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$_</span><span style="color: #000000">
            </span><span style="color: #800080">$Languages</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> {
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Progress </span><span style="color: #000000">-</span><span style="color: #000000">Activity </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$Counter/$($PerformanceCounters.Count)] Generating PLT File for $_</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Status ('Processing {</span><span style="color: #000000">0</span><span style="color: #000000">:p0}' </span><span style="color: #008080">-f</span><span style="color: #000000"> </span><span style="color: #800080">$PercentComplete</span><span style="color: #000000">) </span><span style="color: #000000">-</span><span style="color: #000000">PercentComplete (</span><span style="color: #800080">$PercentComplete</span><span style="color: #000000">*</span><span style="color: #000000">100</span><span style="color: #000000">)
                </span><span style="color: #008000">#</span><span style="color: #008000">If the counter doesn't exist in the current locale</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #008080">-not</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000">.</span><span style="color: #800080">$_</span><span style="color: #000000">))
                {
                    Write</span><span style="color: #000000">-</span><span style="color: #000000">Warning </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">The Performance counter with index $('{0:D4}' -f [int]$($CurrentPerformanceCounter.Index)) has no value for $($_). It will be skipped</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                }
                </span><span style="color: #008000">#</span><span style="color: #008000">If the counter doesn't exist in the en-us locale</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> (</span><span style="color: #008080">-not</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000">.'en</span><span style="color: #000000">-</span><span style="color: #000000">US'))
                {
                    Write</span><span style="color: #000000">-</span><span style="color: #000000">Warning </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">The Performance counter with index $('{0:D4}' -f [int]$($CurrentPerformanceCounter.Index)) has no value for en-US. It will be skipped</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                }
                </span><span style="color: #008000">#</span><span style="color: #008000">We generated the XML content for the counter : en-us and current locale matching</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #0000FF">else</span><span style="color: #000000">
                {
                    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000">.</span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #008080">-ne</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000">.'en</span><span style="color: #000000">-</span><span style="color: #000000">US')
                    {
                        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$XMLWriters</span><span style="color: #000000">[</span><span style="color: #800080">$_</span><span style="color: #000000">]
                        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteComment(</span><span style="color: #800000">&quot;</span><span style="color: #800000">Counter Id: $($CurrentPerformanceCounter.Index)</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
                        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteStartElement('Counter')
                        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteElementString('org',</span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000">.</span><span style="color: #800080">$_</span><span style="color: #000000">)
                        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteElementString('en',</span><span style="color: #800080">$CurrentPerformanceCounter</span><span style="color: #000000">.'en</span><span style="color: #000000">-</span><span style="color: #000000">US')
                        </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteEndElement()
                    }
                    </span><span style="color: #0000FF">else</span><span style="color: #000000">
                    {
                        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$($CurrentPerformanceCounter.$_)] is an english Perfomance Counter name. It will be skipped</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                    }
                }
            }
        } `
        </span><span style="color: #000000">-</span><span style="color: #0000FF">End</span><span style="color: #000000"> { 
            </span><span style="color: #008000">#</span><span style="color: #008000">After collection processing : We generate the XML files</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$Languages</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> {
                </span><span style="color: #008000">#</span><span style="color: #008000">Adding a prefix to identify the source OS</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$CurrentPLTFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Join</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$OutputDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ChildPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($_)_PFL_$($OSVersion).xml</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$XMLWriters</span><span style="color: #000000">[</span><span style="color: #800080">$_</span><span style="color: #000000">]
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteEndElement()
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.WriteEndDocument()
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Flush()
                </span><span style="color: #800080">$XMLWriter</span><span style="color: #000000">.Close()
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">The $CurrentPLTFile has been generated</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            }
        }
    }
    </span><span style="color: #0000FF">else</span><span style="color: #000000">
    {
        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$Force</span><span style="color: #000000">)
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">No non-english language found. The PLT file(s) won't be generated</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">No new non-english language found. The PLT file(s) won't be generated</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
    }
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Progress </span><span style="color: #000000">-</span><span style="color: #000000">Completed </span><span style="color: #000000">-</span><span style="color: #000000">Activity 'PLT Files Generation Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object 'PLT Files Generation Complete </span><span style="color: #000000">!</span><span style="color: #000000">'
}

</span><span style="color: #008000">#</span><span style="color: #008000">CAUTION : Performance Counter Index are not neccessary the same accross the OS. So work with only one OS version at a time</span><span style="color: #008000">
</span><span style="color: #000000">Clear</span><span style="color: #000000">-</span><span style="color: #000000">Host
</span><span style="color: #008000">#</span><span style="color: #008000"> Getting the this script path</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$MyInvocation</span><span style="color: #000000">.MyCommand.Path
</span><span style="color: #008000">#</span><span style="color: #008000"> Getting the directory of this script</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent

</span><span style="color: #008000">#</span><span style="color: #008000">Getting the source OS version </span><span style="color: #008000">
</span><span style="color: #800080">$OSVersion</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> [Environment]</span><span style="color: #000000">::</span><span style="color: #000000">OSVersion.Version.Major.ToString()</span><span style="color: #000000">+</span><span style="color: #000000">'.'</span><span style="color: #000000">+</span><span style="color: #000000">[Environment]</span><span style="color: #000000">::</span><span style="color: #000000">OSVersion.Version.Minor.ToString()
</span><span style="color: #008000">#</span><span style="color: #008000">Adding a prefix to identify the source OS</span><span style="color: #008000">
</span><span style="color: #800080">$ExportedCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">.replace((Get</span><span style="color: #000000">-</span><span style="color: #000000">Item </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">).Extension, </span><span style="color: #800000">&quot;</span><span style="color: #800000">_$($OSVersion).csv</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
</span><span style="color: #008000">#</span><span style="color: #008000">Getting local performance counters</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #000000">-</span><span style="color: #000000">FullName </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #008000">#</span><span style="color: #008000">Force</span><span style="color: #008000">
#</span><span style="color: #008000">Getting the current UI culture (ie. : en-US, fr-FR ...)</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> ([cultureinfo]</span><span style="color: #000000">::</span><span style="color: #000000">CurrentUICulture).Name
</span><span style="color: #800080">$DifferencesCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Join</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ChildPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">Differences.csv</span><span style="color: #800000">&quot;</span><span style="color: #000000">


</span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000">)
{

    </span><span style="color: #008000">#</span><span style="color: #008000">Hashtable for potential performance counters to import</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">{}
    </span><span style="color: #008000">#</span><span style="color: #008000">If we have a file for importing performance counters</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$ExportedCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Leaf)
    {
        </span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Import</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #000000">-</span><span style="color: #000000">FullName </span><span style="color: #800080">$ExportedCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
    }

    </span><span style="color: #008000">#</span><span style="color: #008000">If we have no imported performance counters</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000">.Count </span><span style="color: #008080">-le</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">)
    {
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message 'No Imported Performance Counters'
        </span><span style="color: #008000">#</span><span style="color: #008000">Export the performance counters to a CSV file</span><span style="color: #008000">
</span><span style="color: #000000">        Export</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$ExportedCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
        </span><span style="color: #008000">#</span><span style="color: #008000">Generating PLT File</span><span style="color: #008000">
</span><span style="color: #000000">        New</span><span style="color: #000000">-</span><span style="color: #000000">PLTFile </span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">OutputDir </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
    }
    </span><span style="color: #0000FF">else</span><span style="color: #000000">
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">Merging local and imported performance counter data</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Merge</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #000000">-</span><span style="color: #000000">ImportedPerformanceCounters </span><span style="color: #800080">$ImportedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">CurrentCulturePerformanceCounters </span><span style="color: #800080">$CurrentCulturePerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">CurrentUICulture </span><span style="color: #800080">$CurrentUICulture</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #008000">#</span><span style="color: #008000">-Force </span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #008000">#</span><span style="color: #008000">We export the performance counters to a CSV file</span><span style="color: #008000">
</span><span style="color: #000000">        Export</span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$ExportedCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
        </span><span style="color: #008000">#</span><span style="color: #008000">Generating PLT File</span><span style="color: #008000">
</span><span style="color: #000000">        New</span><span style="color: #000000">-</span><span style="color: #000000">PLTFile </span><span style="color: #000000">-</span><span style="color: #000000">PerformanceCounter </span><span style="color: #800080">$MergedPerformanceCounters</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">OutputDir </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
    }
}
</span><span style="color: #0000FF">else</span><span style="color: #000000">
{
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentUICulture has already been processed ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
}

New</span><span style="color: #000000">-</span><span style="color: #000000">PLTLangFile </span><span style="color: #000000">-</span><span style="color: #000000">FullName </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
</span><span style="color: #800080">$Differences</span><span style="color: #000000">=</span><span style="color: #000000">Compare</span><span style="color: #000000">-</span><span style="color: #000000">PLTFile </span><span style="color: #000000">-</span><span style="color: #000000">FullName </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">|</span><span style="color: #000000"> Sort</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property EN </span><span style="color: #000000">|</span><span style="color: #000000"> Select</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">*</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Unique
</span><span style="color: #800080">$Differences</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Select</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property EN, Locale, OS1, Value1, OS2 , Value2 </span><span style="color: #000000">|</span><span style="color: #000000"> Export</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$DifferencesCSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">NoTypeInformation

</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<p>Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>Génération des MachineKeys .Net dans des environnements à répartition de charge / .Net MachineKeys generation for loadbalanced environments.</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/machinekey-generation</link>
      <pubDate>Wed, 17 May 2017 08:48:06 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1986</guid>
      <description><![CDATA[&nbsp; Go to English version Les serveurs IIS de production sont souvent membres d’une ferme de...]]></description>
      <content:encoded><![CDATA[<p align="justify">&nbsp;</p> <p align="justify"><a href="https://blogs.msdn.microsoft.com/lavanack/2017/03/20/published-hotfix-list-powershell/#en-us" name="fr-fr">Go to English version</a></p> <p align="justify">Les serveurs IIS de production sont souvent membres d’une ferme de serveurs Web (A la fois des raisons de performance et de fiabilité). Or dans le cadre d’applications ASP.Net il est obligatoire d’uniformiser les MachineKeys des applications sur l’ensemble de ces serveurs (je vous invite à consulter le liens ci-dessous si vous en ignorez la raison). Ce point est parfois oublié lors du passage en production. Je vous propose ici un <a href="https://msdnshared.blob.core.windows.net/media/2017/05/MachineKeys.ps1_.txt">script</a> qui vous permettra de le faire (via notamment grâce à l’appel à la fonction Push-MachineKey et après avoir configuré correctement au moins un serveur “source” de la manière suivante (et pour toutes les applications concernées) :&nbsp; </p> <p align="justify">&nbsp;</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/05/Untitled.png"><img title="Untitled" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;padding-right: 0px" border="0" alt="Untitled" src="https://msdnshared.blob.core.windows.net/media/2017/05/Untitled_thumb.png" width="722" height="288"></a></p> <ol> <li> <div align="justify">Décocher les deux cases à cocher sous “Validation Key”</div></li> <li> <div align="justify">Décocher les deux cases à cocher sous “Decryption Key”</div></li> <li> <div align="justify">Cliquer sur “Generate Keys”’</div></li> <li> <div align="justify">Cliquer sur “Apply”</div></li></ol> <p align="justify">&nbsp;</p> <p align="justify">Une fois le serveur “source” correctement configuré, c’est lui qui servira de modèle pour la duplication des MachineKeys. Il suffit de lancer le <a href="https://msdnshared.blob.core.windows.net/media/2017/05/MachineKeys.ps1_.txt">script</a> ci-dessous (depuis le serveur “source”) après avoir modifié la variable $TargetIISServers pour y mettre la liste des serveurs cibles (ie. les autres serveurs de la ferme Web). </p> <p align="justify">Il existe d’autres fonctions présentes dans le <a href="https://msdnshared.blob.core.windows.net/media/2017/05/MachineKeys.ps1_.txt">script</a> que je vais sommairement expliquer ci-après :</p> <ul> <li> <div align="justify">Get-MachineKey : Retourne la liste des MachinesKey locales sous forme de tableau</div></li> <li> <div align="justify">Set-MachineKey : Valorise les MachinesKey locales depuis un tableau passé en argument. Cette fonction supporte les switchs <em>–whatif</em> et <em>–confirm</em> (Risk Mitigation) </div></li> <li> <div align="justify">Push-MachineKey : Pousse les MachineKey locales sur les ordinateurs passées en argument (via du Remoting PowerShell)</div></li> <li> <div align="justify">Show-MachineKey : Affiche (et retourne si <em>–passthru</em> est spécifié) les machines key sur les machines passées en paramètres.</div></li> <li> <div align="justify">Export-MachineKey : Exporte la liste des MachinesKey locales dans le fichier CSV passé en argument</div></li> <li> <div align="justify">Import-MachineKey : Importe localement les MachinesKey depuis le fichier CSV passé en argument</div></li></ul> <p align="justify">&nbsp;</p> <p align="justify"><strong>Liens utiles :</strong></p> <ul> <li> <div align="justify">Generate a Unique Validation Key for Each Application (IIS 7) : <a href="https://technet.microsoft.com/en-us/library/cc754909(v=ws.10).aspx">https://technet.microsoft.com/en-us/library/cc754909(v=ws.10).aspx</a> </div> <li> <div align="justify">machineKey Element (ASP.NET Settings Schema) : <a href="https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.71).aspx">https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.71).aspx</a> </div> <li> <div align="justify">How To: Configure MachineKey in ASP.NET 2.0 : <a href="https://msdn.microsoft.com/en-us/library/ff649308.aspx#paght000007_webfarmdeploymentconsiderations">https://msdn.microsoft.com/en-us/library/ff649308.aspx#paght000007_webfarmdeploymentconsiderations</a> </div> <li> <div align="justify">Generate a Machine Key for a Web Farm (IIS 7) : <a href="https://technet.microsoft.com/en-us/library/cc731979(v=WS.10).aspx">https://technet.microsoft.com/en-us/library/cc731979(v=WS.10).aspx</a> </div></li></ul> <p align="justify">&nbsp; <p align="justify">Ce script est aussi disponible dans le TechNet Script Center : <a title="https://gallery.technet.microsoft.com/IIS-WebFarm-Machine-Key-d8c213de" href="https://gallery.technet.microsoft.com/IIS-WebFarm-Machine-Key-d8c213de">https://gallery.technet.microsoft.com/IIS-WebFarm-Machine-Key-d8c213de</a> <p align="justify"><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/012717_1333_Fusionnerde1.png"></p> <p align="justify"><a href="https://blogs.msdn.microsoft.com/lavanack/2017/03/20/published-hotfix-list-powershell/#fr-FR" name="en-us">Aller à la version française</a> <p align="justify"><br>IIS production servers are often members of a Web server farm (for performance and reliability reasons). However, in the context of ASP.Net applications, it is mandatory to standardize the MachineKeys of applications on all of these servers (I invite you to consult the links below if you do not know the reason). This point is sometimes forgotten in the production environment. I propose here a <a href="https://msdnshared.blob.core.windows.net/media/2017/05/MachineKeys.ps1_.txt">script</a> that will allow you to do this (via the call to the Push-MachineKey function and after having correctly configured at least one "source" server in the following way (and for all the applications concerned) :</p> <p align="justify">&nbsp; <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/05/Untitled1.png"><img title="Untitled" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;padding-right: 0px" border="0" alt="Untitled" src="https://msdnshared.blob.core.windows.net/media/2017/05/Untitled_thumb1.png" width="722" height="284"></a></p> <ol> <li> <div align="justify">Uncheck the two checkboxes under “Validation Key”</div></li> <li> <div align="justify">Uncheck the two checkboxes under “Decryption Key”</div></li> <li> <div align="justify">Click on “Generate Keys”’</div></li> <li> <div align="justify">Click on “Apply”</div></li></ol> <p align="justify">&nbsp;</p> <p align="justify">Once the "source" server is correctly configured, it will be the template for the duplication of the MachineKeys. Just run the <a href="https://msdnshared.blob.core.windows.net/media/2017/05/MachineKeys.ps1_.txt">script</a> below (from the "source" server) after modifying the $TargetIISServers variable to set the list of target servers (ie. the other servers in the Web farm). <p align="justify">&nbsp;</p> <p>There are other functions present in the <a href="https://msdnshared.blob.core.windows.net/media/2017/05/MachineKeys.ps1_.txt">script</a> that I will briefly explain hereafter:</p> <ul> <li>Get-MachineKey: Returns the list of local MachinesKey as an array</li> <li>Set-MachineKey: Sets the local MachinesKey from an array passed as argument. This function supports the -whatif and -confirm (Risk Mitigation)</li> <li>Push-MachineKey: Pushes the local MachineKey on the computers passed as argument (via the PowerShell Remoting)</li> <li>Show-MachineKey: Displays (and returns if -passthru is specified) the MachineKey on the computers passed as argument.</li> <li>Export-MachineKey: Exports the list of the local MachinesKey in the CSV file passed as argument</li> <li>Import-MachineKey: Locally imports the MachinesKey from the CSV file passed as argument</li></ul> <p>&nbsp;</p> <p align="justify"><strong>Useful links:</strong></p> <ul> <li> <div align="justify">Generate a Unique Validation Key for Each Application (IIS 7) : <a href="https://technet.microsoft.com/en-us/library/cc754909(v=ws.10).aspx">https://technet.microsoft.com/en-us/library/cc754909(v=ws.10).aspx</a> </div> <li> <div align="justify">machineKey Element (ASP.NET Settings Schema) : <a href="https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.71).aspx">https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.71).aspx</a> </div> <li> <div align="justify">How To: Configure MachineKey in ASP.NET 2.0 : <a href="https://msdn.microsoft.com/en-us/library/ff649308.aspx#paght000007_webfarmdeploymentconsiderations">https://msdn.microsoft.com/en-us/library/ff649308.aspx#paght000007_webfarmdeploymentconsiderations</a> </div> <li> <div align="justify">Generate a Machine Key for a Web Farm (IIS 7) : <a href="https://technet.microsoft.com/en-us/library/cc731979(v=WS.10).aspx">https://technet.microsoft.com/en-us/library/cc731979(v=WS.10).aspx</a> </div></li></ul> <p align="justify">&nbsp; </p> <p align="justify">The script is also available in the TechNet Script Center : <a title="https://gallery.technet.microsoft.com/IIS-WebFarm-Machine-Key-d8c213de" href="https://gallery.technet.microsoft.com/IIS-WebFarm-Machine-Key-d8c213de">https://gallery.technet.microsoft.com/IIS-WebFarm-Machine-Key-d8c213de</a></p> <p align="justify">&nbsp;</p> <div align="justify"> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:a1e7b125-4a27-479e-871b-f4d3ecee6449" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 762px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000">requires -version 3 -RunAsAdministrator </span><span style="color: #008000">
#</span><span style="color: #008000">requires -Modules WebAdministration</span><span style="color: #008000">
</span><span style="color: #000000">
Import</span><span style="color: #000000">-</span><span style="color: #000000">Module </span><span style="color: #000000">-</span><span style="color: #000000">Name WebAdministration

</span><span style="color: #008000">#</span><span style="color: #008000">region function definitions</span><span style="color: #008000">
#</span><span style="color: #008000">For getting machine keys</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
{
    Import</span><span style="color: #000000">-</span><span style="color: #000000">Module </span><span style="color: #000000">-</span><span style="color: #000000">Name WebAdministration
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Getting machine key configuration from $($env:COMPUTERNAME)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
    </span><span style="color: #800080">$MachineKey</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">WebConfiguration </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> 'system.web</span><span style="color: #000000">/</span><span style="color: #000000">machinekey' </span><span style="color: #000000">-</span><span style="color: #000000">Recurse </span><span style="color: #000000">|</span><span style="color: #000000">
    Select</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property decryptionKey, decryption, validationKey, validation, PSPath, </span><span style="color: #000000">@</span><span style="color: #000000">{
        Name       </span><span style="color: #000000">=</span><span style="color: #000000"> 'ComputerName'
        Expression </span><span style="color: #000000">=</span><span style="color: #000000"> {
            </span><span style="color: #800080">$env:COMPUTERNAME</span><span style="color: #000000">
        }
    }
    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$MachineKey</span><span style="color: #000000">
}

</span><span style="color: #008000">#</span><span style="color: #008000">For setting machine keys</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Set</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
{
    [CmdletBinding(SupportsShouldProcess</span><span style="color: #000000">=</span><span style="color: #0000FF">$true</span><span style="color: #000000">)]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [array]</span><span style="color: #800080">$InputObject</span><span style="color: #000000">
    )
    </span><span style="color: #0000FF">begin</span><span style="color: #000000">
    {
        Import</span><span style="color: #000000">-</span><span style="color: #000000">Module </span><span style="color: #000000">-</span><span style="color: #000000">Name WebAdministration
    }
    </span><span style="color: #0000FF">process</span><span style="color: #000000">
    {
        </span><span style="color: #0000FF">foreach</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$InputObject</span><span style="color: #000000">)
        {
            </span><span style="color: #800080">$IISPath</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000">.PSPath </span><span style="color: #008080">-replace</span><span style="color: #000000"> 'MACHINE</span><span style="color: #000000">/</span><span style="color: #000000">WEBROOT</span><span style="color: #000000">/</span><span style="color: #000000">APPHOST</span><span style="color: #000000">/</span><span style="color: #000000">', 'IIS:\sites\'
            </span><span style="color: #0000FF">if</span><span style="color: #000000"> (Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$IISPath</span><span style="color: #000000">)
            {
                </span><span style="color: #008000">#</span><span style="color: #008000">Risk Mitigation : support of -whatif and -confirm</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #0000FF">If</span><span style="color: #000000"> ((</span><span style="color: #800080">$pscmdlet</span><span style="color: #000000"> </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">) </span><span style="color: #008080">-or</span><span style="color: #000000"> (</span><span style="color: #800080">$pscmdlet</span><span style="color: #000000">.ShouldProcess(</span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000">.PSPath, 'Setting Machine Keys')))
                {
                    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$env:Computername] Setting the decryptionKey to $($CurrentInputObject.decryptionKey) for $($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                    Set</span><span style="color: #000000">-</span><span style="color: #000000">WebConfigurationProperty </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> 'system.web</span><span style="color: #000000">/</span><span style="color: #000000">machinekey' </span><span style="color: #000000">-</span><span style="color: #000000">PSPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">name 'decryptionKey' </span><span style="color: #000000">-</span><span style="color: #000000">value </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000">.decryptionKey)
                    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$env:Computername] Setting the Decryption Algorithm to $($CurrentInputObject.Decryption) for $($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                    Set</span><span style="color: #000000">-</span><span style="color: #000000">WebConfigurationProperty </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> 'system.web</span><span style="color: #000000">/</span><span style="color: #000000">machinekey' </span><span style="color: #000000">-</span><span style="color: #000000">PSPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000">  </span><span style="color: #000000">-</span><span style="color: #000000">name 'Decryption' </span><span style="color: #000000">-</span><span style="color: #000000">value </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000">.Decryption)
                    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$env:Computername] Setting the validationKey to $($CurrentInputObject.validationKey) for $($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                    Set</span><span style="color: #000000">-</span><span style="color: #000000">WebConfigurationProperty </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> 'system.web</span><span style="color: #000000">/</span><span style="color: #000000">machinekey' </span><span style="color: #000000">-</span><span style="color: #000000">PSPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">name 'validationKey' </span><span style="color: #000000">-</span><span style="color: #000000">value </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000">.validationKey)
                    Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">[$env:Computername] Setting the validation Algorithm to $($CurrentInputObject.validation) for $($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                    Set</span><span style="color: #000000">-</span><span style="color: #000000">WebConfigurationProperty </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> 'system.web</span><span style="color: #000000">/</span><span style="color: #000000">machinekey' </span><span style="color: #000000">-</span><span style="color: #000000">PSPath </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentInputObject.PSPath)</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">name 'validation' </span><span style="color: #000000">-</span><span style="color: #000000">value </span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$CurrentInputObject</span><span style="color: #000000">.validation)
                }
            }
            </span><span style="color: #0000FF">else</span><span style="color: #000000">
            {
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Warning </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">$IISPath doesn't exist on $($env:COMPUTERNAME)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            }
        }
    }
    </span><span style="color: #0000FF">end</span><span style="color: #000000">
    {
    }
}

</span><span style="color: #0000FF">Function</span><span style="color: #000000"> Push</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
{
    [CmdletBinding(PositionalBinding </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, SupportsShouldProcess </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [String[]]</span><span style="color: #800080">$ComputerName</span><span style="color: #000000">
    )
    </span><span style="color: #0000FF">begin</span><span style="color: #000000">
    {
        </span><span style="color: #800080">$LocalKeys</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
    }
    </span><span style="color: #0000FF">process</span><span style="color: #000000">
    {
        Invoke</span><span style="color: #000000">-</span><span style="color: #000000">Command </span><span style="color: #000000">-</span><span style="color: #000000">ComputerName </span><span style="color: #800080">$ComputerName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ScriptBlock </span><span style="color: #000000">$</span><span style="color: #000000">{</span><span style="color: #0000FF">function</span><span style="color: #000000">:Set</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey}  </span><span style="color: #000000">-</span><span style="color: #000000">ArgumentList (,</span><span style="color: #800080">$LocalKeys</span><span style="color: #000000">)
    }
    </span><span style="color: #0000FF">end</span><span style="color: #000000">
    {
    }
}


</span><span style="color: #0000FF">Function</span><span style="color: #000000"> Show</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
{
    [CmdletBinding(PositionalBinding </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">, SupportsShouldProcess </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [String[]]</span><span style="color: #800080">$ComputerName</span><span style="color: #000000">,

        [parameter(Mandatory</span><span style="color: #000000">=</span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
        [</span><span style="color: #0000FF">switch</span><span style="color: #000000">]</span><span style="color: #800080">$PassThru</span><span style="color: #000000">
    )
    </span><span style="color: #0000FF">begin</span><span style="color: #000000">
    {
        </span><span style="color: #800080">$AllKeys</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">()
    }
    </span><span style="color: #0000FF">process</span><span style="color: #000000">
    {
        </span><span style="color: #800080">$AllKeys</span><span style="color: #000000">+=</span><span style="color: #000000">Invoke</span><span style="color: #000000">-</span><span style="color: #000000">Command </span><span style="color: #000000">-</span><span style="color: #000000">ComputerName </span><span style="color: #800080">$ComputerName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ScriptBlock </span><span style="color: #000000">$</span><span style="color: #000000">{</span><span style="color: #0000FF">function</span><span style="color: #000000">:Get</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey} </span><span style="color: #000000">|</span><span style="color: #000000"> Select</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">*</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ExcludeProperty PSComputerName, RunSpaceId
    }
    </span><span style="color: #0000FF">end</span><span style="color: #000000">
    {
        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$PassThru</span><span style="color: #000000">)
        {
            </span><span style="color: #800080">$AllKeys</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Sort</span><span style="color: #000000">-</span><span style="color: #000000">Object PSPath, ComputerName </span><span style="color: #000000">|</span><span style="color: #000000"> Out</span><span style="color: #000000">-</span><span style="color: #000000">GridView </span><span style="color: #000000">-</span><span style="color: #000000">Title 'Machine Keys across Web Servers' </span><span style="color: #000000">-</span><span style="color: #000000">PassThru
        }
        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            </span><span style="color: #800080">$AllKeys</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Sort</span><span style="color: #000000">-</span><span style="color: #000000">Object PSPath, ComputerName </span><span style="color: #000000">|</span><span style="color: #000000"> Out</span><span style="color: #000000">-</span><span style="color: #000000">GridView </span><span style="color: #000000">-</span><span style="color: #000000">Title 'Machine Keys across Web Servers'
        }
    }
}


</span><span style="color: #0000FF">function</span><span style="color: #000000"> Export</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path (Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent) </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">CSV file full name</span><span style="color: #008000">
</span><span style="color: #000000">        
        [Alias('FilePath', 'Path')]
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">
    )
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Exporting machine key configuration from $($env:COMPUTERNAME) to $CSVFile</span><span style="color: #800000">&quot;</span><span style="color: #000000">
    Get</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey </span><span style="color: #000000">|</span><span style="color: #000000"> Export</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">NoTypeInformation
}

</span><span style="color: #008000">#</span><span style="color: #008000">For importing machine keys</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Import</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey
{
    [CmdletBinding(PositionalBinding </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, SupportsShouldProcess </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">, ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Leaf
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">CSV file full name</span><span style="color: #008000">
</span><span style="color: #000000">        [Alias('FilePath', 'Path')]
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">
    )
    </span><span style="color: #800080">$LocalKeys</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Import</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000">
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Importing machine key configuration from $(($LocalKeys | Select-Object -ExpandProperty ComputerName -Unique).ComputerName)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
    Set</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey </span><span style="color: #000000">-</span><span style="color: #000000">InputObject </span><span style="color: #800080">$LocalKeys</span><span style="color: #000000">
}
</span><span style="color: #008000">#</span><span style="color: #008000">endregion</span><span style="color: #008000">
</span><span style="color: #000000">
Clear</span><span style="color: #000000">-</span><span style="color: #000000">Host
</span><span style="color: #008000">#</span><span style="color: #008000"> Getting the this script path</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$MyInvocation</span><span style="color: #000000">.MyCommand.Path
</span><span style="color: #008000">#</span><span style="color: #008000"> Getting the directory of this script</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent
</span><span style="color: #008000">#</span><span style="color: #008000">CSV file for exporting/importing machine keys</span><span style="color: #008000">
</span><span style="color: #800080">$CSVFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">.replace((Get</span><span style="color: #000000">-</span><span style="color: #000000">Item </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">).Extension, '.csv')

</span><span style="color: #008000">#</span><span style="color: #008000">Exporting/Backing up local machine keys to a CSV file</span><span style="color: #008000">
#</span><span style="color: #008000">Export-MachineKey -Path $CSVFile -Verbose</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">Importing and setting machine keys from a CSVFile to the local computer </span><span style="color: #008000">
#</span><span style="color: #008000">Get-Item -Path $CSVFile | Import-MachineKey -Verbose #-WhatIf </span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">Getting local machine keys</span><span style="color: #008000">
#</span><span style="color: #008000">$LocalKeys = Get-MachineKey</span><span style="color: #008000">
#</span><span style="color: #008000">Exporting/Backing up local machine keys to a CSV file</span><span style="color: #008000">
#</span><span style="color: #008000">$LocalKeys | Export-Csv -Path $CSVFile -NoTypeInformation</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">Importing machine keys from a CSVFile</span><span style="color: #008000">
#</span><span style="color: #008000">$LocalKeys = Import-Csv -Path $CSVFile</span><span style="color: #008000">
#</span><span style="color: #008000">Setting machine keys the local computer </span><span style="color: #008000">
#</span><span style="color: #008000">Set-MachineKey -InputObject $LocalKeys -whatif</span><span style="color: #008000">
#</span><span style="color: #008000">$LocalKeys | Set-MachineKey -whatif</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #800080">$TargetIISServers</span><span style="color: #000000">=</span><span style="color: #800000">&quot;</span><span style="color: #800000">IIS002</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">DC001</span><span style="color: #800000">&quot;</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">Pushing/Duplicating local machine keys (after a manual setting on the source server) on the targeted computers</span><span style="color: #008000">
</span><span style="color: #000000">Push</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey Push</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey </span><span style="color: #000000">-</span><span style="color: #000000">ComputerName </span><span style="color: #800080">$TargetIISServers</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose


</span><span style="color: #008000">#</span><span style="color: #008000">Checking all machine keys across the web servers</span><span style="color: #008000">
</span><span style="color: #800080">$KeysAcrossWebFarm</span><span style="color: #000000">=</span><span style="color: #000000">Show</span><span style="color: #000000">-</span><span style="color: #000000">MachineKey </span><span style="color: #000000">-</span><span style="color: #000000">ComputerName </span><span style="color: #800080">$TargetIISServers</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PassThru </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
</span><span style="color: #800080">$KeysAcrossWebFarm</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div></div>]]></content:encoded>
    </item>
    <item>
      <title>Lister les attributs de debug de vos DLL / List the debuggable attributes of your DLL</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/lister-les-attributs-de-debug-de-vos-dll-list-the-debuggable-attributes-of-your-dll</link>
      <pubDate>Tue, 21 Mar 2017 11:12:57 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1925</guid>
      <description><![CDATA[Go to English version L’article suivant explique en détail les attributs IsJITTrackingEnabled (À...]]></description>
      <content:encoded><![CDATA[<p><a href="#en-us" name="fr-fr">Go to English version</a></p> <p>L’article <a href="https://social.msdn.microsoft.com/Forums/vstudio/en-US/33961718-64c4-4986-a092-5cfad7c8e414/isjittrackingenabled-and-other-debugging-flags-explained?forum=vsdebug">suivant</a> explique en détail les attributs <a href="https://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.isjittrackingenabled(v=vs.110).aspx">IsJITTrackingEnabled</a> (À partir de .NET Framework 2.0, les informations de suivi JIT sont toujours activées pendant le débogage et cette valeur de propriété est ignorée) et <a title="https://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.isjitoptimizerdisabled(v=vs.110).aspx" href="https://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.isjitoptimizerdisabled(v=vs.110).aspx">IsJITOptimizerDisabled</a> d’une DLL. Dans le cadre d’une application Web, de nombreuses DLL peuvent être utilisées et il serait fastidieux de devoir les tester une à une avec <a href="https://msdn.microsoft.com/fr-fr/library/f7dy01k1(v=vs.110).aspx">ILDasm.exe</a>. Je vous propose donc un script Powershell qui listera ces attributs sur les DLL d’un répertoire ou d’un site Web donné. Le resultat sera similaire à la capture d’écran ci-dessous pour chaque DLL.</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/03/image462.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin-left: auto;padding-right: 0px;border-top-width: 0px;margin-right: auto" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/03/image_thumb438.png" width="826" height="131"></a></p> <p><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/012717_1333_Fusionnerde1.png">  <p><a href="#fr-FR" name="en-us">Aller à la version française</a></p> <p>&nbsp;</p> <p>The following <a href="https://social.msdn.microsoft.com/Forums/vstudio/en-US/33961718-64c4-4986-a092-5cfad7c8e414/isjittrackingenabled-and-other-debugging-flags-explained?forum=vsdebug">article</a> explained the <a href="https://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.isjittrackingenabled(v=vs.110).aspx">IsJITTrackingEnabled</a> (Starting with the .NET Framework 2.0, JIT tracking information is always enabled during debugging, and this property value is ignored) and <a title="https://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.isjitoptimizerdisabled(v=vs.110).aspx" href="https://msdn.microsoft.com/en-us/library/system.diagnostics.debuggableattribute.isjitoptimizerdisabled(v=vs.110).aspx">IsJITOptimizerDisabled</a> of a DLL. In the context of a web application, a great number of DLL can be used and an individual processing (one DLL at at time) with <a href="https://msdn.microsoft.com/fr-fr/library/f7dy01k1(v=vs.110).aspx">ILDasm.exe</a>. could be painful. So I propose a PowerShell script which will list these attributes for all DLL inside a specified directory or a web site. The result will be similar to the screenshot below pour each DLL.</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/03/image463.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin-left: auto;padding-right: 0px;border-top-width: 0px;margin-right: auto" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/03/image_thumb439.png" width="826" height="120"></a></p> <p>&nbsp;</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:b9dd6cf2-9cf6-4c0a-afab-00b7ac83495e" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 762px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000">requires -version 4 -Module WebAdministration</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">region Function Definitions</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Expand</span><span style="color: #000000">-</span><span style="color: #000000">String 
{ 
    &lt;</span><span style="color: #008000">#
</span><span style="color: #000000">            .SYNOPSIS
            Expands a single quoted string containing a reference to a PowerShell variable or to an environment variable.

            .DESCRIPTION
            Expands a single quoted string containing a reference to a PowerShell variable or to an environment variable.

            .PARAMETER Value
            The string to expand (Mandatory)

            .PARAMETER EnvironmentVariable
            A </span><span style="color: #0000FF">switch</span><span style="color: #000000"> to speicify a string containing a reference to an environment variable

            .EXAMPLE
            '</span><span style="color: #000000">$</span><span style="color: #000000">(</span><span style="color: #800080">$host</span><span style="color: #000000">.Version)' </span><span style="color: #000000">|</span><span style="color: #000000"> Expand</span><span style="color: #000000">-</span><span style="color: #000000">string
            Expands the </span><span style="color: #800080">$host</span><span style="color: #000000">.Version PowerShell Built</span><span style="color: #000000">-</span><span style="color: #0000FF">in</span><span style="color: #000000"> variable

            .EXAMPLE
            Expand</span><span style="color: #000000">-</span><span style="color: #000000">String </span><span style="color: #000000">-</span><span style="color: #000000">Value </span><span style="color: #800000">&quot;</span><span style="color: #800000">%temp%</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">EnvironmentVariable
            Expands the </span><span style="color: #000000">%</span><span style="color: #000000">Temp</span><span style="color: #000000">%</span><span style="color: #000000"> MS</span><span style="color: #000000">-</span><span style="color: #000000">DOS environment variable
        
            .INPUTS
            System.String

            .OUTPUTS
            System.String

    </span><span style="color: #008000">#</span><span style="color: #008000">&gt;</span><span style="color: #008000">
</span><span style="color: #000000">    [CmdletBinding()]
    </span><span style="color: #0000FF">param</span><span style="color: #000000">( 
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">,Position </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">,ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">)] 
        [string]</span><span style="color: #800080">$Value</span><span style="color: #000000">, 

        [</span><span style="color: #0000FF">switch</span><span style="color: #000000">]</span><span style="color: #800080">$EnvironmentVariable</span><span style="color: #000000"> 
    )
    </span><span style="color: #008000">#</span><span style="color: #008000">If we specified that the specified value is related to an environment variable</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">if</span><span style="color: #000000">(</span><span style="color: #800080">$EnvironmentVariable</span><span style="color: #000000">)
    {
        [System.Environment]</span><span style="color: #000000">::</span><span style="color: #000000">ExpandEnvironmentVariables(</span><span style="color: #800080">$Value</span><span style="color: #000000">)
    } 
    </span><span style="color: #0000FF">else</span><span style="color: #000000"> 
    {
        </span><span style="color: #800080">$ExecutionContext</span><span style="color: #000000">.InvokeCommand.ExpandString(</span><span style="color: #800080">$Value</span><span style="color: #000000">)
    } 
} 

</span><span style="color: #0000FF">function</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">PhysicalPath
{
    &lt;</span><span style="color: #008000">#
</span><span style="color: #000000">            .SYNOPSIS
            Returns the expanded physical path(s) </span><span style="color: #0000FF">for</span><span style="color: #000000"> the website(s) specified as argument.

            .DESCRIPTION
            Returns the expanded physical path(s) </span><span style="color: #0000FF">for</span><span style="color: #000000"> the website(s) specified as argument.

            .PARAMETER Site
            Optional parameter to specify the web site name(s) </span><span style="color: #0000FF">for</span><span style="color: #000000"> which you want get the physical path. It can contains a collection of web site names. </span><span style="color: #0000FF">If</span><span style="color: #000000"> you omit the </span><span style="color: #0000FF">function</span><span style="color: #000000"> will </span><span style="color: #0000FF">return</span><span style="color: #000000"> the physical path </span><span style="color: #0000FF">for</span><span style="color: #000000"> all hosted web sites.

            .EXAMPLE
            Get</span><span style="color: #000000">-</span><span style="color: #000000">PhysicalPath

            .EXAMPLE
            Get</span><span style="color: #000000">-</span><span style="color: #000000">PhysicalPath </span><span style="color: #000000">-</span><span style="color: #000000">Site </span><span style="color: #800000">&quot;</span><span style="color: #800000">Default Web Site</span><span style="color: #800000">&quot;</span><span style="color: #000000">

            .EXAMPLE
            Get</span><span style="color: #000000">-</span><span style="color: #000000">PhysicalPath </span><span style="color: #000000">-</span><span style="color: #000000">Site </span><span style="color: #800000">&quot;</span><span style="color: #800000">Default Web Site</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">www.contoso.com</span><span style="color: #800000">&quot;</span><span style="color: #000000">

            .INPUTS
            System.String[]

            .OUTPUTS
            System.String[]

    </span><span style="color: #008000">#</span><span style="color: #008000">&gt;    </span><span style="color: #008000">
</span><span style="color: #000000">    [CmdletBinding()]
    </span><span style="color: #0000FF">param</span><span style="color: #000000">( 
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)] 
        [Alias('Name')]
        </span><span style="color: #008000">#</span><span style="color: #008000">Web site name(s)</span><span style="color: #008000">
</span><span style="color: #000000">        [String[]]</span><span style="color: #800080">$Site</span><span style="color: #000000">
    )
    </span><span style="color: #008000">#</span><span style="color: #008000">Array for storing all physical path related to the specified web sites</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">()
    </span><span style="color: #008000">#</span><span style="color: #008000">If no site has been specified we get all hosted web sites</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #000000">!</span><span style="color: #800080">$Site</span><span style="color: #000000">)
    {
        </span><span style="color: #800080">$WebSites</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">Website
    }
    </span><span style="color: #008000">#</span><span style="color: #008000">If we specified one or multiple web site names we filter to get only those related to the specified names</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">else</span><span style="color: #000000">
    {
        </span><span style="color: #800080">$WebSites</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">Website </span><span style="color: #000000">|</span><span style="color: #000000"> Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript {
            </span><span style="color: #800080">$_</span><span style="color: #000000">.Name </span><span style="color: #000000">-</span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$Site</span><span style="color: #000000">
        }
    }
    </span><span style="color: #008000">#</span><span style="color: #008000">For each specified website</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$WebSites</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object  </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> { 
        </span><span style="color: #008000">#</span><span style="color: #008000">Getting the physical path of the sites and storing it in the array</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> Expand</span><span style="color: #000000">-</span><span style="color: #000000">String </span><span style="color: #000000">-</span><span style="color: #000000">Value </span><span style="color: #800080">$_</span><span style="color: #000000">.PhysicalPath </span><span style="color: #000000">-</span><span style="color: #000000">EnvironmentVariable
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Adding Physical Path for Site: $($_.Name) (Path:$($_.PhysicalPath))</span><span style="color: #800000">&quot;</span><span style="color: #000000">

        </span><span style="color: #008000">#</span><span style="color: #008000">Getting the physical path of the nested applications and storing it in the array</span><span style="color: #008000">
</span><span style="color: #000000">        Get</span><span style="color: #000000">-</span><span style="color: #000000">WebApplication </span><span style="color: #000000">-</span><span style="color: #000000">Site </span><span style="color: #800080">$_</span><span style="color: #000000">.Name </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object  </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> { 
            </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> Expand</span><span style="color: #000000">-</span><span style="color: #000000">String </span><span style="color: #000000">-</span><span style="color: #000000">Value </span><span style="color: #800080">$_</span><span style="color: #000000">.PhysicalPath </span><span style="color: #000000">-</span><span style="color: #000000">EnvironmentVariable
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`tAdding Physical Path for Application: $($_.Path) (Path:$($_.PhysicalPath))</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }

        </span><span style="color: #008000">#</span><span style="color: #008000">Getting the physical path of the nested virtual directories and storing it in the array</span><span style="color: #008000">
</span><span style="color: #000000">        Get</span><span style="color: #000000">-</span><span style="color: #000000">WebVirtualDirectory </span><span style="color: #000000">-</span><span style="color: #000000">Site </span><span style="color: #800080">$_</span><span style="color: #000000">.Name </span><span style="color: #000000">|</span><span style="color: #000000"> </span><span style="color: #0000FF">ForEach</span><span style="color: #000000">-</span><span style="color: #000000">Object  </span><span style="color: #000000">-</span><span style="color: #0000FF">Process</span><span style="color: #000000"> {
            </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> Expand</span><span style="color: #000000">-</span><span style="color: #000000">String </span><span style="color: #000000">-</span><span style="color: #000000">Value </span><span style="color: #800080">$_</span><span style="color: #000000">.PhysicalPath </span><span style="color: #000000">-</span><span style="color: #000000">EnvironmentVariable
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`tAdding Physical Path for Virtual Directory: $($_.Path) (Path:$($_.PhysicalPath))</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
    }
    </span><span style="color: #008000">#</span><span style="color: #008000">Spkiiping duplicate entries</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">(</span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Select</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Unique)
    </span><span style="color: #008000">#</span><span style="color: #008000">Returning physical paths</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000">
}

</span><span style="color: #0000FF">function</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">DebuggableAttribute
&lt;</span><span style="color: #008000">#
</span><span style="color: #000000">        .SYNOPSIS
        Returns an hashtable containing all assemblies and related assemblies found </span><span style="color: #0000FF">in</span><span style="color: #000000"> the specified physical paths or web site name(s)

        .DESCRIPTION
        Returns an hashtable containing all assemblies and related assemblies found </span><span style="color: #0000FF">in</span><span style="color: #000000"> the specified physical paths or web site name(s)
        The keys are the found assemblies (under the form a custom PowerShell object) and the values are arays containing referenced assemblies (under the form a custom PowerShell object)

        .PARAMETER Site
        Optional parameter to specify the web site name(s) from where you want get assembly informations. </span><span style="color: #0000FF">If</span><span style="color: #000000"> you omit the </span><span style="color: #0000FF">function</span><span style="color: #000000"> will </span><span style="color: #0000FF">return</span><span style="color: #000000"> the physical path </span><span style="color: #0000FF">for</span><span style="color: #000000"> all hosted web sites.

        .PARAMETER Path
        Optional parameter to specify the physical path(s) from where you want get assembly informations.

        .EXAMPLE
        Get</span><span style="color: #000000">-</span><span style="color: #000000">DebuggableAttribute

        .EXAMPLE
        Get</span><span style="color: #000000">-</span><span style="color: #000000">DebuggableAttribute </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800000">&quot;</span><span style="color: #800000">C:\inetpub\wwwroot</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">D:\inetpub\wwwroot</span><span style="color: #800000">&quot;</span><span style="color: #000000">

        .EXAMPLE
        Get</span><span style="color: #000000">-</span><span style="color: #000000">DebuggableAttribute </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800000">&quot;</span><span style="color: #800000">C:\inetpub\wwwroot</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose

        .EXAMPLE
        Get</span><span style="color: #000000">-</span><span style="color: #000000">DebuggableAttribute </span><span style="color: #000000">-</span><span style="color: #000000">Site </span><span style="color: #800000">&quot;</span><span style="color: #800000">Default Web Site</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Verbose

        .INPUTS
        System.String[]

        .OUTPUTS
        System.Array

</span><span style="color: #008000">#</span><span style="color: #008000">&gt;    </span><span style="color: #008000">
</span><span style="color: #000000">{
    [CmdletBinding(DefaultParameterSetName </span><span style="color: #000000">=</span><span style="color: #000000"> 'Site')]
    </span><span style="color: #0000FF">param</span><span style="color: #000000">(
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">,ParameterSetName </span><span style="color: #000000">=</span><span style="color: #000000"> 'Site')] 
        [ValidateNotNullOrEmpty()]
        [Alias('Name')]
        </span><span style="color: #008000">#</span><span style="color: #008000">if Web site names have been specified</span><span style="color: #008000">
</span><span style="color: #000000">        [String[]]</span><span style="color: #800080">$Site</span><span style="color: #000000">,
        
        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">,ParameterSetName </span><span style="color: #000000">=</span><span style="color: #000000"> 'File',ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">,ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({
                    Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Container
        })]
        </span><span style="color: #008000">#</span><span style="color: #008000">if file paths have been specified</span><span style="color: #008000">
</span><span style="color: #000000">        [alias('FullName')]
        [String[]]</span><span style="color: #800080">$Path</span><span style="color: #000000">
    )
    
    Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Parameter Set : $($psCmdlet.ParameterSetName)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
    </span><span style="color: #008000">#</span><span style="color: #008000">if Web site names have been specified</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">if</span><span style="color: #000000"> ((</span><span style="color: #800080">$psCmdlet</span><span style="color: #000000">.ParameterSetName) </span><span style="color: #008080">-eq</span><span style="color: #000000"> 'Site')
    {
        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$Site</span><span style="color: #000000">)
        {
            </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">PhysicalPath </span><span style="color: #000000">-</span><span style="color: #000000">Site </span><span style="color: #800080">$Site</span><span style="color: #000000">
        }
        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">PhysicalPath
        }
    }
    </span><span style="color: #008000">#</span><span style="color: #008000">if file paths have been specified</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> ((</span><span style="color: #800080">$psCmdlet</span><span style="color: #000000">.ParameterSetName) </span><span style="color: #008080">-eq</span><span style="color: #000000"> 'File')
    {
        </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Path</span><span style="color: #000000">
    }
    
    </span><span style="color: #008000">#</span><span style="color: #008000">Array for storing all data</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">()
    </span><span style="color: #008000">#</span><span style="color: #008000">Going through physical path collection</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">ForEach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentPhysicalPath</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$PhysicalPaths</span><span style="color: #000000">)
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">For every *.dll file inside the path</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">ForEach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentDLL</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">ChildItem </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentPhysicalPath</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Recurse </span><span style="color: #008080">-File</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> </span><span style="color: #000000">*</span><span style="color: #000000">.dll)
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Processing $($CurrentDLL.Name) ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            try 
            { 
                </span><span style="color: #008000">#</span><span style="color: #008000">Loading the DLL</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$AssemblyLoaded</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> [System.Reflection.Assembly]</span><span style="color: #000000">::</span><span style="color: #000000">LoadFile(</span><span style="color: #800080">$CurrentDLL</span><span style="color: #000000">.FullName)
                </span><span style="color: #008000">#</span><span style="color: #008000">Getting the DLL attributes </span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$attributes</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$AssemblyLoaded</span><span style="color: #000000">.GetCustomAttributes([System.Diagnostics.DebuggableAttribute], </span><span style="color: #0000FF">$false</span><span style="color: #000000">)
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentDLL.FullName) was successfully loaded.</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #800080">$Details</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> 'Non debuggable DLL'
                </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITTrackingEnabled </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">)
                {
                    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITOptimizerDisabled </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">)
                    {
                        </span><span style="color: #800080">$Details</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> 'Non</span><span style="color: #000000">-</span><span style="color: #000000">optimized debug DLL'
                    }
                    </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> (</span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITTrackingEnabled </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)
                    {
                        </span><span style="color: #800080">$Details</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> 'Optimized debug DLL'
                    }
                }
                </span><span style="color: #0000FF">else</span><span style="color: #000000">
                {
                    </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITOptimizerDisabled </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">)
                    {
                        </span><span style="color: #800080">$Details</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> 'Non</span><span style="color: #000000">-</span><span style="color: #000000">optimized release DLL'
                    }
                    </span><span style="color: #0000FF">elseif</span><span style="color: #000000"> (</span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITTrackingEnabled </span><span style="color: #008080">-eq</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)
                    {
                        </span><span style="color: #800080">$Details</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> 'Optimized release DLL'
                    }
                }
                </span><span style="color: #008000">#</span><span style="color: #008000">Storing data into a PSObject</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$CurrentAssemblyObject</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName PSObject </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">@</span><span style="color: #000000">{
                    ServerName             </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Env:ComputerName</span><span style="color: #000000">
                    Name                   </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$AssemblyLoaded</span><span style="color: #000000">.GetName()
                    Location               </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$AssemblyLoaded</span><span style="color: #000000">.Location
                    IsJITOptimizerDisabled </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITOptimizerDisabled
                    IsJITTrackingEnabled   </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$attributes</span><span style="color: #000000">.IsJITTrackingEnabled
                    ImageRuntimeVersion    </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$AssemblyLoaded</span><span style="color: #000000">.ImageRuntimeVersion
                    IsValidDotNetAssembly  </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$true</span><span style="color: #000000">
                    Details                </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Details</span><span style="color: #000000">
                }
                </span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentAssemblyObject</span><span style="color: #000000">
            } 
            catch  
            {
                </span><span style="color: #008000">#</span><span style="color: #008000"> it is not a valid dotnet assembly </span><span style="color: #008000">
</span><span style="color: #000000">                Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">$($CurrentDLL.FullName) was not successfully loaded and is now tagged as a no valid .Net assembly</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                Write</span><span style="color: #000000">-</span><span style="color: #000000">Warning </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">[Exception] $_.Exception.Message</span><span style="color: #800000">&quot;</span><span style="color: #000000">
                </span><span style="color: #008000">#</span><span style="color: #008000">Storing data into a PSObject</span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$CurrentAssemblyObject</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName PSObject </span><span style="color: #000000">-</span><span style="color: #000000">Property </span><span style="color: #000000">@</span><span style="color: #000000">{
                    ServerName             </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Env:ComputerName</span><span style="color: #000000">
                    Name                   </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
                    Location               </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentDLL</span><span style="color: #000000">.FullName
                    IsJITOptimizerDisabled </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
                    IsJITTrackingEnabled   </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
                    ImageRuntimeVersion    </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
                    IsValidDotNetAssembly  </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">
                    Details                </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
                }
                </span><span style="color: #008000">#</span><span style="color: #008000">Storing the new created object into the collection                </span><span style="color: #008000">
</span><span style="color: #000000">                </span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentAssemblyObject</span><span style="color: #000000">
            } 
            </span><span style="color: #800080">$AssemblyLoaded</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$null</span><span style="color: #000000">
        }
    }
    </span><span style="color: #008000">#</span><span style="color: #008000">Returning the collection</span><span style="color: #008000">
</span><span style="color: #000000">    </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000">
}

Clear</span><span style="color: #000000">-</span><span style="color: #000000">Host
</span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$MyInvocation</span><span style="color: #000000">.MyCommand.Path
</span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent
</span><span style="color: #008000">#</span><span style="color: #008000"> Creating CSV file name based on the script full file path and by appending the timestamp at the end of the file name</span><span style="color: #008000">
</span><span style="color: #800080">$CSVFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">.replace((Get</span><span style="color: #000000">-</span><span style="color: #000000">Item </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">).Extension, '_'</span><span style="color: #000000">+$</span><span style="color: #000000">(Get</span><span style="color: #000000">-</span><span style="color: #000000">Date  </span><span style="color: #000000">-</span><span style="color: #000000">Format 'yyyyMMddTHHmmss')</span><span style="color: #000000">+</span><span style="color: #000000">'.csv')

</span><span style="color: #008000">#</span><span style="color: #008000"> Get assembly infos for a given web site in verbose mode</span><span style="color: #008000">
#</span><span style="color: #008000"> $DebuggableAttribute = Get-DebuggableAttribute -Site 'Default Web Site' -Verbose</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000"> Get assembly infos for a all hosted web sites</span><span style="color: #008000">
</span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">DebuggableAttribute

</span><span style="color: #008000">#</span><span style="color: #008000"> Get assembly infos for a all hosted web sites in verbose mode</span><span style="color: #008000">
#</span><span style="color: #008000"> $DebuggableAttribute = Get-DebuggableAttribute -Verbose</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000"> Get assembly infos for two given web sites in verbose mode</span><span style="color: #008000">
#</span><span style="color: #008000"> $DebuggableAttribute = Get-DebuggableAttribute -Site &quot;Default Web Site&quot;, &quot;www.contoso.com&quot; -Verbose</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000"> Get assembly infos for a given directory in verbose mode</span><span style="color: #008000">
#</span><span style="color: #008000"> $DebuggableAttribute = Get-DebuggableAttribute -Path &quot;C:\inetpub\wwwroot&quot; -Verbose</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000"> Get assembly infos for a given directory by using a pipeline in verbose mode</span><span style="color: #008000">
#</span><span style="color: #008000"> $DebuggableAttribute = Get-Item -Path &quot;C:\inetpub\wwwroot&quot; | Get-DebuggableAttribute -Verbose</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000">

</span><span style="color: #008000">#</span><span style="color: #008000"> Export the assembly to a default CSV file in the current directory</span><span style="color: #008000">
</span><span style="color: #800080">$DebuggableAttribute</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Export</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Force </span><span style="color: #000000">-</span><span style="color: #000000">NoTypeInformation
Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">Results are available in '$CSVFile'</span><span style="color: #800000">&quot;</span><span style="color: #000000">

    </span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<p>Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>Lister les bulletins de sécurité MS publiés entre deux dates / List MS security bulletins published during a date range</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/published-hotfix-list-powershell</link>
      <pubDate>Mon, 20 Mar 2017 11:14:17 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1865</guid>
      <description><![CDATA[Go to English version Lors de l’un de mes onsites suite à un IIS RaaS+, je me suis trouvé confronté...]]></description>
      <content:encoded><![CDATA[<p align="justify"><a href="#en-us" name="fr-fr">Go to English version</a></p> <p align="justify">Lors de l’un de mes onsites suite à un <a href="https://go.microsoft.com/fwlink/?LinkId=619117">IIS RaaS+</a>, je me suis trouvé confronté à un serveur qui n’avait pas été patché depuis le 02 Avril 2012 (!). Je ne m’attarderai pas ici sur les risques encourus et la difficulté (pour ne pas dire impossibilité)&nbsp; de la remédiation. Mais une question m’est venue à l’esprit : Combien de bulletins de sécurité Microsoft a publié depuis cette date ?</p> <p align="justify">En cherchant un peu j’ai vu que la page <a title="https://technet.microsoft.com/en-us/security/bulletins" href="https://technet.microsoft.com/en-us/security/bulletins">https://technet.microsoft.com/en-us/security/bulletins</a> me donnait les informations dont j’avais besoin. En poussant un peu plus loin l’analyse à l’aide d’une trace réseau j’ai vu que le résultat était transmis en <a href="https://www.json.org/">JSON</a> via une URI du type <a title="https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=1&amp;bulletinsPerPage=15&amp;locale=en-us" href="https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=1&amp;bulletinsPerPage=15&amp;locale=en-us">https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=1&amp;bulletinsPerPage=15&amp;locale=en-us</a>. Il ne restait plus qu’à manipuler les données JSON en PowerShell (nativement avec la cmdlet <a title="https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.utility/convertfrom-json" href="https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.utility/convertfrom-json">ConvertFrom-Json</a>). Je vous propose donc <a href="https://msdnshared.blob.core.windows.net/media/2017/03/Get-MSSecurityBulletin.ps1_.txt">ici</a> la version de mon <a href="https://msdnshared.blob.core.windows.net/media/2017/03/Get-MSSecurityBulletin.ps1_.txt">script</a>.</p> <p align="justify">&nbsp;</p> <p align="justify">Ce script est aussi disponible dans le TechNet Script Center : <a title="https://gallery.technet.microsoft.com/List-MS-security-bulletins-2b545eb2" href="https://gallery.technet.microsoft.com/List-MS-security-bulletins-2b545eb2">https://gallery.technet.microsoft.com/List-MS-security-bulletins-2b545eb2</a></p> <p><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/012717_1333_Fusionnerde1.png">  <p><a href="#fr-FR" name="en-us">Aller à la version française</a></p> <p align="justify">During one of my onsites following an <a href="https://go.microsoft.com/fwlink/?LinkId=619117">IIS RaaS+</a>, I faced to a server that had not been patched since April 2, 2012 (!). I will not dwell here on the risks involved and the difficulty (or the impossibility) of the remediation. But one question came to my mind: How many security bulletins Microsoft has published since that date?</p> <p align="justify"><br>Looking for a bit, I saw that the <a href="https://technet.microsoft.com/en-us/security/bulletins">https://technet.microsoft.com/en-us/security/bulletins</a> page gave me the information I needed. By doing a deeper the analysis with a network trace I saw that the result was transmitted in JSON via a URI of the type <a title="https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=1&amp;bulletinsPerPage=15&amp;locale=en-us" href="https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=1&amp;bulletinsPerPage=15&amp;locale=en-us">https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=1&amp;bulletinsPerPage=15&amp;locale=en-us</a>. . All that was left to do was to manipulate the JSON data in PowerShell (natively with the ConvertFrom-Json cmdlet). So <a href="https://msdnshared.blob.core.windows.net/media/2017/03/Get-MSSecurityBulletin.ps1_.txt">here</a> I propose the version of my <a href="https://msdnshared.blob.core.windows.net/media/2017/03/Get-MSSecurityBulletin.ps1_.txt">script</a>.</p> <p align="justify">&nbsp;</p> <p>The script file is also available at the TechNet Script Center repository, at: <a title="https://gallery.technet.microsoft.com/List-MS-security-bulletins-2b545eb2" href="https://gallery.technet.microsoft.com/List-MS-security-bulletins-2b545eb2">https://gallery.technet.microsoft.com/List-MS-security-bulletins-2b545eb2</a></p> <p>&nbsp;</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:950c3866-3c1c-446b-ba60-39422418e039" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 762px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000">requires -version 3</span><span style="color: #008000">
</span><span style="color: #0000FF">function</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">MSSecurityBulletin
{
    [CmdletBinding(PositionalBinding </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
        [alias('From', 'Start')]
        [datetime]</span><span style="color: #800080">$StartDate</span><span style="color: #000000">,
        
        [parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
        [alias('To', '</span><span style="color: #0000FF">End</span><span style="color: #000000">')]
        [datetime]</span><span style="color: #800080">$EndDate</span><span style="color: #000000">
        
        &lt;</span><span style="color: #008000">#
</span><span style="color: #000000">                </span><span style="color: #008000">#</span><span style="color: #008000">Code replaced by a dynamic parameter</span><span style="color: #008000">
</span><span style="color: #000000">                [parameter(Mandatory</span><span style="color: #000000">=</span><span style="color: #0000FF">$false</span><span style="color: #000000">)]
                [ValidateScript({New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName[System.Globalization.CultureInfo]</span><span style="color: #000000">::</span><span style="color: #000000">GetCultures([System.Globalization.CultureTypes]</span><span style="color: #000000">::</span><span style="color: #000000">AllCultures).Name </span><span style="color: #008080">-contains</span><span style="color: #000000"> </span><span style="color: #800080">$_</span><span style="color: #000000">})]
                [String]</span><span style="color: #800080">$Locale</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">&gt;</span><span style="color: #008000">
</span><span style="color: #000000">    )
    </span><span style="color: #008000">#</span><span style="color: #008000">Dynamic parameter to fill the list of known locales</span><span style="color: #008000">
</span><span style="color: #000000">    DynamicParam {
        </span><span style="color: #008000">#</span><span style="color: #008000"> Create the dictionary </span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$RuntimeParameterDictionary</span><span style="color: #000000">  </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.Management.Automation.RuntimeDefinedParameterDictionary

        </span><span style="color: #008000">#</span><span style="color: #008000"> Create the collection of attributes</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$AttributeCollection</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.Collections.ObjectModel.Collection[System.Attribute]

        </span><span style="color: #008000">#</span><span style="color: #008000"> Create and set the parameters' attributes</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$Attributes</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.Management.Automation.ParameterAttribute
        </span><span style="color: #800080">$Attributes</span><span style="color: #000000">.Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$false</span><span style="color: #000000">
        </span><span style="color: #800080">$Attributes</span><span style="color: #000000">.ParameterSetName </span><span style="color: #000000">=</span><span style="color: #000000"> 'Locale'
        
        </span><span style="color: #008000">#</span><span style="color: #008000"> Add the attributes to the attributes collection</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$AttributeCollection</span><span style="color: #000000">.Add(</span><span style="color: #800080">$Attributes</span><span style="color: #000000">)
        
        </span><span style="color: #008000">#</span><span style="color: #008000"> Generate and set the ValidateSet </span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$ValidateSet</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> [System.Globalization.CultureInfo]</span><span style="color: #000000">::</span><span style="color: #000000">GetCultures([System.Globalization.CultureTypes]</span><span style="color: #000000">::</span><span style="color: #000000">AllCultures).Name </span><span style="color: #000000">|</span><span style="color: #000000"> Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript {
            </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #008080">-match</span><span style="color: #000000"> '\w</span><span style="color: #000000">+-</span><span style="color: #000000">\w</span><span style="color: #000000">+</span><span style="color: #000000">'
        }
        </span><span style="color: #800080">$ValidateSetAttribute</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.Management.Automation.ValidateSetAttribute </span><span style="color: #000000">-</span><span style="color: #000000">ArgumentList (</span><span style="color: #800080">$ValidateSet</span><span style="color: #000000">)
        
        </span><span style="color: #008000">#</span><span style="color: #008000"> Add the ValidateSet to the attributes collection</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$AttributeCollection</span><span style="color: #000000">.Add(</span><span style="color: #800080">$ValidateSetAttribute</span><span style="color: #000000">)
        
        </span><span style="color: #008000">#</span><span style="color: #008000"> Create and return the dynamic parameter</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$Locale</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.Management.Automation.RuntimeDefinedParameter </span><span style="color: #000000">-</span><span style="color: #000000">ArgumentList ('Locale', [string], </span><span style="color: #800080">$AttributeCollection</span><span style="color: #000000">)        
        </span><span style="color: #800080">$RuntimeParameterDictionary</span><span style="color: #000000">.Add('Locale', </span><span style="color: #800080">$Locale</span><span style="color: #000000">)
        </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$RuntimeParameterDictionary</span><span style="color: #000000"> 
    }
    
    </span><span style="color: #0000FF">begin</span><span style="color: #000000">
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">Getting the dynamic paramater </span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$Locale</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$PSBoundParameters</span><span style="color: #000000">.Locale
    }
    </span><span style="color: #0000FF">process</span><span style="color: #000000">
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">If the results have more than one result page</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$HasMore</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">Offset for paging</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$Offset</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">Current result page</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$CurrentPage</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">Bulletin number per page</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$BulletinsPerPage</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">1000</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">Array storing the hotfix list</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">@</span><span style="color: #000000">()
        </span><span style="color: #008000">#</span><span style="color: #008000">If the locale parameter has nt been specified we will use the &quot;en-Us&quot; locale</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #000000">!</span><span style="color: #800080">$Locale</span><span style="color: #000000">)
        {
            </span><span style="color: #800080">$Locale</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> 'en</span><span style="color: #000000">-</span><span style="color: #000000">us'
        }
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$Locale : $($Locale)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        </span><span style="color: #800080">$CultureInfo</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">TypeName System.Globalization.CultureInfo </span><span style="color: #000000">-</span><span style="color: #000000">ArgumentList (</span><span style="color: #800080">$Locale</span><span style="color: #000000">)
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$CultureInfo : $CultureInfo</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        
        </span><span style="color: #0000FF">While</span><span style="color: #000000"> (</span><span style="color: #800080">$HasMore</span><span style="color: #000000">)
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">Getting the URI </span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Invoke</span><span style="color: #000000">-</span><span style="color: #000000">WebRequest </span><span style="color: #000000">-</span><span style="color: #000000">Uri </span><span style="color: #800000">&quot;</span><span style="color: #800000">https://technet.microsoft.com/security/bulletin/services/GetBulletins?searchText=&amp;sortField=0&amp;sortOrder=1&amp;currentPage=$CurrentPage&amp;bulletinsPerPage=$BulletinsPerPage&amp;locale=$Locale</span><span style="color: #800000">&quot;</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">UseBasicParsing
            </span><span style="color: #008000">#</span><span style="color: #008000">UTF-8 conversion</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> [system.Text.Encoding]</span><span style="color: #000000">::</span><span style="color: #000000">UTF8.GetString(</span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000">.RawContentStream.ToArray())
            </span><span style="color: #008000">#</span><span style="color: #008000">JSON -&gt; Object conversion</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> ConvertFrom</span><span style="color: #000000">-</span><span style="color: #000000">Json 
            </span><span style="color: #008000">#</span><span style="color: #008000">Getting only bulletin data</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000">.b
            </span><span style="color: #800080">$CurrentPage</span><span style="color: #000000">++</span><span style="color: #000000">
            </span><span style="color: #800080">$Offset</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000">.b.Count
            </span><span style="color: #800080">$HasMore</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Offset</span><span style="color: #000000"> </span><span style="color: #008080">-lt</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentBulletin</span><span style="color: #000000">.l
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$CurrentPage : $CurrentPage</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$Offset : $Offset</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$HasMore : $HasMore</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #008000">#</span><span style="color: #008000">if a start date has been specified we need to filter</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$StartDate</span><span style="color: #000000">)
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$StartDate : $StartDate</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript {
                ([datetime]</span><span style="color: #000000">::</span><span style="color: #000000">ParseExact(</span><span style="color: #800080">$_</span><span style="color: #000000">.d,</span><span style="color: #800080">$CultureInfo</span><span style="color: #000000">.DateTimeFormat.ShortDatePattern,[System.Globalization.CultureInfo]</span><span style="color: #000000">::</span><span style="color: #000000">InvariantCulture) </span><span style="color: #008080">-ge</span><span style="color: #000000"> </span><span style="color: #800080">$StartDate</span><span style="color: #000000">)
            }
        }
        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">Just to know the date of the first hotfix</span><span style="color: #008000">
</span><span style="color: #000000">            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Starting from $(($Bulletins | Select-Object -Property @{
                Name       = 'Date'
                Expression = { [datetime]::ParseExact($_.d,$CultureInfo.DateTimeFormat.ShortDatePattern,[System.Globalization.CultureInfo]::InvariantCulture) }
            } -Unique | Sort-Object -Property Date | Select-Object -First 1).Date)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #008000">#</span><span style="color: #008000">if an end date has been specified we need to filter</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #800080">$EndDate</span><span style="color: #000000">)
        {
            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">`$EndDate : $EndDate</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Where</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">FilterScript {
                ([datetime]</span><span style="color: #000000">::</span><span style="color: #000000">ParseExact(</span><span style="color: #800080">$_</span><span style="color: #000000">.d,</span><span style="color: #800080">$CultureInfo</span><span style="color: #000000">.DateTimeFormat.ShortDatePattern,[System.Globalization.CultureInfo]</span><span style="color: #000000">::</span><span style="color: #000000">InvariantCulture) </span><span style="color: #008080">-le</span><span style="color: #000000"> </span><span style="color: #800080">$EndDate</span><span style="color: #000000">)
            }
        }
        </span><span style="color: #0000FF">else</span><span style="color: #000000">
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">Just to know the date of the last hotfix</span><span style="color: #008000">
</span><span style="color: #000000">            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Ending to $(($Bulletins | Select-Object -Property @{
                Name       = 'Date'
                Expression = { [datetime]::ParseExact($_.d,$CultureInfo.DateTimeFormat.ShortDatePattern,[System.Globalization.CultureInfo]::InvariantCulture) }
            } -Unique | Sort-Object -Property Date -Descending | Select-Object -First 1).Date)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        }
        </span><span style="color: #0000FF">return</span><span style="color: #000000"> </span><span style="color: #800080">$Bulletins</span><span style="color: #000000">
    }
    </span><span style="color: #0000FF">end</span><span style="color: #000000">
    {
    }
}

Clear</span><span style="color: #000000">-</span><span style="color: #000000">Host
</span><span style="color: #008000">#</span><span style="color: #008000"> Getting the this script path</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$MyInvocation</span><span style="color: #000000">.MyCommand.Path
</span><span style="color: #008000">#</span><span style="color: #008000"> Getting the directory of this script</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Parent

</span><span style="color: #008000">#</span><span style="color: #008000"> Building a CSV file with the same base name that with script</span><span style="color: #008000">
</span><span style="color: #800080">$CSVFile</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">.replace((Get</span><span style="color: #000000">-</span><span style="color: #000000">Item </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentScript</span><span style="color: #000000">).Extension, '.csv')

</span><span style="color: #008000">#</span><span style="color: #008000">$Bulletins = Get-MSSecurityBulletin -StartDate '01/01/2008' -EndDate '12/31/2017' -Verbose </span><span style="color: #008000">
#</span><span style="color: #008000">$Bulletins = Get-MSSecurityBulletin -StartDate '04/02/2012' -Locale fr-fr -Verbose </span><span style="color: #008000">
#</span><span style="color: #008000">$Bulletins = Get-MSSecurityBulletin -StartDate '04/02/2012' -Verbose </span><span style="color: #008000">
#</span><span style="color: #008000">The From/Start/StartDate and To/End/Endate are expressed by using your regional settings</span><span style="color: #008000">
#</span><span style="color: #008000">In this example I'm configured in en-US but I want to get the results by using the fr-FR locale</span><span style="color: #008000">
</span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Get</span><span style="color: #000000">-</span><span style="color: #000000">MSSecurityBulletin </span><span style="color: #000000">-</span><span style="color: #000000">From '</span><span style="color: #000000">04</span><span style="color: #000000">/</span><span style="color: #000000">02</span><span style="color: #000000">/</span><span style="color: #000000">2012</span><span style="color: #000000">' </span><span style="color: #000000">-</span><span style="color: #000000">Locale fr</span><span style="color: #000000">-</span><span style="color: #000000">FR </span><span style="color: #000000">-</span><span style="color: #000000">Verbose 
</span><span style="color: #008000">#</span><span style="color: #008000">Displaying the number of hotfixes</span><span style="color: #008000">
</span><span style="color: #000000">Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">Security bulletins Count : $($Bulletins.Count)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">Exporting to a CSV file</span><span style="color: #008000">
</span><span style="color: #000000">Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">The security bulletins have been exported to $CSVFile</span><span style="color: #800000">&quot;</span><span style="color: #000000">
</span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Export</span><span style="color: #000000">-</span><span style="color: #000000">Csv </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CSVFile</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Force </span><span style="color: #000000">-</span><span style="color: #000000">NoTypeInformation </span><span style="color: #000000">-</span><span style="color: #000000">Encoding UTF8
</span><span style="color: #008000">#</span><span style="color: #008000">Security bulletins By Rating</span><span style="color: #008000">
</span><span style="color: #000000">Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object 'Security bulletins By Rating : '
</span><span style="color: #800080">$Bulletins</span><span style="color: #000000"> </span><span style="color: #000000">|</span><span style="color: #000000"> Group</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Rating </span><span style="color: #000000">-</span><span style="color: #000000">NoElement </span><span style="color: #000000">|</span><span style="color: #000000"> Format</span><span style="color: #000000">-</span><span style="color: #000000">Table</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<p>Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>IIS Configuration Auditing / Audit de Configuration IIS</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/iis-configuration-auditing</link>
      <pubDate>Wed, 15 Mar 2017 14:22:55 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1785</guid>
      <description><![CDATA[Go to English version L'article de blog...]]></description>
      <content:encoded><![CDATA[<p><a href="#en-us">Go to English version</a></p> <p>L'article de blog <a title="https://blogs.msdn.microsoft.com/webtopics/2010/03/19/iis-7-5-how-to-enable-iis-configuration-auditing/" href="https://blogs.msdn.microsoft.com/webtopics/2010/03/19/iis-7-5-how-to-enable-iis-configuration-auditing/">https://blogs.msdn.microsoft.com/webtopics/2010/03/19/iis-7-5-how-to-enable-iis-configuration-auditing/</a> explique en détails l'audit de Configuration IIS.&nbsp; J'aimerai ajouter quelques informations dans cet article.</p> <p>Je recommende d'augmenter la taille du log à Mo de manière à avoir un historique plus long des changements de configuration. Vous pouvez augmenter la taille en faisant un click droit sur le nom du log et en choisissant <strong>Propriétés</strong>. <b><img title="Application and Services Logs / Microsoft / Windows / IIS-Configuration/Operational event log " class="aligncenter" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;margin-left: auto;padding-right: 0px;border-top-width: 0px;margin-right: auto" border="0" alt="Application and Services Logs / Microsoft / Windows / IIS-Configuration/Operational event log " src="https://msdnshared.blob.core.windows.net/media/2017/03/image350.png" width="604" height="435"></b></p> <p align="justify">Pour rappel, l'audit de configuration IIS affiche l'élément de configuration qui a été modifié, l'utilisateur qui a initié la modification ainsi que les valeurs avant et après changement. Dans la capture d'écran ci-dessous l'administrateur local a changé la liaison du "Site Web par défaut" de "*: 80:" à "*: 81:" (Seul le numéro de port a changé) le 15 Mars 2017 à 06:15:48.</p> <p><img title="Event log entry" class="aligncenter" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="Event log entry" src="https://msdnshared.blob.core.windows.net/media/2017/03/image351.png" width="604" height="506"></p> <p align="justify">Remarque: Un seul changement peut générer plusieurs entrées de journal dans ce journal d'événements en fonction des sections de configuration.</p> <p>Si vous souhaitez activer l'audit de configuration et augmenter la taille du journal à 10 Mo via un script, je propose les deux possibilités suivantes:</p> <ul> <li>À partir d'une invite de commande élevée : </li></ul> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:3d694b0c-259e-4721-8b5e-2b367552622a" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 100px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">REM</span><span style="color: #008000"> To enable the configuration auditing and increase the log size to 10 MB.</span><span style="color: #008000">
</span><span style="color: #000000">
wevtutil </span><span style="color: #0000FF">Set</span><span style="color: #000000">-Log Microsoft-IIS-Configuration</span><span style="color: #000000">/</span><span style="color: #000000">Operational </span><span style="color: #000000">/</span><span style="color: #000000">e</span><span style="color: #800000">:true</span><span style="color: #000000"> </span><span style="color: #000000">/</span><span style="color: #000000">ms:</span><span style="color: #000000">10485760</span><span style="color: #000000">

</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<ul>
<li>From an elevated PowerShell prompt : </li></ul>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:b117f048-599f-4197-b89a-cf623849bb48" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 150px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000"> To enable the configuration auditing and increase the log size to 10 MB.</span><span style="color: #008000">
</span><span style="color: #800080">$logName</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">Microsoft-IIS-Configuration/Operational</span><span style="color: #800000">&quot;</span><span style="color: #000000">
</span><span style="color: #800080">$log</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object System.Diagnostics.Eventing.Reader.EventLogConfiguration </span><span style="color: #800080">$logName</span><span style="color: #000000">
</span><span style="color: #800080">$log</span><span style="color: #000000">.IsEnabled</span><span style="color: #000000">=</span><span style="color: #0000FF">$true</span><span style="color: #000000">
</span><span style="color: #800080">$log</span><span style="color: #000000">.MaximumSizeInBytes</span><span style="color: #000000">=</span><span style="color: #000000">10MB
</span><span style="color: #800080">$log</span><span style="color: #000000">.SaveChanges()
</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<p>&nbsp;</p>
<p align="justify"><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/012717_1333_Fusionnerde1.png"></p>
<p align="justify"><a href="#fr-FR">Aller à la version française</a></p>
<p>The <a title="https://blogs.msdn.microsoft.com/webtopics/2010/03/19/iis-7-5-how-to-enable-iis-configuration-auditing/" href="https://blogs.msdn.microsoft.com/webtopics/2010/03/19/iis-7-5-how-to-enable-iis-configuration-auditing/">https://blogs.msdn.microsoft.com/webtopics/2010/03/19/iis-7-5-how-to-enable-iis-configuration-auditing/</a> blog article explains in details the IIS Configuration Auditing.&nbsp; I would like add some details in this article.</p>
<p>I recommend to increase the log size to 10 MB to have a longer history about the configuration changes. You can increase the size by right-clicking on the log name in the Event Viewer and choose <strong>Properties</strong>.</p>
<p><b><img title="Application and Services Logs / Microsoft / Windows / IIS-Configuration/Operational event log " class="aligncenter" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="Application and Services Logs / Microsoft / Windows / IIS-Configuration/Operational event log " src="https://msdnshared.blob.core.windows.net/media/2017/03/image350.png" width="604" height="435"></b></p>
<p><b></b></p>
<p>As a reminder, the IIS configuration auditing displays the configuration element which was changed, the user who initiated the change, and the original and the new value of the element. In the screenshot below the local administrator has changed the binding of the “Default Web Site” from “*:80:” to “*:81:” (Only the port number has changed”) the March 15th 2017 at 06:15:48 AM.</p>
<p><img title="Event log entry" class="aligncenter" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;float: none;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="Event log entry" src="https://msdnshared.blob.core.windows.net/media/2017/03/image351.png" width="604" height="506"></p>
<p>Note : A single change can generate multiple log entries in this dedicated event log depending of the configuration sections to commit.</p>
<p>&nbsp;</p>
<p>If you want to enable the configuration auditing and increase the log size to 10 MB via a script I propose the two following possibilities :</p>
<ul>
<li>From an elevated command prompt: </li></ul>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:730f48e3-d634-4f60-a9c7-2dddc7b6a6d6" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 100px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">REM</span><span style="color: #008000"> To enable the configuration auditing and increase the log size to 10 MB.</span><span style="color: #008000">
</span><span style="color: #000000">
wevtutil </span><span style="color: #0000FF">Set</span><span style="color: #000000">-Log Microsoft-IIS-Configuration</span><span style="color: #000000">/</span><span style="color: #000000">Operational </span><span style="color: #000000">/</span><span style="color: #000000">e</span><span style="color: #800000">:true</span><span style="color: #000000"> </span><span style="color: #000000">/</span><span style="color: #000000">ms:</span><span style="color: #000000">10485760</span><span style="color: #000000">

</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<ul>
<li>From an elevated PowerShell prompt: </li></ul>
<div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:18703894-8e35-40e4-85c2-96f066df382c" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 822px;height: 150px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000"> To enable the configuration auditing and increase the log size to 10 MB.</span><span style="color: #008000">
</span><span style="color: #800080">$logName</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">Microsoft-IIS-Configuration/Operational</span><span style="color: #800000">&quot;</span><span style="color: #000000">
</span><span style="color: #800080">$log</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object System.Diagnostics.Eventing.Reader.EventLogConfiguration </span><span style="color: #800080">$logName</span><span style="color: #000000">
</span><span style="color: #800080">$log</span><span style="color: #000000">.IsEnabled</span><span style="color: #000000">=</span><span style="color: #0000FF">$true</span><span style="color: #000000">
</span><span style="color: #800080">$log</span><span style="color: #000000">.MaximumSizeInBytes</span><span style="color: #000000">=</span><span style="color: #000000">10MB
</span><span style="color: #800080">$log</span><span style="color: #000000">.SaveChanges()
</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<p>Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>Fusionner des présentations Powerpoint dans un fichier avec Powershell / Merge multiple PowerPoint files into one file with Powershell</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/merge-powerpoint-files-powershell</link>
      <pubDate>Thu, 26 Jan 2017 14:44:08 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1275</guid>
      <description><![CDATA[Go to English version [MAJ : 09/03/2017] La formation représente une partie non négligeable de mon...]]></description>
      <content:encoded><![CDATA[<p align="justify"><a href="#en-us" name="fr-fr">Go to English version</a></p> <p align="justify">[MAJ : 09/03/2017] La formation représente une partie non négligeable de mon travail. En fonction des sujets de formation, il se peut que le support soit juste une présentation PowerPoint couvrant tous les modules et les leçons attenantes (un module est découpé en plusieurs leçons) ou alors&nbsp; soit constitué d'un ensemble de présentations PowerPoint&nbsp; (par exemple un fichier par leçon) comme c'est le cas pour la formation <a href="https://download.microsoft.com/documents/France/services/2013/workshop/ENWorkshop-IIS-Administration-Troubleshooting-and-Best-Practices.pdf">Workshop Plus : IIS Troubleshooting and Best Practices</a></p> <p align="justify"><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/WSIISATBP1.png"></p> <p align="justify">D'un point de vue strictement personnel, j'avoue que je préfère n'ouvrir qu'un seul fichier plutôt que de jongler entre diverses présentations. Pour cela j'ai donc créer le script suivant (le code ainsi que des exemples de présentations sont disponibles <a href="https://msdnshared.blob.core.windows.net/media/2017/03/Merge-PowerPointPresentation.zip">ici</a>) qui rassemble toutes les présentations en un seul fichier (en respectant le thème de chaque présentation).</p> <p align="justify">Ce script est aussi disponible dans le TechNet Script Center : <a title="https://gallery.technet.microsoft.com/scriptcenter/Merge-multiple-PowerPoint-49139f2c" href="https://gallery.technet.microsoft.com/scriptcenter/Merge-multiple-PowerPoint-49139f2c">https://gallery.technet.microsoft.com/scriptcenter/Merge-multiple-PowerPoint-49139f2c</a></p> <p align="justify"><img alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/012717_1333_Fusionnerde1.png"></p> <p align="justify"><a href="#fr-FR" name="en-us">Aller à la version française</a></p> <p align="justify">[Updated 03/09/2017] Training is a significant part of my work. Depending on the training topics, the support may be just only a PowerPoint presentation covering all the modules and the related lessons (a module is divided into several lessons) or a set of PowerPoint presentations (eg. 1 File per lesson) like for the <a href="https://download.microsoft.com/documents/France/services/2013/workshop/ENWorkshop-IIS-Administration-Troubleshooting-and-Best-Practices.pdf">Workshop Plus : IIS Troubleshooting and Best Practices</a>.</p> <p align="justify"><a href="https://msdnshared.blob.core.windows.net/media/2017/01/WSIISATBP1.png"><img border="0" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/01/WSIISATBP1.png"></a></p> <p align="justify">From a strictly personal point of view, I confess that I prefer to open only one file rather than juggling various presentations. To do this, I create the following script (the code as well as examples of presentations are available <a href="https://msdnshared.blob.core.windows.net/media/2017/03/Merge-PowerPointPresentation.zip">here</a>) that gathers all the presentations in a single file (respecting the theme of each presentation).</p> <p align="justify">The script file is also available at the TechNet Script Center repository, at: <a title="https://gallery.technet.microsoft.com/scriptcenter/Merge-multiple-PowerPoint-49139f2c" href="https://gallery.technet.microsoft.com/scriptcenter/Merge-multiple-PowerPoint-49139f2c">https://gallery.technet.microsoft.com/scriptcenter/Merge-multiple-PowerPoint-49139f2c</a></p> <p align="justify">&nbsp;</p> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:2cb720d2-515a-4436-b289-c281ce7b49ba" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 782px;height: 782px;background-color:White;overflow: scroll"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000">region function definitions</span><span style="color: #008000">
#</span><span style="color: #008000">Function for releasing a COM object</span><span style="color: #008000">
</span><span style="color: #0000FF">Function</span><span style="color: #000000"> Remove</span><span style="color: #000000">-</span><span style="color: #000000">Ref 
{
    </span><span style="color: #0000FF">param</span><span style="color: #000000">
    (
        [Object]
        </span><span style="color: #800080">$ref</span><span style="color: #000000">
    )

    </span><span style="color: #800080">$null</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Remove</span><span style="color: #000000">-</span><span style="color: #000000">Variable </span><span style="color: #000000">-</span><span style="color: #000000">Name </span><span style="color: #800080">$ref</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">ErrorAction SilentlyContinue
    </span><span style="color: #0000FF">while</span><span style="color: #000000"> ([System.Runtime.InteropServices.Marshal]</span><span style="color: #000000">::</span><span style="color: #000000">ReleaseComObject([System.__ComObject]</span><span style="color: #800080">$ref</span><span style="color: #000000">) </span><span style="color: #008080">-gt</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">) 
    {

    }
    [System.GC]</span><span style="color: #000000">::</span><span style="color: #000000">Collect()
    [System.GC]</span><span style="color: #000000">::</span><span style="color: #000000">WaitForPendingFinalizers() 
}


</span><span style="color: #008000">#</span><span style="color: #008000">Main function for merging PowerPoint presentations</span><span style="color: #008000">
</span><span style="color: #0000FF">Function</span><span style="color: #000000"> Merge</span><span style="color: #000000">-</span><span style="color: #000000">PowerPointPresentation 
{
    &lt;</span><span style="color: #008000">#
</span><span style="color: #000000">            .SYNOPSIS
            Merge multiple PowerPoint presentation files to one file

            .DESCRIPTION
            Merge multiple PowerPoint presentation files to one file

            .PARAMETER Source
            The PowerPoint presentation files to merge specified by its full name

            .PARAMETER Destination
            The target PowerPoint presentation file specified by its full name

            .PARAMETER Open
            A </span><span style="color: #0000FF">switch</span><span style="color: #000000"> to specify </span><span style="color: #0000FF">if</span><span style="color: #000000"> we keep the PowerPoint application opened after the processing

            .EXAMPLE
            </span><span style="color: #800080">$Get</span><span style="color: #000000">-</span><span style="color: #000000">ChildItem </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #0000FF">filter</span><span style="color: #000000"> </span><span style="color: #000000">*</span><span style="color: #000000">.pptx </span><span style="color: #000000">|</span><span style="color: #000000"> Sort</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Name </span><span style="color: #000000">|</span><span style="color: #000000"> Merge</span><span style="color: #000000">-</span><span style="color: #000000">PowerPointPresentation </span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Open
            Will merge all the PowerPoint files into the current directory into one single Powerpoint file by using a timestamped filename (ie. yyyyMMddTHHmmss.pptx like 20170126T091011.pptx) 
            The output will be verbose
            The PowerPoint application won't be left after the processing

            .EXAMPLE
            </span><span style="color: #800080">$Presentations</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\0.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\1.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\2.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\3.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\4.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\5.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\6.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\7.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\8.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">,</span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\9.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            Merge</span><span style="color: #000000">-</span><span style="color: #000000">PowerPointPresentation </span><span style="color: #000000">-</span><span style="color: #000000">Source </span><span style="color: #800080">$Presentations</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Destination C:\Temp\MergedPresentation.pptx
            Will merge all the specified PowerPoint files into into the C:\Temp\MergedPresentation.pptx Powerpoint file
    </span><span style="color: #008000">#</span><span style="color: #008000">&gt;</span><span style="color: #008000">
</span><span style="color: #000000">    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        </span><span style="color: #008000">#</span><span style="color: #008000">The collection of the powerpoint files to merge</span><span style="color: #008000">
</span><span style="color: #000000">        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">,ValueFromPipeline </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">,ValueFromPipelineByPropertyName </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$True</span><span style="color: #000000">)]
        [ValidateScript({
                    (Test</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PathType Leaf) </span><span style="color: #008080">-and</span><span style="color: #000000"> (</span><span style="color: #800080">$_</span><span style="color: #000000"> </span><span style="color: #008080">-match</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">\.ppt(x{0,1})$</span><span style="color: #800000">&quot;</span><span style="color: #000000">)
        })]
        [alias('FilePath', 'Path', 'FullName')]
        [string[]]</span><span style="color: #800080">$Source</span><span style="color: #000000">,

        </span><span style="color: #008000">#</span><span style="color: #008000">The path of the generated powerpoint file</span><span style="color: #008000">
</span><span style="color: #000000">        [Parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)]
        [ValidateNotNullOrEmpty()]
        [alias('OutputFile')]
        [string]</span><span style="color: #800080">$Destination</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">$</span><span style="color: #000000">(Join</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">$</span><span style="color: #000000">([Environment]</span><span style="color: #000000">::</span><span style="color: #000000">GetFolderPath('MyDocuments')) </span><span style="color: #000000">-</span><span style="color: #000000">ChildPath </span><span style="color: #000000">$</span><span style="color: #000000">('{</span><span style="color: #000000">0</span><span style="color: #000000">:yyyyMMddTHHmmss}' </span><span style="color: #008080">-f</span><span style="color: #000000"> (Get</span><span style="color: #000000">-</span><span style="color: #000000">Date))),

        </span><span style="color: #008000">#</span><span style="color: #008000">To keep open the generated Powerpoint presentation</span><span style="color: #008000">
</span><span style="color: #000000">        [parameter(Mandatory </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000FF">$False</span><span style="color: #000000">)]
        [</span><span style="color: #0000FF">switch</span><span style="color: #000000">]</span><span style="color: #800080">$Open</span><span style="color: #000000">
    )
    </span><span style="color: #0000FF">begin</span><span style="color: #000000">
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">Opening the PowerPoint application once</span><span style="color: #008000">
</span><span style="color: #000000">        Add</span><span style="color: #000000">-</span><span style="color: #000000">Type </span><span style="color: #000000">-</span><span style="color: #000000">AssemblyName Microsoft.Office.Interop.PowerPoint
        </span><span style="color: #800080">$Powerpoint</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> New</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">ComObject Powerpoint.Application
        </span><span style="color: #008000">#</span><span style="color: #008000">Creating a new PowerPoint presentation</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$Powerpoint</span><span style="color: #000000">.Presentations.Add(</span><span style="color: #0000FF">$True</span><span style="color: #000000">)
        </span><span style="color: #008000">#</span><span style="color: #008000"> Adding an empty slide : mandatory</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$null</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.Slides.Add(</span><span style="color: #000000">1</span><span style="color: #000000">, [Microsoft.Office.Interop.PowerPoint.PpSlideLayout]</span><span style="color: #000000">::</span><span style="color: #000000">ppLayoutBlank)
        </span><span style="color: #800080">$SlidesNb</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">
    }
    </span><span style="color: #0000FF">process</span><span style="color: #000000">
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">For all files passed as argument outside a pipeline context</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> (</span><span style="color: #800080">$CurrentSource</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$Source</span><span style="color: #000000">)
        {
            </span><span style="color: #008000">#</span><span style="color: #008000">Getting the base name of the processed presentation</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$CurrentPresentationName</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> (Get</span><span style="color: #000000">-</span><span style="color: #000000">Item </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentSource</span><span style="color: #000000">).BaseName
            
            </span><span style="color: #008000">#</span><span style="color: #008000">Inserting the slide of the current presentationt o the new one</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$InsertedSlidesNb</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.Slides.InsertFromfile(</span><span style="color: #800080">$CurrentSource</span><span style="color: #000000">, </span><span style="color: #800080">$SlidesNb</span><span style="color: #000000">)
            
            </span><span style="color: #008000">#</span><span style="color: #008000">Applying the original template</span><span style="color: #008000">
</span><span style="color: #000000">            </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.Slides.Range((</span><span style="color: #800080">$SlidesNb</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">)..(</span><span style="color: #800080">$SlidesNb</span><span style="color: #000000">+</span><span style="color: #800080">$InsertedSlidesNb</span><span style="color: #000000">)).ApplyTemplate(</span><span style="color: #800080">$CurrentSource</span><span style="color: #000000">)

            </span><span style="color: #008000">#</span><span style="color: #008000">Adding a new section for the inserted context with the name of the processed presentation</span><span style="color: #008000">
</span><span style="color: #000000">            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Adding the section $CurrentPresentationName before Slide $($SlidesNb+1)...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$null</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.SectionProperties.AddBeforeSlide(</span><span style="color: #800080">$SlidesNb</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">, </span><span style="color: #800080">$CurrentPresentationName</span><span style="color: #000000">)

            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message </span><span style="color: #800000">&quot;</span><span style="color: #800000">Processed file $CurrentSource by inserting $InsertedSlidesNb slides ($($SlidesNb+1) ==&gt; $($SlidesNb+$InsertedSlidesNb)) ...</span><span style="color: #800000">&quot;</span><span style="color: #000000">
            </span><span style="color: #800080">$SlidesNb</span><span style="color: #000000"> </span><span style="color: #000000">+=</span><span style="color: #000000"> </span><span style="color: #800080">$InsertedSlidesNb</span><span style="color: #000000">
        }
    }
    </span><span style="color: #0000FF">end</span><span style="color: #000000">
    {
        </span><span style="color: #008000">#</span><span style="color: #008000">Deleting the useless empty slide (added at the beginning)</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.Slides.Range(</span><span style="color: #800080">$SlidesNb</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">).Delete()
        </span><span style="color: #008000">#</span><span style="color: #008000">Saving the final file</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.SaveAs(</span><span style="color: #800080">$Destination</span><span style="color: #000000">)
        Write</span><span style="color: #000000">-</span><span style="color: #000000">Host </span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #800000">&quot;</span><span style="color: #800000">The new presentation was saved in $($NewPresentation.FullName) ($SlidesNb slides)</span><span style="color: #800000">&quot;</span><span style="color: #000000">
        </span><span style="color: #008000">#</span><span style="color: #008000">If the -Open switch is specified we keep the PowerPoint application opened</span><span style="color: #008000">
</span><span style="color: #000000">        </span><span style="color: #0000FF">if</span><span style="color: #000000"> (</span><span style="color: #000000">!</span><span style="color: #800080">$Open</span><span style="color: #000000">)
        {
            </span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">.Close()
            </span><span style="color: #008000">#</span><span style="color: #008000">$Powerpoint.Quit() | Out-Null</span><span style="color: #008000">
</span><span style="color: #000000">            Write</span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Message 'Releasing PowerPoint ...'
            Remove</span><span style="color: #000000">-</span><span style="color: #000000">Ref </span><span style="color: #000000">-</span><span style="color: #000000">ref (</span><span style="color: #800080">$NewPresentation</span><span style="color: #000000">)
            Remove</span><span style="color: #000000">-</span><span style="color: #000000">Ref </span><span style="color: #000000">-</span><span style="color: #000000">ref (</span><span style="color: #800080">$Powerpoint</span><span style="color: #000000">)
        }
    }
}
</span><span style="color: #008000">#</span><span style="color: #008000">endregion</span><span style="color: #008000">
</span><span style="color: #000000">
Clear</span><span style="color: #000000">-</span><span style="color: #000000">Host
</span><span style="color: #008000">#</span><span style="color: #008000">Getting the current directory (where this script file resides)</span><span style="color: #008000">
</span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> Split</span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$MyInvocation</span><span style="color: #000000">.MyCommand.Path
</span><span style="color: #008000">#</span><span style="color: #008000">Loading the PowerPoint assembly</span><span style="color: #008000">
</span><span style="color: #000000">
</span><span style="color: #008000">#</span><span style="color: #008000">Example 1 : Processing all the PowerPoint presentation in current directory in the alphabetical order</span><span style="color: #008000">
</span><span style="color: #000000">Get</span><span style="color: #000000">-</span><span style="color: #000000">ChildItem </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #0000FF">Filter</span><span style="color: #000000"> </span><span style="color: #000000">*</span><span style="color: #000000">.pptx </span><span style="color: #000000">|</span><span style="color: #000000">
Sort</span><span style="color: #000000">-</span><span style="color: #000000">Object </span><span style="color: #000000">-</span><span style="color: #000000">Property Name </span><span style="color: #000000">|</span><span style="color: #000000">
Merge</span><span style="color: #000000">-</span><span style="color: #000000">PowerPointPresentation </span><span style="color: #000000">-</span><span style="color: #000000">Verbose </span><span style="color: #000000">-</span><span style="color: #000000">Open

</span><span style="color: #008000">#</span><span style="color: #008000">Example 2 : Processing a list of some PowerPoint presentations specified by their absolute path</span><span style="color: #008000">
</span><span style="color: #800080">$Presentations</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\0.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\1.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\2.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\3.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\4.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\5.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\6.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\7.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\8.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">, </span><span style="color: #800000">&quot;</span><span style="color: #800000">$CurrentDir\9.pptx</span><span style="color: #800000">&quot;</span><span style="color: #000000">
Merge</span><span style="color: #000000">-</span><span style="color: #000000">PowerPointPresentation </span><span style="color: #000000">-</span><span style="color: #000000">Source </span><span style="color: #800080">$Presentations</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Destination </span><span style="color: #800080">$CurrentDir</span><span style="color: #000000">\all.pptx </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div>
<p align="justify">Laurent.</p>]]></content:encoded>
    </item>
    <item>
      <title>Modification de la date d'écriture d'un fichier sur un ensemble de serveurs en parallèle / Changing the last write time of a file on a set of servers using a parallel processing</title>
      <link>https://docs.microsoft.com/archive/blogs/lavanack/workflow-parallel-lastwritetime</link>
      <pubDate>Thu, 15 Dec 2016 13:33:20 GMT</pubDate>
      <dc:creator><![CDATA[Laurent VAN ACKER]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lavanack/?p=1165</guid>
      <description><![CDATA[Go to English version  Lors d'une de mes sessions de formation PowerShell, un client m'a demandé la...]]></description>
      <content:encoded><![CDATA[<div id="fr-FR" align="justify"><a href="#en-US">Go to English version</a></div> <div align="justify"></div> <div align="justify">Lors d'une de mes sessions de formation PowerShell, un client m'a demandé la possibilité de modifier la date de dernière écriture d'un fichier sur un ensemble de serveurs (pour des problématiques de backup) en parallèle (pour des raisons de performance). Les workflows PowerShell permettent justement d'effectuer des tâches en parallèle. Après plusieurs tentatives de scripts infructueuses, j'ai abouti au script suivant (assez simple au prime abord - Le code source est disponible <a href="https://msdnshared.blob.core.windows.net/media/2017/02/Set-LastWriteTime-WF.ps1_.txt" target="_blank">ici</a>) :</div> <p align="justify">&nbsp;</p> <p align="justify"> <div align="justify"> <hr> </div> <p align="justify"> <div id="en-US" align="justify"><a href="#fr-FR">Aller à la version française</a></div> <div align="justify"></div> <div align="justify">In one of my PowerShell training sessions, a client asked me to change the last write time of a given file on a set of servers (for backup reasons) in parallel way (for performance reasons ). PowerShell workflows allow you to do that. After several attempts of unsuccessful scripts, I wrote to the following script (simple enough at first glance - The source code is available <a href="https://msdnshared.blob.core.windows.net/media/2017/02/Set-LastWriteTime-WF.ps1_.txt" target="_blank">here</a>) :</div> <p align="justify">&nbsp;</p> <div align="justify"> <div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:ac68a8c1-fdf6-4e04-89fb-768cde41fffa" class="wlWriterEditableSmartContent" style="float: none;padding-bottom: 0px;padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px"><pre style="width: 802px;height: 427px;background-color:White;overflow: auto"><div><!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
https://www.CodeHighlighter.com/

--><span style="color: #008000">#</span><span style="color: #008000">requires -version 3</span><span style="color: #008000">
</span><span style="color: #000000">
workflow Set</span><span style="color: #000000">-</span><span style="color: #000000">LastWriteTime</span><span style="color: #000000">-</span><span style="color: #000000">WF
{
    [CmdletBinding()]
    </span><span style="color: #0000FF">Param</span><span style="color: #000000">(
        [String[]]</span><span style="color: #800080">$Computers</span><span style="color: #000000">,
        [String]</span><span style="color: #800080">$FullName</span><span style="color: #000000">,
        [Datetime]</span><span style="color: #800080">$LastWriteTime</span><span style="color: #000000">
    )

    </span><span style="color: #0000FF">foreach</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">parallel(</span><span style="color: #800080">$Computer</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #800080">$Computers</span><span style="color: #000000">)
    {
        Set</span><span style="color: #000000">-</span><span style="color: #000000">ItemProperty </span><span style="color: #000000">-</span><span style="color: #000000">Path </span><span style="color: #800080">$FullName</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">Name LastWriteTime </span><span style="color: #000000">-</span><span style="color: #000000">Value </span><span style="color: #800080">$LastWriteTime</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">PSComputerName </span><span style="color: #800080">$Computer</span><span style="color: #000000">
    }
} 

Clear</span><span style="color: #000000">-</span><span style="color: #000000">Host
</span><span style="color: #800080">$Computers</span><span style="color: #000000"> </span><span style="color: #000000">=</span><span style="color: #000000"> '2012R2</span><span style="color: #000000">-</span><span style="color: #000000">MS', '2012R2</span><span style="color: #000000">-</span><span style="color: #000000">DC', 'WIN8</span><span style="color: #000000">-</span><span style="color: #000000">WS'
Set</span><span style="color: #000000">-</span><span style="color: #000000">LastWriteTime</span><span style="color: #000000">-</span><span style="color: #000000">WF </span><span style="color: #000000">-</span><span style="color: #000000">Computers </span><span style="color: #800080">$Computers</span><span style="color: #000000"> </span><span style="color: #000000">-</span><span style="color: #000000">FullName 'C:\Windows\WindowsUpdate.log' </span><span style="color: #000000">-</span><span style="color: #000000">LastWriteTime </span><span style="color: #000000">$</span><span style="color: #000000">(Get</span><span style="color: #000000">-</span><span style="color: #000000">Date) </span><span style="color: #000000">-</span><span style="color: #000000">Verbose
</span></div></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  https://dunnhq.com --></div></div>
<div align="justify">&nbsp;</div>
<div align="justify">Laurent.</div>]]></content:encoded>
    </item>
  </channel>
</rss>