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
    }
}

}



dimanche 20 novembre 2011

Get-ChildItem un peu plus conviviale :)

Salut, je ne sais pas si quelqu'un d'autre a eu l'idée d'ajouter ces deux fonctionnalités à la cmdlet 'Get-ChildItem' et je n'ai pas aussi tester Powershell vNext pour voir s'il implémente l'une de ces deux fonctionnalités... alors, je me suis dit pourquoi attendre ?! j'ai tout ce qu'il me faut pour configurer mes 'cmdlets' .... alors la première chose qui m'ai venu à l'esprit c'est d'ajouter deux nouveaux paramètres: 'FileSizeInHumanReadableFormat' et 'Pattern' le premier est une implémentation du switch '-lh' de la commande lunix 'ls' qui signifie "Display File Size in Human Readable Format" et l'autre paramètre pour allez un cran au-dessus des simples wildcards utiliser par les "filter" et "include" ... 'pattern' va nous permette d'utiliser les RegExp dans nos recheches :) vous pouvez voir les nouveaux paramètres de la fonction 'Get-ChildItem' en écrivant ceci:
Get-Command Get-ChildItem -TotalCount 1 -Syntax  
en fait le méchanisme d'execution des commandes dans "Windows Powershell"
help Precedence
va nous permettre d'executer notre fonction avant le cmdlet 'Get-Childtem'

Function Get-ChildItem {
<#

.ForwardHelpTargetName Get-ChildItem
.ForwardHelpCategory Cmdlet

#>

[CmdletBinding(DefaultParameterSetName='Items', SupportsTransactions=$true)]
param(
    [Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
    [System.String[]]
    ${Path},

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

    [Parameter(Position=1)]
    [System.String]
    ${Filter},

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

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

    [Switch]
    ${Recurse},

    [Switch]
    ${FileSizeInHumanReadableFormat},

    [Switch]
    ${Force},

    [Switch]
    ${Name})

begin
{
    try {
        $outBuffer = $null
        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
        {
            $PSBoundParameters['OutBuffer'] = 1
        }
        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Get-ChildItem', [System.Management.Automation.CommandTypes]::Cmdlet)
        $cmd = ""
        if($FileSizeInHumanReadableFormat) {
          $PSBoundParameters.Remove('FileSizeInHumanReadableFormat') | Out-Null
          $cmd = @"
            | ForEach-Object {
                `$_length=Switch(`$_.length) {
                  { `$_ -lt 1kb } 
                           {  '{0}B' -f (`$_) ;break }
                  { `$_ -lt 1MB }
                           {  '{0}KB' -f ([math]::round(`$(`$_/ 1kb)), 2) ;break }
                  { `$_ -lt 1gb }
                            { '{0}MB' -f ([math]::round(`$(`$_/ 1mb), 2)) ;break }
                  defaut { 
                            {  '{0}GB' -f ([math]::round(`$(`$_/ 1gb), 2)) ;break }
                   }
                }
                if(`$_.PSISContainer) { `$_length=`$null }
                New-Object PSObject -Property @{
                  Mode = `$_.Mode
                  LastWriteTime = `$_.LastWriteTime
                  Length = `$_length
                  Name = `$_.Name
                }
            }         
"@
        }
        if($PSBoundParameters['Pattern']) {
          if($Filter -or $Include) {
           throw "les paramètres Pattern et Filter/Include sont mutuellemnt exculsive"
          } else {
          $PSBoundParameters.Remove('Pattern') | Out-Null
          $scriptCmd = {& $wrappedCmd @PSBoundParameters | Where { $_.Name -imatch "$Pattern"  } }
          }
        } else {
          $scriptCmd = {& $wrappedCmd @PSBoundParameters } 
        }
        $scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock(
                $scriptCmd.ToString() + $cmd
            )
        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
        $steppablePipeline.Begin($PSCmdlet)
    } catch {
        throw
    }
}

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

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

}



voici quelques utilisation de cette fonction:
Get-ChildItem  -Path $env:windir -Pattern "^\d{2}" -FileSizeInHumanReadableFormat
Get-ChildItem -path $env:windir -filter *.txt -FileSizeInHumanReadableFormat
 
la sortie de la commande est un objet:
System.Management.Automation.PSCustomObject 
 ou
System.IO.FileSystemInfo

jeudi 10 novembre 2011

Get-Help: comment afficher l'aide graphique sans être connecté à internet

salut,

voici une petite fonction proxy du cmdlet Get-Help qui vous permettera d'avoir une aide graphique sans utilisation du paramètre "Online" (qui requiert une connexion internet)...la démarche est toute simple: On décompile à la volée le fichier d'aide local de PS puis on sélectionne la rubrique choisi par une simple recherche...


Function Get-Man {
<#

.ForwardHelpTargetName Get-Help
.ForwardHelpCategory Cmdlet

#>

[CmdletBinding(DefaultParameterSetName='AllUsersView')]
param(
    [Parameter(Position=0, ValueFromPipelineByPropertyName=$true)]
    [System.String]
    ${Name},

    [System.String]
    ${Path},

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

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

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

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

    [Parameter(ParameterSetName='DetailedView')]
    [Switch]
    ${Detailed},

    [Parameter(ParameterSetName='AllUsersView')]
    [Switch]
    ${Full},

    [Parameter(ParameterSetName='Examples')]
    [Switch]
    ${Examples},

    [Parameter(ParameterSetName='Parameters')]
    [System.String]
    ${Parameter},
    
    # affiche l'aide dans le navigateur par defaut
    [Switch]
    ${ShowUI},

    [Switch]
    ${Online})

begin
{
    try {
        $outBuffer = $null
        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
        {
            $PSBoundParameters['OutBuffer'] = 1
        }
        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-Help', [System.Management.Automation.CommandTypes]::Cmdlet)
        if($PSBoundParameters['ShowUI']) {
          $null=$PSBoundParameters.Remove('ShowUI')
                
    function invokeUI {
         param(
           [Parameter(ValueFromPipeLineByPropertyName=$True)]
           $Name
         )
        Begin{
             $HelpChm = "$env:Windir\Help\WindowsPowerShellHelp.chm"
             $HelpTmp = "$env:Temp\PSCmd"
             if (! (Test-Path $HelpChm) ) { 
                  throw "le fichier source $HelpChm est introuvable"
             }
            if(! (Test-Path $HelpTmp)) {
                 Start-Process -File "hh.exe" -Arg "-decompile $HelpTmp $HelpChm" -Wait
            }
            $HtmlFiles = Get-childItem "$HelpTmp\html" *.htm
        }
        Process{
            forEach($file in @($HtmlFiles)) {
                 [Xml]$Xml = get-content $file.Fullname
                 if($Xml.html.head.title -ieq "$Name") {
                    invoke-item $file.Fullname 
                 }
            }
       }
       End{
           Remove-Item $HelpTmp -Recurse
       }
   }

        $scriptCmd = {& $wrappedCmd @PSBoundParameters | invokeUI}
        } else {
        $scriptCmd = {& $wrappedCmd @PSBoundParameters }
        }
        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
        $steppablePipeline.Begin($PSCmdlet)
    } catch {
        throw
    }
}

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

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

l'utilisation de Get-Man est simple voici quelques exemples:

PS>  Get-Man -Name Select-Xml -ShowUI
 
PS> Get-commend Get-Man -syntax






mercredi 24 août 2011

plage d'adresses

salut,

voici un petit script simple pour trouver une plage d'adresses entre deux IP:

    @echo off
    
    call :go 192.168.0.3 192.168.0.65
    echo %ips%
    goto :eof
     
    :go
    setlocal enabledelayedexpansion&set a=0
    for /f "tokens=1-8 delims=." %%a in ("%1.%2") do (
       set /A a=%%h-%%d,b=%%g-%%c,c=%%f-%%b,d=%%e-%%a  
       for %%e in (b c d) do (
          if !%%e! gtr 0 (set e=!e!*255) else (set e=)
       set /A a+=%%e!e!
    ))
    endlocal & set ips=%a%





comment convertir un decimal en binaire

 salut,




@echo off

set num=
set bin=
set k=

set /A num=%1,1/num 2>Nul || (
  findstr /bl "::|" %0
  exit /b 1)
::|
::| usage:  prog 
::|
::| exemple: prog 2335
::|
:lp
set /A k=num %% 2
set bin=%k%%bin%
set /A num/=2
if %num% gtr 0 goto :lp

echo  %bin%


mercredi 27 juillet 2011

Comment numéroter les lignes d'un fichier:

salut,

L'une des solutions possibles:

   @Echo >$ oFF
   Set file=c:\temp\a.txt
   for /f "delims=" %%a in ('
      "fc /l /n %file% $|findstr -vbi [\*A-Z]"
    ') do echo %%a
   del $ 
   goto:eof 




samedi 14 mai 2011

utilisation de %variable% en PS

Salut,

voici une petite fonction pouvant afficher/créer des variables d'environements aussi simple que les batchs NT


del alias:set -ea 0
function set
{
  $_nam,$_rest = "$args".Split('=')
  if(!$_rest -and $_nam) { gci "env:$($_nam)" }
  elseif(!$_nam) { gci env: }
  else {
    $_val = [environment]::ExpandEnvironmentVariables("$_rest")
    ni -pa env:$_nam -va $_val -fo
  }
}


et voici quelques exemples d'utilisation:


# affichage de toutes les variables d'environments
[1] set
Name                           Value                                           
----                           -----                                           
ALLUSERSPROFILE                D:\Documents and Settings\All Users             
APPDATA                        D:\Documents and Settings\walid2mi\Applicatio...
CLIENTNAME                     Console                                         
CommonProgramFiles             D:\Program Files\Fichiers communs   
...
...

[2] # affichage des variables commencant par "P"
[2] set p*
Name                           Value                                           
----                           -----                                           
Path                           D:\WINDOWS\system32;D:\WINDOWS;D:\WINDOWS\Sys...
PATHEXT                        .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;....
PROCESSOR_ARCHITECTURE         x86                                             
ProgramFiles                   D:\Program Files                                

[3] # création d'une variable "user"
[3] set user = %username%

[4] # création d'une variable "Home"
[4] set home=$home