Sep 062017
 

Avec ça, vous aurez les dernières erreurs et leurs causes possibles.

 

$NpsServers=('DC01','DC02')
$ReturnArray=@()

$NPS_Filter="<QueryList>
 <Query Id=`"0`" Path=`"System`">
 <Select Path=`"System`">*[System[Provider[@Name='NPS']]]</Select>
 <Select Path=`"System`">*[System[Provider[@Name='HRA']]]</Select>
 <Select Path=`"System`">*[System[Provider[@Name='Microsoft-Windows-HCAP']]]</Select>
 <Select Path=`"Security`">*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and Task = 12552]]</Select>
 </Query>
</QueryList>"

foreach ( $NpsServer in $NpsServers ) {
 foreach ( $Event in (Get-WinEvent -MaxEvents 800 -ComputerName $NpsServer -FilterXml ([xml]$NPS_Filter) | where {$_.message -like "*denied*"} ) ){
 $Message=$Event.Message.Split("`n")

$Retour = [PSCustomObject]@{
 TimeCreated =$Event.TimeCreated
 MachineName =$Event.MachineName
 AccountName =((($Message |Select-String -Pattern "Account Name" -CaseSensitive)[0]).ToString().split(':')[1]).trim()
 AuthType =((($Message |Select-String -Pattern "Authentication Type" -CaseSensitive)[0]).ToString().split(':')[1]).trim()
 Reason =''
 }
 if ($Message |Select-String -Pattern "Reason" ){
 $Retour.Reason =((($Message |Select-String -Pattern "Reason:" -CaseSensitive)[0]).ToString().split(':')[1]).trim()
 }

$ReturnArray+=$Retour
 }
}
$ReturnArray| ft -autosize

 

Juil 162017
 

A lancer en PowerShell

mkdir wifi
 cd wifi

netsh wlan export profile key=clear

$retour=@()

dir *.xml |% {
 $xml=[xml] (get-content $_)
 $tmp='' |select SSID,Password
 $tmp.SSID=$xml.WLANProfile.SSIDConfig.SSID.name
 $tmp.password=$xml.WLANProfile.MSM.Security.sharedKey.keymaterial
 $retour+=$tmp
 }

cd ..
 rmdir -recurse wifi

$retour | format-table -autosize
Et voilà…
Nov 242016
 

$Session = New-Object -ComObject « Microsoft.Update.Session »
$Searcher = $Session.CreateUpdateSearcher()
$historyCount = $Searcher.GetTotalHistoryCount()
$Searcher.QueryHistory(0, $historyCount) | Select-Object Date,
@{name= »Operation »; e={switch($_.operation){
1 {« Installation »}; 2 {« Uninstallation »}; 3 {« Other »}}}},
@{name= »Status »; e={switch($_.resultcode){
1 {« In Progress »}; 2 {« Succeeded »}; 3 {« Succeeded With Errors »}; 4 {« Failed »}; 5 {« Aborted »}}}},
@{name= »KB »;E={$_.title.split(« (« )[1].split(« ) »)[0]} },
Title | Export-Csv -NoType « $Env:userprofile\Desktop\Windows Updates.csv »
Source : https://social.technet.microsoft.com/wiki/contents/articles/4197.how-to-list-all-of-the-windows-and-software-updates-applied-to-a-computer.aspx

 

Oct 172016
 

Amusant. Si vous faites « enregistrer sous » et choisissez le format « CSV » et que vous avez des caractères bizarres ( Comme é,è,&,..) Excel les détruira lors de l’enregistrement (pas sympa)

Si vous faites « fichier > exporter » et choisissez le format CSV, ca va mieux! mais c’est pas encore ça.. (les champs ne sont pas entre guillemets et on ne peux pas choisir le caractère de séparation…

Voici donc un script PowerShell qui fait le boulot…

Et pour que ce soit GENIAL, faites un raccourci windows avec cette commande:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe  -ExecutionPolicy Bypass   -file  « H:\Scripts\XLS to CSV.ps1 »
(pensez à changer le chemin du script)
Ainsi, il vous suffira de faire un drag’n drop de votre fichier excel sur ce raccourci et HOP! converti !
(on pourait aussi envisager de le mettre dans « send to » mais, ca, je vous laisse faire)

param([string]$xlFile=’nothing’)
$debugMode=$false
$ErrorActionPreference=’Stop’
if ($debugMode) { $xlFile= »H:\Book1.xlsx » }
$csvFile=$xlfile.Replace(‘.xlsx’,’.csv’).replace(‘.xls’,’.csv’)
## Checking…
if ( $xlFile -eq ‘nothing’ ) { Write-Host « No Excel file given. aborting… »                                                     -foregroundcolor red ;$tmp=Read-Host « Press ENTER key to exit »;exit }
if ( test-path($xlFile -eq $false)  ) { Write-Host « Specified Excel file does not exist. »                                        -foregroundcolor red ;$tmp=Read-Host « Press ENTER key to exit »;exit }
if ( test-path($csvFile)   ) { Write-Host « Old converted CSV file exist. Please, delete it before trying to convert it again. »   -foregroundcolor red ;$tmp=Read-Host « Press ENTER key to exit »;exit }
# http://stackoverflow.com/questions/687891/exception-automating-excel-2007-with-powershell-when-calling-workbooks-add
& {
[threading.thread]::CurrentThread.CurrentCulture = ‘en-US’
$xl = New-Object -COM « Excel.Application »
$xl.Visible = $debugMode
Write-Host « Opening source file » -foregroundcolor green
$wb = $xl.Workbooks.Open($xlFile)
$ws = $wb.Sheets.Item(1)
  $i=1
while( $ws.Cells.Item(1, $i).value2 -ne $null ) { if ( $debugMode) {Write-host « Debug 1 : counting column $i »}; $i++ }
$maxColonne=$i-1
  $i=1
while( $ws.Cells.Item($i, 1).value2 -ne $null ) { if ( $debugMode) {Write-host « Debug 1 : counting row $i »}; $i++ }
$maxLigne=$i
  Write-Host « There will be $maxColonne columns and $MaxLigne lines to convert. » -foregroundcolor green
$object=@()
$ligne=2   # ligne 1 = titre
$colonne=1
  while( $ws.Cells.Item($ligne,1).value2 -ne $null ) {
$line=New-Object PSObject
$colonne=1
while( $colonne -le $maxColonne) {
$cell=$ws.Cells.Item($ligne,$colonne).value2
if ($cell -eq $null) { $cell = «  » }
Add-Member -InputObject $line -MemberType NoteProperty -Name $ws.Cells.Item(1, $colonne).value2 -Value $cell
if ( $debugMode) {Write-host « debug2  » + $ws.Cells.Item($ligne,$colonne).value2 }
$colonne++
}
$ligne++
$object += $line
write-host -NoNewline « `r                                              `r Progres : $ligne/$maxLigne »
}
  $wb.Close() | out-null
$xl.Quit() | out-null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) | out-null
  Write-Host « `r`n$ligne rows where converted. » -foregroundcolor green
Write-Host « Saving datas to $csvFile. Please, wait… » -foregroundcolor cyan
$object | Export-Csv $csvFile -NoTypeInformation -Delimiter ‘;’ -Encoding UTF8
Write-Host « Save completed. » -foregroundcolor green
sleep 3
}
Tadaaaaa…
Sep 152016
 

Pré-requis :

Un share réseau sur lequel l’objet COMPUTER de la machine VEEAM a les droits en écriture.
Le soft ignore les paramètres de credentials créés pour l’occasion, alors, autant s’en passer complètement 🙂
Le script doit être lancé en tant qu’administrateur !!

J’ai préféré créer un script qui fait tout plutôt que de faire de la config dans l’application et dans le script.

Le script :

# Author: Vladimir Eremin
# Created Date: 3/24/2015
# http://forums.veeam.com/member31097.html
#
# Adapted by Myself
# Must be run as administrator !
# backup everything except VMs defined

##################################################################
#                   User Defined Variables
##################################################################

$ExceptionVMNames = @('DSVA-VM01','VM-VEEAM-01')           # Theses VMs will NOT be backuped.
$HostName = "ESXNAME01"
$Directory = "\\NAS01.DOMAIN.COM\VEEAM"
$CompressionLevel = "5"              # Desired compression level (Optional; Possible values: 0 - None, 4 - Dedupe-friendly, 5 - Optimal, 6 - High, 9 - Extreme)
$EnableQuiescence = $True            # Quiesce VM when taking snapshot (Optional; VMware Tools are required; Possible values: $True/$False)
$Retention = "In3days"               # Possible values: Never , Tonight, TomorrowNight, In3days, In1Week, In2Weeks, In1Month)

$EnableNotification = $True          # Send an eMail about the backup when completed.
$SMTPServer = "smtp.domain.com"
$EmailFrom = "veeam.site1@domain.com"
$EmailTo = "myself@domain.com"
$EmailSubject = "VM backup of SITE 1"




# Pour la création des objets nécessaires au backup. Il n'est pas nécessaire de les créer dans l'interface graphique.
$ESX_name='ESXNAME01.domain.com'
$ESX_User='root'
$ESX_password='MemePasEnReve:-)'
$NAS_name='NAS01'

# Get-Command -Module VeeamPSSnapIn           # pour lister les commandes possibles...

##################################################################
#                   End User Defined Variables
##################################################################

Add-PSSnapin VeeamPSSnapin

Connect-VBRServer -server localhost

if ( Find-VBRViEntity -name $ESX_name -HostsAndClusters ) {
  Write-Host "ESX exist" -foregroundcolor GREEN
} else {
  Write-Host "ESX does not exist. Create it" -foregroundcolor CYAN
  Add-VBRESXi -Name $ESX_name -User $ESX_User -Password $ESX_password
}

$Server = Get-VBRServer -name $HostName

# Création du repository.
# Attention, les droits NTFS du share doivent autoriser l'objet COMPUTER a modifier les fichiers sur le NAS.
if (Get-VBRBackupRepository -name $NAS_name ) {
  Write-Host "Repository exist" -foregroundcolor GREEN
} else {
  Write-Host "Repository does not exist. Create it"  -foregroundcolor CYAN
  Add-VBRBackupRepository -Name $NAS_name -Type CifsShare -RotatedDrive -Description "Synology NAS" -Server $server -Folder $Directory
}

# Creation du proxy pour backup local
if ( ( Get-VBRViProxy | measure).count -ne 1  ) {
  Write-Host "Proxy does not exist. Create it" -foregroundcolor CYAN
  Get-VBRServer | ? { $_.type -eq "Local" } | Add-VBRViProxy -Description "Local Backup Proxy" -MaxTasks 2
} else {
  Write-Host "Proxy exist"  -foregroundcolor GREEN
}

#################### Main program ################

$MesssagyBody = @()

foreach ($VM in Find-VBRViEntity -Server $Server | ? {$_.type -eq "vm" -and $_.name -notin $ExceptionVMNames -and $_.name -notlike "*_clone_*" }){

  Write-Host "Starting backup of " $VM.name -nonewline -foregroundcolor cyan
  $ZIPSession = Start-VBRZip -Entity $VM -Folder $Directory -Compression $CompressionLevel -DisableQuiesce:(!$EnableQuiescence) -AutoDelete $Retention
  if ( $ZIPSession.Result -eq 'Failed' ) {
    Write-Host ". statut : " $ZIPSession.Result -foregroundcolor RED
  } else {
    Write-Host ". statut : " $ZIPSession.Result -foregroundcolor GREEN
  }


  If ($EnableNotification){
    $TaskSessions = $ZIPSession.GetTaskSessions().logger.getlog().updatedrecords
    $FailedSessions =  $TaskSessions | where {$_.status -ne "ESucceeded"}

    if ($FailedSessions -ne $Null){
      $MesssagyBody = $MesssagyBody + ($ZIPSession | Select-Object @{n="Name";e={($_.name).Substring(0, $_.name.LastIndexOf("("))}} ,@{n="Start Time";e={$_.CreationTime}},@{n="End Time";e={$_.EndTime}},Result,@{n="Details";e={$FailedSessions.Title}})
    }Else{
      $MesssagyBody = $MesssagyBody + ($ZIPSession | Select-Object @{n="Name";e={($_.name).Substring(0, $_.name.LastIndexOf("("))}} ,@{n="Start Time";e={$_.CreationTime}},@{n="End Time";e={$_.EndTime}},Result,@{n="Details";e={($TaskSessions | sort creationtime -Descending | select -first 1).Title}})
    }
  }
}

If ($EnableNotification){
  #                   Email formatting
  $style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
  $style+=   "TABLE{border: 1px solid black; border-collapse: collapse;}"
  $style+=   "TH{border: 1px solid black; background: #ddddff; padding: 5px; }"
  $style+=   "TD{border: 1px solid black; padding: 5px; }"
  $style+= "</style>"

  $Message = New-Object System.Net.Mail.MailMessage $EmailFrom, $EmailTo
  $Message.Subject = $EmailSubject
  $Message.IsBodyHTML = $True
  $message.Body = $MesssagyBody | ConvertTo-Html -head $style | Out-String
  $SMTP = New-Object Net.Mail.SmtpClient($SMTPServer)
  $SMTP.Send($Message)
}
La commande pour la tache planifiée :
schtasks /create /SC daily /TN Daily_VM_backup /TR "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -file C:\Script\Veeam_Zip_SITE1.ps1" /ST 23:00 /RU system
Et voila…
Jan 292016
 

Si vous tentez d’ouvrir une console via la ligne de commande PowerShell et que vous avez cette erreur :

get-vm MGMT | Open-VMConsoleWindow
Open-VMConsoleWindow : 29-01-16 11:44:00    Open-VMConsoleWindow        Unable to find the specified browser: "C:\".
Au caractère Ligne:1 : 15
+ get-vm MGMT | Open-VMConsoleWindow
+               ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument : (:) [Open-VMConsoleWindow], InvalidArgument
+ FullyQualifiedErrorId : ViCore_ViCoreServiceImpl_GetVMConsoleWindowBrowser_FileNotFound,VMware.VimAutomation.ViCore.Cmdlets.Commands.OpenVMConsoleWindow

C’est que PowerCli ne sait pas quel browser utiliser (ouais… super le message d’erreur, hein !)
Dans ce cas, configurez le browser à utiliser via une des deux commandes suivantes (en fonction de vos préference). Cette action est à exécuter avec des droits d’administrateur.

Notez que vous devez indiquer la version 32 bit du browser !

Internet Explorer
Set-PowerCLIConfiguration –VMConsoleWindowBrowser 'C:\Program Files (x86)\Internet Explorer\iexplore.exe'
Firefox
Set-PowerCLIConfiguration –VMConsoleWindowBrowser “C:\Program Files (x86)\Mozilla Firefox\firefox.exe”

 

Sep 162015
 

Si vous avez une BBox qui d?conne comme la mienne, vous ne savez plus où se trouve quelle VM/PC/T?l?phone/bidule.. d’un point de vue IP. Ce petit script fait un inventaire assez sympa. (attention, gourmand en ressources )

Adaptez les champs en gras selon vos besoins 🙂

$MASK='10.254.0.'
$myJobs=for( $i=1;$i -le 254 ; $i++){ 
  $ip=''+$MASK+$i
  Start-Job? -ArgumentList $ip -ScriptBlock { param ($ip)
    if ( test-connection $ip -Quiet -Count 2 ) {
      try    { $hostname=[System.Net.Dns]::gethostentry($ip).Hostname }
      catch { $hostname='Unknown' }

      Finally{ New-Object PSObject -Property @{ IP = $IP ; HostName = $Hostname } }
    }
  }
}
$myJobs | wait-job | out-null
$myJobs | foreach { $_ | receive-job -keep | select IP, Hostname } | tee -variable inventaire | ft -autosize
Sep 072015
 

Bonjour,

Si, comme moi, vous ne savez pas « vraiment » sur quel switch, ni quel port se trouve connecté la vmnic de votre ESX ET que votre switch ne supporte pas CDP, mais LLDP, voici un script maison qui va vous donner l’info.

Mon script lance une capture d’une trame spécifique émise par le switch sur chaque porte afin de faire un inventaire.
L’info est sauvée dans un datastore connu de tous les ESXs (plus facile pour récupérer l’info)

Prérequis :

  • un accès ROOT sur chaque ESX
  • Une connexion via SSH possible sur la console
  • Un datastore commun à tous les ESXs

La création du tableau de correspondance ESX <> mot de passe ROOT

$ESXs =@{'ESX01' ='abc123'}
$ESXs+=@{'ESX02' ='def456'}

Le script :

get-datacenter "MON DataCenter" | get-vmhost | foreach {
$esx=$_.name
$password=$ESXs.Get_Item($_.name)
$_ | Get-VirtualSwitch | select -expandproperty nic| foreach {
$vmnic=$_

$file= »C:\temp\$esx-$vmnic.sh »
‘ps | grep « pkt » | awk  »{ print $1 } » | kill’ | out-file $file -Encoding ascii
« pktcap-uw –uplink $vmnic –ethtype 0x88cc -c 1 -o /tmp/$vmnic  » | out-file $file -append -Encoding ascii
‘FEX=`hexdump -e « 500 \ »%_p\ » \ »\\n\ » » /tmp/’+$vmnic+’ | cut -b 67-77`’ | out-file $file -append -Encoding ascii
‘echo `hostname`,’+$vmnic+’,$FEX >> /vmfs/volumes/MonDatastore/vmnicInventory.csv’ | out-file $file -append -Encoding ascii
« putty.exe $esx -l root -pw $password -m C:\temp\$esx-$vmnic.sh »
putty.exe $esx -l root -pw $password -m C:\temp\$esx-$vmnic.sh | out-null
}
}

Si tout se passe bien, vous vous retrouvez avec un super fichier texte avec toutes les infos.

NB : J’affiche dans la console la ligne de commande que j’execute, car il m’est déjà arrivé de voir « putty » planter en pleine collecte. Plutôt que de tout relancer, je ne lance que la commande qui a planté.
NB2 : Je ne lance pas toutes les collectes en même temps, car il peux arriver que 2 commandes veuillent écrire en même temps et alors, ca plante. C’est plus lent, mais plus sur.

Août 282015
 

ca peux sembler être le titre d’un roman, mais dans la catégorie cauchemar alors ! Je m’explique :

Aujourd’hui, j’ai écrit un super script qui fait plein de choses intéressantes, et histoire de faire ça correctement, je mets quelques programmes exécutable supplémentaires dans le répertoire C:\Windows\system32.

Jusque-là, rien de bien méchant, sauf que mon script qui est lancé par un service supplémentaire, refuse d’exécuter les programmes que j’ai ajouté. Fichier introuvable qu’il me dit.

Introuvable, introuvable? Il lui faut des lunettes, oui!

Je lance à la main, ça fonctionne. Je le lance à partir du service, ça ne fonctionne plus.

Là, on se dit qu’on commence à perdre la tête ou que Windows est une belle merde. Et donc on se retrouve a faire des choses aussi stupide que de faire un « dir » des fichiers en question .

Et c’est là que ça se corse, comme dirait Napoléon

Quand mon script liste les fichiers, il ne trouve rien. Quand je liste les fichiers, je les vois…

Je vous passe tous les noms d’oiseaux qui me sont passés par l’esprit…

Et j’en suis arrivé à la conclusion que la seule différence était le service en question, vieux service qui fonctionnait en 32 bits. Je démarre une console PowerShell en 32 bits, et tente de lister les fichiers? Surprise, pas de fichiers présents. Ou plutôt, pas de fichier 32 bits!!!!!

Windows, pour une raison que je n’explique toujours pas, n’affiche pas les programmes 32 bits qui se trouve dans le répertoire C:\Windows\system32.

J’ai donc trouvé 2 solutions:

  • Mettre à jour mon service en 64 bits, j’ai de la chance il est disponible.
  • Déplacer mes exécutables dans un autre endroit (ce qui n’est pas une bonne idée quand ce sont des fichiers standards Microsoft comme « dfsutil »)

Si vous êtes arrivés sur cette page, et que cela solutionne votre problème, merci de me laisser un message en commentaire, afin que je me sente moins seul merci!

En fait, Microsoft est déjà prêt pour les ordinateurs quantiques. En fonction de la manière dont on regarde, le résultat n’est pas le même. Tu existes et tu n’existes pas en même temps.

Juil 012015
 

Vous souhaitez interroger vos DBs mais les m?thodes fournies sont chiantes peu ergonomiques?
Facile! Voici 2 fonctions qui font le boulot.
Remarque utile : pas besoin d’installer un quelconque client! C’est natif !

SQL

Function querySQL ( $query, $database='master', $Server) {
$connection = New-Object System.Data.SqlClient.SqlConnection;
$connection.ConnectionString = "Server=$Server;Database=$database;Integrated Security=True;Connect Timeout=$timeOut;";
try {
$connection.Open();
$command = $connection.CreateCommand();
$command.CommandText = $query;
try{
$result = $command.ExecuteReader();
$SQLData = new-object System.Data.DataTable;

$SQLData.Load($result);
$connection.Close();
Remove-Variable connection, command, result
$SQLData
}
catch{Write-Host "Oups: Cannot query" -foregroundcolor Magenta}
}
catch{Write-Host "Oups: Connot open : Do you have the right to connect to this DB?" -foregroundcolor Magenta}
}

Oracle

function queryOracle ( $TNSName, $Query, $Username, $Password) {
[System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient") | out-null

$OracleConnection = New-Object System.Data.OracleClient.OracleConnection("Data Source=$TNSName;User Id=$Username;Password=$Password;Integrated Security=no");
$OracleConnection.Open()

$SelectCommand = New-Object System.Data.OracleClient.OracleCommand;
$SelectCommand.Connection = $OracleConnection
$SelectCommand.CommandText = $Query
$SelectCommand.CommandType = [System.Data.CommandType]::Text

$result = New-Object System.Data.DataTable
$result.Load($SelectCommand.ExecuteReader())

$reader = $SelectCommand.ExecuteReader()
while ($reader.Read()) {
$obj = New-Object PSObject
0..($reader.FieldCount-1) | % {
$obj | Add-Member -MemberType NoteProperty -Name ($reader.GetName($_) -replace "\W", "") -Value ($reader.GetValue($_))
}
$obj
}
}