jeudi 3 mai 2012

String.Match( why not ? )

salut, l'un des points fort de PowerShell c'est son extensibilité et sa flexibilité, prenons par exemple, les fichiers de configuration de types étendus, ces fichiers permettent d'ajouter des membres dynamiques ou statiques aux objets telques des propriétés ou des méthodes,..etc l'ajout de ces membres ce fait grâce à la cmdlet Update-TypeData qui va charger notre fichier de configuration en mémoire puis ajoutera nos membres dans la session active. voici un petit exemple:


    
        System.String
        
            
                Matches
                
            

           
                Match
                
            

        
    

ce fichier de configuration va ajouter au type system.string deux nouvelles méthodes Match et Matches la première méthode va matcher la première reference de la chaine de caractères, et la deuxième va matcher toutes les références trouvée.. voius devez avant tout charger ce fichier en mémoire:
PS> Update-TypeData MyType.ps1xml
ensuite on pourra faire des choses du genre:
PS> # premier test
PS> Get-Content file.txt | foreach { $_.matches('KB\d{5,}') }
PS>
PS> $s = 'aeejkdkk55d'
PS> $p = '^.'
PS> $s.Match($p)
PS>

mercredi 4 avril 2012

le pipeline... comment en tirer profit ?

salut, l'une des plus belle choses dans powershell est son méchanisme révolutionnaire de pipeline et plus précisemment le méchanisme de liaison entre la sortie d'une commande et l'entrée d'une autre commande , en fait powershell permet de lier entre la valeur et/ou la propriété de l'objet de sortie avec le(s) paramètres de la commande d'entrée...ceci va nous permettre non seulement de rendre le pipeline entre les commandes "fluide" et "puissant" mais aussi de construire nos propres objets personnalisés si la liaison entre les commandes du pipeline n'est pas "permise" on va prendre un exemple facile...nous avons un fichier machines.txt contenant le nom de quelques machines:
C:\> cat ./machines.txt

win8
srv-9
localhost
nous voulons parcourir tous ces posts et afficher tous les services en marche pouvant être stopper...nous avons deux méthodes pour traiter ce problème 1- la façon "traditionnelle" 2- la façcon "powershell way" 1- la façon traditionnelle: pas de magie, c'est verbeux déclaratif et surtout fastidieux pour les tâches rapides d'administrations.
$computers=cat ./machines.txt
foreach($computer in $computers) {
  get-service -computer $computer | where {$_.status -eq 'running' -and $_.canstop -eq $true}
}
2- powershell way: c'est magique, concit, direct et rapide à écrire:
cat ./machines.txt | ConvertFrom-Csv -h 'computername' | gsv | ? {$_.status -eq 'running' -and $_.canstop}
tout le secret reside dans le méchanisme de binding entre les commandes: get-service à un paramètre "-computerName" et il accepte l'entrée du pipeline en mode "BypropertyName" tout ce qu'on fera par la suite c'est de générer un objet ayant comme propriété 'computerName' et ...c'est tout..c'est pas magique ça

samedi 31 mars 2012

Clear-PSSession : comment nettoyer notre environement

salut, les "entités" qui prennent de la place dans la mémoires comme les fonctions-filtres-variables-alias-modules-psessions-..etc peuvent parfois encombré notre session..pour remedier à ce problème voici une petite fonction 'Clear-PSSession' qui permet de nettoyer complètement notre environement et en plus s'auto-charge automatiquement:
if($Host.Name -ne 'ConsoleHost') {
  write-error "ce module ne fonctionne que sous le terminal powershell"
  return
}

$Script:CurrentProcess = $pid
$Script:MyCmd = $MyInvocation.MyCommand.Definition

function Clear-PSSession {
   powershell -noexit -c "stop-process $($Script:currentProcess);import-module '$($Script:MyCmd)'"
}

Export-ModuleMember -Function *  
exemple d'utilisation:

PS> $a = 1
PS> function foo {1}
PS> foo
1
PS> Import-Module .\psession.psm1
PS> gcm -Module psession


CommandType     Name                                                Definition
-----------     ----                                                ----------
Function        Clear-PSSession                                     ...



PS> Clear-PSSession
PS> foo
Le terme « foo » n'est pas reconnu comme nom d'applet de commande, fonction, fichier de script ou prog
 Vérifiez l'orthographe du nom, ou si un chemin d'accès existe, vérifiez que le chemin d'accès est cor
.
Au niveau de ligne : 1 Caractère : 4
+ foo <<<<
    + CategoryInfo          : ObjectNotFound: (foo:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException


PS> $a
PS>

samedi 10 mars 2012

Get-WMIHelp : un Get-Help pour WMI

salut, dans le post précédent, la fonction Get-WMIHelp nous permettait une aide afficher dans la console..dans ce post on va rendre cette aide plus conviviale.. voici la nouvelle fonction
function Get-WMIHelp {  
  <#
.SYNOPSIS

  Affiche des informations sur les classes et propriétés WMI

.DESCRIPTION

  Affiche des informations sur les classes et propriétés WMI

.PARAMETER InputObject

Spécifie un objets  représentant l'objet à récupérer. Entrez une variable contenant l'objets, ou tapez une commande ou une expression permettant d'obtenir cet objet. Vous pouvez également diriger un objet
  vers Get-WMIHelp. 
 
 .PARAMETER Class
 Spécifie le nom d'une classe WMI
 
.PARAMETER Path
 
 Spécifie le chemin d'accès de l'emplacement où le fichier de sortie éléments doit être copiés.

.EXAMPLE

PS C:\> Get-WmiObject -List win32_Bios | Get-WMIHelp

Cette commande obtient toutes les données disponibles sur les paramètres de la classe WMI 'win32_Bios'


.EXAMPLE

PS C:\> Get-WMIHelp -InputObject ([WMIClass]'win32_process')

.EXAMPLE

PS C:\> $WMI = Get-WmiObject -List win32_share
PS C:\> Get-WMIHelp -InputObject $WMI -Path Z:\shareinfo.htm

 La première commande obtient les méta données de la classe WMI 'win32_share', puis elle les stocke dans la variable $WMI.
 La deuxième commande utilise le paramètre InputObject pour passer l'objet  qui est stocké dans la variable $WMI à la fonction Get-WMIHelp. 
 Le paramètre 'Path' permet de spécifier un chemin pour stocké notre fichier "htm"


.EXAMPLE

PS C:\> Get-WMIHelp -Class "win32_OperatingSystem" -path c:\os.htm

 
.LINK
about_WMI_Cmdlets
Get-WmiObject

.INPUTS
System.Management.ManagementClass

.NOTES

   Author: Walid Toumi
   Blog: http://walidtoumi.blogspot.com
   Date: 2/28/2012
   Keywords: WMI - Get-WmiObject - Help
#>
  [CmdletBinding(DefaultParameterSetName='InputObject')]
  param(
   [Parameter(
     ValueFromPipeLine=$True,
     Mandatory=$True,
     Position=0,
     ParameterSetName='InputObject')]
   [ValidateNotNullOrEmpty()]
   [System.Management.ManagementClass]
   ${InputObject},
   [Parameter(Position=0,ParameterSetName='class')]
   ${Class},
   [System.String]
   ${Path})
 
  Try{ 
       switch ($PSCmdlet.ParameterSetName) {
        "Class" {
           $null=Get-WmiObject -Class $Class -ea 'stop'
           $IS_WMI_CLASS = $Class
         }
        "InputObject" {
              $IS_WMI_CLASS = $InputObject.__CLASS
         }
       }
       $WMIClass = Get-WmiObject -List $IS_WMI_CLASS -Amended
       $Desc = $WMIClass.Qualifiers['Description']
       $WMIProperties = $WMIClass.PSbase.Properties
       $Head=@"
     
"@
     $Body = @"
    

WMI CLASS

$($WMIClass.__Class)

WMI CLASS DESCRIPTION

$($Desc.Value)

PARAMETERS

"@ $WMIHelp = $WMIProperties | ForEach-Object { $desc = $($WMIClass.psbase.Properties["$($_.Name)"]).Qualifiers['Description'] New-Object PSObject -Property @{ Description = $desc.value Type = $_.Type Name = $_.Name } } <# end foreach #> | ConvertTo-Html -Property name,Type,description -Head $Head -Body $Body } catch { Write-Error $_ } finally { $WMIHelp > $env:TEMP\wmihelp.htm if($Path) { Try{ Move-Item $env:TEMP\wmihelp.htm $Path -ea 'stop' } catch { Write-Error $_ } } # end if else { Invoke-Item -Path $env:TEMP\wmihelp.htm } # end else } # end finally }

mardi 28 février 2012

invoke-item hklm:\softawre est-ce possible ?

Salut, parfois on est confronté devant des cas ou l'affichage des données dans le prompt n'est plus adéquate, pour cette raison l'equipe de developpeur de PS nous a fourni une cmdlet spécial du nom 'invoke-item' cette cmdlet, nous permet d'executer des actions sur les objets, tel que: * ouvrir le fichier 'a.txt' avec l'application qui lui est associée * ou bien "ouvrir le dossier 'c:\tree'" * ou bien "ouvrir tous les fichiers qui commencent par 't' et qui se termine par 'txt'" cette cmdlet est plus complète que la commande 'start' parcequ'elle permet l'utilisation des wildcards et permet de filtrer les élements selon certains critères. malheureusement cette cmdlet n'est pas suporter par le psprovider 'Registry' .... si on fait une chose du genre:
PS Walid2mi>> Invoke-Item HKCU:\Software
ça va nous retourner une erreur:
Invoke-Item : L'exécution du fournisseur s'est arrêtée, car le fournisseur ne prend pas en charge cette opération.
comme vous venez de constatez, le 'Registry' n'est pas le même environement que le 'FileSystem' une des solutions possibles est de créer notre propre fonction 'Invoke-Registry' qui va nous permettre d'afficher le registre sur la clef qu'on entrera comma paramètre...voici la fonction
function Invoke-Registry {

<#
.SYNOPSIS
   affiche le registre sur la clef spécifié
   
.DESCRIPTION
   affiche le registre sur la clef spécifié
 
.PARAMETER Path
Spécifie le chemin d'accès de la clef de registre sélectionné

.PARAMETER Maximize
maximize la fenêtre du registre
 
.EXAMPLE
   PS HKLM:\Softawre> invoke-Registry .
 
.EXAMPLE
   PS C:\> Invoke-Registry -Path 'Registry::\HKEY_Classes_Root\txtfile'
 
.EXAMPLE
   PS C:\> Invoke-Registry HKCU:\Environment -Max
 
.LINK
 invoke-item

.INPUTS
 none
vous ne pouvez pas diriger des objets pour cette fonction 

.OUTPUTS
 none 

.NOTES
   Author: Walid Toumi
   Blog: http://walidtoumi.blogspot.com
   Date: 2/28/2012
   Keywords: Registry - Invoke-Item
#>
    param(
      [Parameter(Mandatory=$true)]
      [ValidateScript({
             if(((item $_).PSProvider.Name -eq 'Registry') -or $_ -eq '.') 
             {$true} else {throw 'le paramètre "Path" doit correspondre à une clef de registre valide'}})]
        $Path,
      [Switch]$Maximize)
       try{
            $ErrorActionPreference = 1
            $key = (Get-Item $Path).Name
            $item = get-itemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit -Name lastkey
            $item.LastKey = "My Computer\$key"
            Set-ItemProperty -Path $item.PSPath -Name lastkey $item.LastKey
            if($Maximize) { invoke-expression "$env:comSpec /c start /max regedit.exe" } else { regedit.exe }
       } 
       catch {
            Write-Error $_.Exception.message
        }
       finally{
           $ErrorActionPreference = 2
       }
}
cette solution n'est peux être pas la plus optimale, mais elle fonctionne. si je trouve un peux de 'temps' et de 'paix'...ces jours-ci...je pourrais même envisagé de créer une fonction proxy du cmdlet 'invoke-item' qui utiliserait cette technique.. à bientôt alors...que la paix soit avec nous! ;)

lundi 2 janvier 2012

fonction qui affiche et sélectionne les fichiers à la volée

salut,

il y a des fois, la recherche de fichiers dans un répertoire contenant des centaines voire des milliers d'autres fichiers, soit une tâche fastidieuse...ça sera sympa d'avoir une petite fonction qui fait ceci à notre place et en plus sélectionne notre fichier à la voilée, non :)
Function Select-File {
 
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory=$True)]
    [ValidateScript({ 
             if(Test-Path $_) {$true}
             else {
               throw $("fichier ""$_"" introuvable")
             } 
    })]
    [System.String]$FilePath
  )
  Begin{
      $item=get-item $FilePath
      Start-Process -f explorer.exe -a "/select,""$($item.FullName)"""
  }
}

on peux utiliser cette petite fonction ainsi:
PS> Select-File c:\fichier.txt
EDIT: la fonction ne peux pas être utiliser comme un filtre

dimanche 27 novembre 2011

get-content peux désormais traiter les fichiers XML



salut, pour eviter de caster tout le temps les fichiers xml en [Xml] à fin de les traiter j'ai ajouté deux nouveaux paramètres à 'get-content' AsXml et XPath pour que le traitement soit direct.
Function Get-Content {
<#
***************************************************************************
 
 --------------------8<-----------------------------------------
    Ajout de deux nouveaux paramètres pour simplifier
    le traitement des fichiers XML: [-AsXml] [-XPath ]
    
    Attention: l'expression Xpath est sEnSiBlE à La cAsSe
    
                                  Walid toumi             
 --------------------8<-----------------------------------------
 
 PS> # Exemples d'utilisation:
 
 PS> $file = "$PSHOME\types.ps1xml"
 
 PS> $u = cat $file -As | Select-Xml -XP "//ScriptProperty" | Select -Expand Node
 PS> $u

 PS> $Xml = Get-Content $file -AsXml
 PS> $Xml.Types.Type[1..10]
 
 PS> Get-Content $file -AsXml -XPath "//Type[contains(Name,'Xml')]/Name"
 
 **************************************************************************
 
.ForwardHelpTargetName Get-Content
.ForwardHelpCategory Cmdlet

#>

[CmdletBinding(DefaultParameterSetName='Path', SupportsTransactions=$true)]
param(
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [System.Int64]
    ${ReadCount},

    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [System.Int64]
    ${TotalCount},

    [Parameter(ParameterSetName='Path', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
    [System.String[]]
    ${Path},

    [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
    [Alias('PSPath')]
    [System.String[]]
    ${LiteralPath},

    [System.String]
    ${Filter},

    [System.String[]]
    ${Include},

    [System.String[]]
    ${Exclude},
    
    [System.String]
    ${XPath},

    [Switch]
    ${Force},
    
    [Switch]
    ${AsXml},

    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [System.Management.Automation.PSCredential]
    ${Credential})

begin
{
    try {
        $outBuffer = $null
        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
        {
            $PSBoundParameters['OutBuffer'] = 1
        }
        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Get-Content', [System.Management.Automation.CommandTypes]::Cmdlet)
        $cmd = ''
         if($AsXml) {
          [void]$PSBoundParameters.Remove('AsXml')
          $cmd += ' | ForEach-Object {$fx=@()} {$fx+=$_} {$fx -as [Xml]}'
            if($XPath) {
               [void]$PSBoundParameters.Remove('XPath')
               $cmd += ' | Select-Xml -XPath $XPath | Select -expand Node'
            }
        } 
        $ScriptCmd = [ScriptBlock]::Create(
           { & $wrappedCmd @PSBoundParameters }.ToString() + $Cmd
          )
        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
        $steppablePipeline.Begin($PSCmdlet)
    } catch {
        throw
    }
}

process
{
    try {
        $steppablePipeline.Process($_)
    } catch {
        throw
    }
}

end
{
    try {
        $steppablePipeline.End()
    } catch {
        throw
    }
}

}