PI Services

Le blog des collaborateurs de PI Services

Utilisation de WinSCP .Net Assembly et COM library

Dans cet article nous allons apprendre l'utilisation et l'importance de WinSCP .Net Assembly et COM library.

Introduction

Nous sommes habitué à utiliser le client WinSCP pour se connecter sur un serveur SFTP,SCP ou FTP. Il existe même un module très basique appelé WinSCP.com pour envoyer ou réceptionner des données via un fichier *.bat. Cependant, beaucoup d'entre nous ignore l'existance de WinSCP .Net Assembly et COM library qui offre la possibilité de manipuler des fichiers à distance depuis un environnement supportant .NET, par exemple C#,VB. Net, PowerShell,SSIS et même depuis les sites MS AZURE.

WinSCP .Net assembly et COM library offrent beaucoup de possibilité en termes de ligne de commandes pour automatiser l'envoi et la réception de fichier depuis un serveur FTP,SCP ou sFTP. 

Prérequis

Télécharger le fichier zip indiqué ci-dessous et décompresser le.

Exemple de programmation en PoSH

  • L'initialisation d'une connexion sur un serveur
try
{
    # appel WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"
 
    # paramètre de connexion
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = "example.com"
        UserName = "user"
        Password = "mypassword"
        SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
    }
 
    $session = New-Object WinSCP.Session
 
    try
    {
        # initialiser la connexion
        $session.Open($sessionOptions)
 
        Write-Host "You are now connected!!!"
    }
    finally
    {
        # Déconnecter et nettoyer
        $session.Dispose()
    }
 
    exit 0
}
catch [Exception]
{
    # Exception
    Write-Host ("Error: {0}" -f $_.Exception.Message)
    exit 1
}

Pour se connecter sur un serveur sFTP avec une clé privée et sans login et mot de passe, remplacer la ligne :

Password = "mypassword"
        SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"

par 

SshPrivateKeyPath = "chemin vers la clé privée"
        GiveUpSecurityAndAcceptAnySshHostKey = "true"
  • Télécharger un fichier 

Pour télécharger un fichier avec son nom, utiliser la ligne de commande ci-dessous:

$session.GetFiles($session.EscapeFileMask(<chemin complet du fichier>), <destination locale>).Check()
  • Pour uploader un fichier 
 # Upload files
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
 
        $transferResult = $session.PutFiles("d:\toupload\*", "/home/user/", $False, $transferOptions)

 

Pour avoir plus d'informations sur les classes existantes : https://winscp.net/eng/docs/library

 

Windows Serveur : Extraction des configurations DHCP

Attention ne s'applique qu'à partir de  Windows Server 2012 et Windows 8.

Comment connaitre rapidement les configurations DHCP du domaine? Eh bien, avec Powershell.

 

Lister les serveurs DHCP du domaine:

Pour lister les serveurs DHCP du domaine vous pouvez utiliser la commande:

Get-DhcpServerInDC

Cette commande vous retournera par défaut :

  1. l'adresse IP du ou des serveurs
  2. Le nom Dns du ou des serveurs

Lister les scopes DHCP:

Pour lister les scopes DHCP et leurs configurations vous pouvez utiliser la commande suivante:

Get-DhcpServerv4Scope

Par défaut cette commande vous retournera les éléments suivants:

  1. L'étendue
  2. Le masque sous réseau
  3. Le Nom du scope
  4. L'état (Actif ou Inactif)
  5. L'adresse IP de début
  6. L'adresse IP de fin
  7. La durée des baux

Bien sur il est possible de récupérer d'autres informations si vous le souhaitez.

Obtenir des informations sur les scopes:

Pour obtenir des informations sur l'utilisation des scopes vous pouvez utiliser la commande suivante:

 

Get-DhcpServerv4ScopeStatistics

 

Cette commande retourne :

  1. L'étendue
  2. Le nombre d'adresses libres
  3. Le nombre d'adresses utilisées
  4. Le pourcentage d'utilisation
  5. Le nombre d'adresses réservées
  6. Le nombre d'adresses en attente de distribution (normalement 0)
  7. Le nom de l'étendue globale

Peut on scripter tout ça?

Il vous est possible d'exécuter toutes ces commandes à distance via "invoke-command" ou "Enter-PSSession" sauf la commande "Get-DhcpServerInDC".

Donc il est possible de scripter toutes ces commandes et avoir une belle extraction sans se connecter au serveur à condition de déjà posséder la résultante de  "Get-DhcpServerInDC".

Sinon vous pouvez aussi exécuter un script depuis le serveur, mais bon ça, c'est quand même moins "Secure".

Plus d'informations sur : 

https://technet.microsoft.com/library/jj590751(v=wps.620).aspx

 

 

Fonction de collecte de perf via Scom

Bien que la méthode en passant par une requête SQL soit plus rapide, il peut être utile de pouvoir collecter des données de performance spécifique via le sdk Scom.

La fonction suivants prend en paramètre  les données de connexion ($managementServer,$user,$passwd) et les critère de compteurs de performance qui peuvent être regroupé dans le paramètre $criteria, ainsi que le paramètre $HourOffset qui permet de préciser une fenêtre de collecte.

! Attention: Plus ce paramètre en heure est important, plus le nombre de sample renvoyé est important.

 

    # Fonction de recuperation de compteur de performance dans la base OperationsManager       Function GetPerfValueFromScomv2($managementServer,$user,$passwd,$criteria,$monitoringClassId = $null,$monitoringObjectName = $null,$monitoringObjectDisplayName = $null,$objectName = $null,$counterName = $null,$instanceName = $null,$HourOffset,$startTime = (Get-Date).AddHours(-$HourWindow),$endTime = (Get-Date))     {   #Fonction d'ajout de critere a la requete function Add-Criteria() {     param($criteria,$clause)           if ($criteria -ne $null)         {$criteria += " AND $clause"}     else         {$criteria = $clause}               return($criteria) }     #Import du module Scom import-module OperationsManager   #Connexion au management server     $mgConn = New-Object Microsoft.EnterpriseManagement.ManagementGroupConnectionSettings($managementServer) $mgConn.UserName = $user $mgConn.Password = $passwd $mg = New-Object Microsoft.EnterpriseManagement.ManagementGroup($mgConn)     if ($criteria -eq $null) {     if ($monitoringClassId -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "MonitoringClassId = '{$monitoringClassId}'" }     if ($monitoringObjectDisplayName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "MonitoringObjectDisplayName = '$monitoringObjectDisplayName'" }     if ($monitoringObjectName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "MonitoringObjectName = '$monitoringObjectName'" }     if ($objectName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "ObjectName = '$objectName'" }     if ($counterName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "CounterName = '$counterName'" }     if ($instanceName -ne $null) { $criteria = Add-Criteria -criteria $criteria -clause "InstanceName = '$instanceName'" } }   #Creation du reader $reader = $mg.GetMonitoringPerformanceDataReader($criteria) while ($reader.Read()) {     #Creation de l'objet de performance     $perfData = $reader.GetMonitoringPerformanceData()     $valueReader = $perfData.GetValueReader($startTime,$endTime)       #Renvoi des valeurs     while ($valueReader.Read())     {         $perfValue = $valueReader.GetMonitoringPerformanceDataValue()         $perfValue     } }   }        

Quest RUM : Script de désinstallation des agents

Bonjour à tous !

Lors d'une migration effectuée à l'aide du produit Quest Migration Manager for Active Directory, vous vous retrouvez souvent en fin de migration avec un nombre conséquent d'agents Quest à désinstaller de tous les postes migrés.

Ce que vous pouvez très bien faire à l'aide de Quest RUM (Resource Updating Manager) via l'option Cleanup :

Mais il peut arriver qu'entre temps que certains postes migrés soient devenus indisponibles. Plutôt que de refaire une passe numéro X pour désinstaller les agents, nous allons voir comment automatiser la désinstallation de ceux-ci.

Prérequis

Pour ce faire, il vous faut :

  • Un serveur sur lequel sera placé un partage accessible par toutes les machines ayant un agent Quest
  • Un éditeur de script Powershell
  • Une console d'édition de stratégies de groupe

Le partage de fichiers

Afin que notre script de désinstallation puisse écrire les logs nécessaire, il doit avoir à disposition un partage sur lequel les machines concernées puissent avoir un droit d'écriture de fichiers.

Par défaut, le script va utiliser le nom de partage QuestUninstallLogs$ mais vous pourrez le modifier via les arguments du script. Nous rajoutons un à la fin du nom du partage afin de masquer celui-ci.

Il faut ajouter sur le partage (droit de partage) le droit en modification pour le groupe Everyone.

Il faut ajouter sur le dossier (droit NTFS) le droit en modification et en écriture pour le groupe Authenticated Users

Une fois cela fait, nous pouvons passer à l'édition du script.

Le script

Arguments

Le script s'appelle à l'aide des arguments suivants :

  • -Pole (obligatoire) : Nom du dossier de 1er niveau des logs
  • -Site (obligatoire) : Nom du dossier de 2ème niveau des logs
  • -LogServer (obligatoire) : Nom du serveur devant recevoir les logs
  • -LogShare (facultatif) : Nom du partage devant recevoir les logs

Sortie

Deux types de fichiers de logs vont être générés en sortie dans le chemin indiqué en paramètre du script :

  • XXX_SUMMARY.log : Fichier résumant toutes les désinstallations effectuées par le script
  • COMPUTERS\PC-XXX.log : Fichier détaillant le déroulement de la désinstallation de l'agent Quest pour le poste concerné

Code

#-------------------#
# Script Parameters #
#-------------------#
# Description
# The Uninstall_Quest_Agent script is uninstalling the Quest RUM Agent
# 
# How to use it 
#
# .\Uninstall_Quest_Agent.ps1 -Pole "POLE_IDF" -Site "Site_1" -LogServer "LOG_SERVER_1" -LogShare "QuestUninstallLogs$"
#
# -Pole = Targeted Pole
# -Site = Targeted Site
# -LogServer = Server on which the uninstall logs will be stored
# -LogShare (not mandatory) = Network Share on which the uninstall logs will be stored

########## PARAMETERS ##########

[CmdletBinding(DefaultParametersetName="Common")]
param(
	
	#Attribute field to check
	[Parameter(Mandatory=$true,Position=1)][string] $Pole = $null,
	
	#Attribute field to check
	[Parameter(Mandatory=$true,Position=2)][string] $Site = $null,
	
	#Attributes fields to check
	[Parameter(Mandatory=$false,Position=3)][string] $LogServer = $null,

	#Attributes fields to check
	[Parameter(Mandatory=$false,Position=4)][string] $LogShare = "QuestUninstallLogs$"
	
	)

########## SCRIPT EXECUTION ##########

# Check if script has been executed (log file already exists)

# Define logfile path and name
# Detailed logs
$LogFileDirectoryPath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site + "\COMPUTERS"
$LogFileName = $env:computername + ".log"
$LogFilePath = $LogFileDirectoryPath + "\" + $LogFileName

# Summary logs
$SummaryLogFileDirectoryPath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site
$SummaryLogFileName = $Pole + "_" + $Site + "_" + "SUMMARY.log"
$SummaryLogFilePath = $SummaryLogFileDirectoryPath + "\" + $SummaryLogFileName

# End script if Quest Agent Service is missing
$Service = Get-Service QsRUMAgent -ErrorAction SilentlyContinue

if($Service -eq $null)
{
    Exit
}

########## LOG FILES MANAGMENT ##########

# Checking if directories need to be created

# Check if pole directory exists
$PoleFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole

# If directory don't exist, we create it
if(!(Test-Path $PoleFilePath))
{
    New-Item $PoleFilePath -ItemType Directory
}

# Check if site directory exists
$SiteFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site

# If directory don't exist, we create it
if(!(Test-Path $SiteFilePath))
{
    New-Item $SiteFilePath -ItemType Directory
}

# Check if COMPUTERS directory exists
$ComputersFilePath = "\\" + $LogServer + "\" + $LogShare + "\" + $Pole + "\" + $Site + "\COMPUTERS"

# If directory don't exist, we create it
if(!(Test-Path $ComputersFilePath))
{
    New-Item $ComputersFilePath -ItemType Directory
}

########## UNINSTALLING AGENT ##########

$Date = (Get-Date).ToString()
$ComputerName = "\\" + $env:computername

# Log
$ToWrite = $Date + " - " + "Begining of Quest agent uninstallation"
Add-Content $LogFilePath $ToWrite

# Stopping and Deleting Quest Migration Manager RUM Agent Service
$Service = Get-Service QsRUMAgent -ErrorAction SilentlyContinue

#If service exists
if($Service)
{
    Stop-Service $Service.Name
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Service - Stopped"
    Add-Content $LogFilePath $ToWrite

    sc.exe $ComputerName delete $Service.Name
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Service - Deleted"
    Add-Content $LogFilePath $ToWrite

    # Log Général
    $ToWrite = $Date + " - " + $env:computername + " - " + "Agent Deleted"
    Add-Content $SummaryLogFilePath $ToWrite
}

else
{
    # Log
    $ToWrite = $Date + " - " + "ERROR : Quest Migration Manager RUM Agent Service not found !"
    Add-Content $LogFilePath $ToWrite
}

# Deleting Quest Migration Manager RUM Agent Directory
$QuestAgentDirectory = "$env:SystemRoot\Quest Resource Updating Agent"

#If directory exists
if(Test-Path $QuestAgentDirectory)
{
    Remove-Item $QuestAgentDirectory -Recurse
    # Log
    $ToWrite = $Date + " - " + "Quest Migration Manager RUM Agent Directory - Deleted"
    Add-Content $LogFilePath $ToWrite
}

else
{
    # Log
    $ToWrite = $Date + " - " + "ERROR : Quest Migration Manager RUM Agent Directory not found !"
    Add-Content $LogFilePath $ToWrite
}

# Log
$ToWrite = $Date + " - " + "End of Quest agent uninstallation"
Add-Content $LogFilePath $ToWrite

Utilisation du script

Vous pouvez utiliser ce script directement sur le poste concerné ou par GPO pour une désinstallation groupée.

Par GPO, le script s'utilise dans la section Powershell dans les Paramètres Ordinateurs de la console de configuration des GPO.

Le chemin pour y accéder est Configuration Ordinateur > Stratégies > Paramètres Windows > Arrêt > Scripts Powershell

A minima, le script doit s'appeller à l'aide des paramètres suivants :

Au fur et à mesure que le script est exécuté, vous devriez voir le dossier des logs se remplir, que ce soit pour le log SUMMARY qui résume toutes les désinstallations ou pour les logs individuels par machine.

Poste de Travail : Fixer le Navigateur par Défaut

Voici comment fixer le navigateur par défaut de vos utilisateurs.

Via PowerShell:

Exécutez les commandes suivantes à l'ouverture de session utilisateur sous forme de script powershell en fonction de votre choix.

Pour Internet Explorer:

Set-Location HKCU:\
    Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\ftp\UserChoice' -name ProgId IE.FTP
    Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice' -name ProgId IE.HTTP
    Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice' -name ProgId IE.HTTPS

 

Pour Mozilla Firefox:

Set-Location HKCU:\
    Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\ftp\UserChoice' -name ProgId FirefoxURL
    Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice' -name ProgId FirefoxURL
    Set-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice' -name ProgId FirefoxURL

Vous pouvez aussi le faire par GPO dans "Configuration Utilisateur > Paramètres Windows > Registre"

Chargement du Module PowerShell SCCM 2012 R2

Vous avez installé les outils admins sur un serveur mais vous ne trouvez pas le module Configuration Manager PowerShell.

Il y a une petite subtilité, celui ci est présent mais dans les binaires de l’application:

le fichier à importer se trouver dans le répertoire c:\program files (x86)\Microsoft Configuration Manager\AdminConsole\bin et se nomme ConfigurationManger.psd1

 

Avant import

image

 

Après import

image

Identification du noeud SQL actif en PS

Vous êtes dans un contexte de database mirroré, et vous avez besoin de connaitre l’actuel serveur principal.

 

Voici une fonction qui va vous permettre de l’identifier.

 

Function Test-SQLConn ($Server)
{
    $connectionString = "Data Source=$Server;Integrated Security=true;Initial Catalog=master;Connect Timeout=2;"
    $sqlConn = new-object ("Data.SqlClient.SqlConnection") $connectionString
    trap
    {
    Write-host "Closed";
    continue
    }
    $sqlConn.Open()
    if ($sqlConn.State -eq 'Open')
    {
        $sqlConn.Close();
        "Opened successfully."
    }
}

 

image

Powershell : Découverte des postes en DHCP et IP fixes

Qui n'a jamais été confronté à un conflit d'adresse IP dans son réseau?

Le plus énervant quand cela arrive c'est de déterminer qui a une IP fixe sur sa machine alors que l'ensemble du parc est censé être en DHCP.

Afin de se se faciliter la tâche et de ne pas devoir passer sur chaque poste voici un script qui va vous permettre de savoir quels postes sont éteints, quels postes sont en DHCP et surtout lesquels ne le sont pas et avec quelle adresse IP (ou plutôt l'ensemble des configurations de chaque carte réseau).

Les Outils :

Pour ce faire vous aurez besoin d'un fichier texte avec les informations suivantes:

  • La première ligne doit s'appeler "Ordi"
  • le reste du fichier contient le nom de vos machines

Exemple :

Dans mon cas le fichier s'appelle DHCP.txt (le nom sera réutilisé dans le Script)

Une fois que le fichier est créé passons à la seconde partie le script:

Dans votre cas il suffira de modifier les lignes:

  • 3
  • 10
  • 17
  • 18
  • 19 
# Script pour détecter l'état des cartes réseaux

$CSV = "C:\Users\XXX\Documents\DHCP.txt"  # Ici on déclare le chemin d'accès au fichier créé plus tôt

# Import du fichier
Import-Csv -Path $CSV | ForEach-Object {

# Déclaration des variables
$Postes = $_.ordi
$Destination = "C:\Users\XXX\Documents\Audit\DHCP\$Postes.txt" # Attention Ici lorsque vous modifiez le chemin ne supprimez pas $Postes.txt

# Test de connexion afin de vérifier que le poste est démarré
If ((Test-connection $Postes -count 2 -Quiet) -eq "True") {

# Déclaration des variables
$Postes = $_.ordi
$Destination = "C:\Users\XXX\Documents\Audit\DHCP\$Postes.txt" # Attention Ici lorsque vous modifiez le chemin ne supprimez pas $Postes.txt
$Poste_DHCP = "C:\Users\XXX\Documents\Audit\OK.txt" # Ici on déclare le chemin et le fichier dans lequel seront inscrit les postes en DHCP
$Poste_Off = "C:\Users\XXX\Documents\Audit\NOK.txt" # Ici on déclare le chemin et le fichier dans lequel seront inscrit les postes éteints

# Récupération des paramètres de la ou des cartes réseaux
Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Postes | ForEach-Object {
$IP = $_.IPAddress
$DHCP = $_.DHCPEnabled
if (($DHCP -eq $False) -and ($IP -ne $null)) {Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Postes | Select-Object -Property ServiceName,Description,DHCPEnabled,IPEnabled,IPAddress | fl | Out-File $Destination}
Elseif (($DHCP -eq $True) -and ($IP -ne $null)) {Write-Output "Le poste $Postes est en DHCP" | Add-Content -Path $Poste_DHCP}
}
}
Else {
Write-Output "Le poste $Postes est éteint" | Add-Content -Path $Poste_Off
}}

 

En espérant que cela vous servira.

Affichage du Body d’un mail en PowerShell via l’utilisation des Web Services API Exchange

 

Lorsque vous récupérez un mail en PowerShell au travers des API Web Services Exchange, le corps du mail semble vide.

 

image

 

Pour afficher le contenu du body, il faut appeler la fonction .load().

Le body du mail s’affiche.

image

 

Cependant celle ci s’affiche formaté en HTML.

SI vous souhaitez l’afficher sous un format texte, il faut indexer une variable avec la propriété Text.

Exemple :

$psPropertySet= New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text

$mail.load($psPropertySet)

$mail.body.text

 

Résultat:

image