Question Comment construire un objet qui construit du code?
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6311
- Remerciements reçus 68
il y a 16 ans 1 mois #6088
par Laurent Dardenne
Tutoriels PowerShell
Avant d'aborder de plain-pied ce sujet, je vous propose de revoir qq notions de dynamisme autour des Scriptblocks (réalisé sous PS v2).
Première tentative, on paramètre une partie du code d'un Scriptblock :
[code:1]
$Message=\"Ceci est un message de test\"
$sb={Write-Host $Message}
&$sb
[/code:1]
Le code précédent utilise la substitution de variable pour paramétrer l'appel d'un cmdlet.
Allons plus loin, paramétrons entièrement le code du Scriptblock :
[code:1]
$code=\"Write-host '$Message'\"
$sb={$code}
&$sb
[/code:1]
Ici la substitution de la variable $Code dans le Scriptblock n'est pas équivalente au code précédent.
Dans ce cas, l'exécution du Scriptblock affiche le contenu de la variable $code.
Pour construire un Scriptblock on peut utiliser le code suivant :
[code:1]
$sb=$ExecutionContext.InvokeCommand.NewScriptBlock($code)
&$sb
[/code:1]
Pour paramétrer entièrement le code d'un Scriptblock on peut aussi utiliser le cmdlet Invoke-Expression :
[code:1]
$sb={invoke-expression $code}
&$sb
[/code:1]
Cette indirection ne nécessite pas de code avancé.
Toutefois si on l'utilise dans un pipeline le nombre d'objets à traiter peut influencer le temps de traitement (il peut être multiplié par 2).
Si on manipule des patterns de commande (dixit Bruce Payette), c'est à dire des constructions récurrentes où seul le paramétrage change, la manipulation directe d'objet de type Scriptblock me semble préférable.
Un exemple de pattern simple, la recherche d'objet selon une date portée par une de ses propriétés, ici des objets fichiers :
[code:1]
Get-Childitem \"$pwd\"|
Where {'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '30/01/2010'}|
Select Name, \"CreationTime\"
[/code:1]
On peut paramétrer la clause Where ainsi :
[code:1]
#Date du jour au format court
$DtPattern=(Get-Culture).DateTimeFormat.ShortDatePattern
$Date=get-date -format $DtPattern
$Pattern=\"{0:$DtPattern}\"
$Property=\"LastWriteTime\"
Get-Childitem \"$pwd\"|
Where {\"$Pattern\" -f $_.$property -eq \"$Date\"}|
Select Name, \"CreationTime\"
[/code:1]
La limite ici est que la clause Where, bien que paramétrée, portera tjrs sur le même type de recherche, seuls les opérandes changent.
On peut bien sûr, comme on vient de le voir, utiliser Invoke-Expression :
[code:1]
#Début de code identique au précédent exemple
$Property=\"LastWriteTime\"
$Code=\"'$Pattern' -f `$_.$property -eq '$Date'\"
Get-Childitem \"$pwd\"|
Where {invoke-expression $code}|
Select Name, $Property
[/code:1]
On peut se satisfaire de cette solution, et passer en paramètre la variable $Code.
Si on souhaite manipuler plusieurs critères de recherche basés une date, tout en évitant l'usage du cmdlet Invoke-Expression, l'usage d'un générateur de filtre réduira la redondance de code.
Dit autrement, la clause Where peut porter sur une propriété ou une classe différente, de plus l'opérateur peut être différent :
[code:1]
#Début de code identique au précédent exemple
$Property=\"StartTime\"
$Code=\"'`$_.$Property' -ge [DateTime]::Today.Adddays(-1)\"
Get-Process |
Where {invoke-expression $code}|
Select Name, $Property
[/code:1]
Notre pattern de commande est donc:
On liste des objets pour les filtrer d'après une propriété de type Date.
Je vous propose de regrouper ces différents critères de recherche, utilisés dans une clause Where, dans un objet personnalisé dont une méthode renvoie un Scriptblock.
Ce Scriptblock étant paramétrable et généré dynamiquement lors de l'appel de la méthode.
Pour le Scriptblock suivant, on doit paramétrer l'opérateur de formatage et la date de recherche. :
[code:1]
'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '28/12/2009'}
[/code:1]
Pour les opérandes de l'opérateur de formatage on peut les substituer lors la création de l'objet personnalisé, quant à la date on la passera en paramètre de la méthode.
Le problème est de parvenir à retarder la substitution lors de chaque étape de construction du code :
[code:1]
function DemoDynamic([string] $PropertyName) {
#On construit dynamiquement un objet possédant une méthode créant dynamiquement un Scriptblock
#Comme il y a deux niveaux de substitution, on doit tripler le caractère backtick :
# le premier est un caractère d'échappement pour le caractère dollar ($),
# le second est un caractère d'échappement pour le troisième caractère d'échappement.
#
#Ce code génère la ligne d'instruction suivante :
# $ExecutionContext.InvokeCommand.NewScriptBlock(\"`$_.MypropertyName -eq '$($Args[0])'\"}
#Première substitution
#récupère la chaîne de formatage court d'une date
#Pour une session Fr : dd/MM/yyyy
$DtPattern=(Get-Culture).DateTimeFormat.ShortDatePattern
$ThisDate=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"'{0:$DtPattern}' -f ```$_.\"+$PropertyName+\" -eq '`$(`$Args[0])'`\"«»)\"
#Lors de l'appel de la méthode ThisDate, on construit le code final du Scriptblock.
#C'est ce Scriptblock qui sera exécuté.
#Seconde substitution
$MakeMember=@\"
New-Object PSObject|
#Args[0] attend une string contenant une date au format Fr de type : \"28/12/2009\"
Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru
\"@
Invoke-Expression $MakeMember
} # DemoDynamic
[/code:1]
Le code renseignant la variable $DtPattern permet un usage localisé du filtre, sous réserve que le format de la date passée en argument soit correct.
L'usage de la variable $ThisDate facilite la relecture en décomposant les étapes de construction du code, car la mise au point des deux niveaux de substitution est délicate.
Un exemple d'utilisation :
[code:1]
$property=\"LastWriteTime\"
#construit le générateur de filtre
$Factory= DemoDynamic $property
#Génére un Scriptblock
#$ThisDate=$Factory.ThisDate(\"29/01/2010\"«»)
$FiltreThisDate=$Factory.ThisDate((get-date -format ((Get-Culture).DateTimeFormat.ShortDatePattern)))
#Affiche le code du Scriptblock
$FiltreThisDate
cd $env:Temp
#Utilise le Scriptblock
Get-Childitem \"$pwd\"|Where $FiltreThisDate|Select Name,$property
#ou
# Get-Childitem \"$pwd\"|Where ($Factory.ThisDate((get-date -format \"dd/MM/yyyy\"«»)))|Select Name,$property
[/code:1]
Le code de DemoDynamic paramètre le nom de propriété, on peut l'héberger dans une propriété en utilisant cette autre astuce :
powershell-scripting.com/index.php?optio...=14&id=6052#6052
La version 2 :
[code:1]
function DemoDynamic {
$ThisDate=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"'{0:$((Get-Culture).DateTimeFormat.ShortDatePattern)}' -f ```$_.`$(`$this.PropertyName) -eq '`$(`$Args[0])'`\"«»)\"
$MakeMember=@\"
New-Object PSObject|
Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru
\"@
$Object=Invoke-Expression $MakeMember
$Object|Add-Member ScriptProperty PropertyName -value {\"CreationTime\"} -SecondValue {
#On modifie la valeur du getter
#(\"CreationTime\" est sa valeur d'origine).
$Getter=$ExecutionContext.InvokeCommand.NewScriptBlock(\"`\"$($Args[0])`\"\"«»)
#On réutilise le code du setter
#(ici on est certains de ne récupérer qu'un seul élément).
$Setter=@($this.PsObject.Properties.Match(\"PropertyName\"«»))[0]
#On supprime la propriété actuelle.
[void]$this.PsObject.Properties.Remove(\"PropertyName\"«»)
#Puis on la reconstruit dynamiquement.
$ANewMySelf=New-Object System.Management.Automation.PSScriptProperty(\"PropertyName\",`
$Getter,$Setter.SetterScript)
[void]$this.PsObject.Properties.Add($ANewMySelf)
} -Passthru
} # DemoDynamic
[/code:1]
Un exemple d'utilisation :
[code:1]
cd $env:temp
#construit l'objet
$Factory= DemoDynamic
$Aujourdhui=(get-date -format ((Get-Culture).DateTimeFormat.ShortDatePattern))
$FiltreThisDate=$Factory.ThisDate($Aujourdhui)
Get-Childitem \"$pwd\"|Where $FiltreThisDate|Select Name,\"$($Factory.PropertyName)\"
#On paramètre le générateur de filtre avec une nouvelle propriété
$Factory.PropertyName=\"LastWriteTime\"
$FiltreThisDate2=$Factory.ThisDate($Aujourdhui)
Get-Childitem \"$pwd\"|Where $FiltreThisDate2|Select Name,\"$($Factory.PropertyName)\"
[/code:1]
On peut ajouter une clause Where pour filtrer le type du fichier :
[code:1]
Get-Childitem \"$pwd\"|Where {!$_.psIsContainer}|Where $FiltreThisDate2 |Select Name,\"$($Factory.PropertyName)\"
[/code:1]
Reste à construire ce générateur de filtres.<br><br>Message édité par: Laurent Dardenne, à: 2/02/10 16:10
Première tentative, on paramètre une partie du code d'un Scriptblock :
[code:1]
$Message=\"Ceci est un message de test\"
$sb={Write-Host $Message}
&$sb
[/code:1]
Le code précédent utilise la substitution de variable pour paramétrer l'appel d'un cmdlet.
Allons plus loin, paramétrons entièrement le code du Scriptblock :
[code:1]
$code=\"Write-host '$Message'\"
$sb={$code}
&$sb
[/code:1]
Ici la substitution de la variable $Code dans le Scriptblock n'est pas équivalente au code précédent.
Dans ce cas, l'exécution du Scriptblock affiche le contenu de la variable $code.
Pour construire un Scriptblock on peut utiliser le code suivant :
[code:1]
$sb=$ExecutionContext.InvokeCommand.NewScriptBlock($code)
&$sb
[/code:1]
Pour paramétrer entièrement le code d'un Scriptblock on peut aussi utiliser le cmdlet Invoke-Expression :
[code:1]
$sb={invoke-expression $code}
&$sb
[/code:1]
Cette indirection ne nécessite pas de code avancé.
Toutefois si on l'utilise dans un pipeline le nombre d'objets à traiter peut influencer le temps de traitement (il peut être multiplié par 2).
Si on manipule des patterns de commande (dixit Bruce Payette), c'est à dire des constructions récurrentes où seul le paramétrage change, la manipulation directe d'objet de type Scriptblock me semble préférable.
Un exemple de pattern simple, la recherche d'objet selon une date portée par une de ses propriétés, ici des objets fichiers :
[code:1]
Get-Childitem \"$pwd\"|
Where {'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '30/01/2010'}|
Select Name, \"CreationTime\"
[/code:1]
On peut paramétrer la clause Where ainsi :
[code:1]
#Date du jour au format court
$DtPattern=(Get-Culture).DateTimeFormat.ShortDatePattern
$Date=get-date -format $DtPattern
$Pattern=\"{0:$DtPattern}\"
$Property=\"LastWriteTime\"
Get-Childitem \"$pwd\"|
Where {\"$Pattern\" -f $_.$property -eq \"$Date\"}|
Select Name, \"CreationTime\"
[/code:1]
La limite ici est que la clause Where, bien que paramétrée, portera tjrs sur le même type de recherche, seuls les opérandes changent.
On peut bien sûr, comme on vient de le voir, utiliser Invoke-Expression :
[code:1]
#Début de code identique au précédent exemple
$Property=\"LastWriteTime\"
$Code=\"'$Pattern' -f `$_.$property -eq '$Date'\"
Get-Childitem \"$pwd\"|
Where {invoke-expression $code}|
Select Name, $Property
[/code:1]
On peut se satisfaire de cette solution, et passer en paramètre la variable $Code.
Si on souhaite manipuler plusieurs critères de recherche basés une date, tout en évitant l'usage du cmdlet Invoke-Expression, l'usage d'un générateur de filtre réduira la redondance de code.
Dit autrement, la clause Where peut porter sur une propriété ou une classe différente, de plus l'opérateur peut être différent :
[code:1]
#Début de code identique au précédent exemple
$Property=\"StartTime\"
$Code=\"'`$_.$Property' -ge [DateTime]::Today.Adddays(-1)\"
Get-Process |
Where {invoke-expression $code}|
Select Name, $Property
[/code:1]
Notre pattern de commande est donc:
On liste des objets pour les filtrer d'après une propriété de type Date.
Je vous propose de regrouper ces différents critères de recherche, utilisés dans une clause Where, dans un objet personnalisé dont une méthode renvoie un Scriptblock.
Ce Scriptblock étant paramétrable et généré dynamiquement lors de l'appel de la méthode.
Pour le Scriptblock suivant, on doit paramétrer l'opérateur de formatage et la date de recherche. :
[code:1]
'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '28/12/2009'}
[/code:1]
Pour les opérandes de l'opérateur de formatage on peut les substituer lors la création de l'objet personnalisé, quant à la date on la passera en paramètre de la méthode.
Le problème est de parvenir à retarder la substitution lors de chaque étape de construction du code :
[code:1]
function DemoDynamic([string] $PropertyName) {
#On construit dynamiquement un objet possédant une méthode créant dynamiquement un Scriptblock
#Comme il y a deux niveaux de substitution, on doit tripler le caractère backtick :
# le premier est un caractère d'échappement pour le caractère dollar ($),
# le second est un caractère d'échappement pour le troisième caractère d'échappement.
#
#Ce code génère la ligne d'instruction suivante :
# $ExecutionContext.InvokeCommand.NewScriptBlock(\"`$_.MypropertyName -eq '$($Args[0])'\"}
#Première substitution
#récupère la chaîne de formatage court d'une date
#Pour une session Fr : dd/MM/yyyy
$DtPattern=(Get-Culture).DateTimeFormat.ShortDatePattern
$ThisDate=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"'{0:$DtPattern}' -f ```$_.\"+$PropertyName+\" -eq '`$(`$Args[0])'`\"«»)\"
#Lors de l'appel de la méthode ThisDate, on construit le code final du Scriptblock.
#C'est ce Scriptblock qui sera exécuté.
#Seconde substitution
$MakeMember=@\"
New-Object PSObject|
#Args[0] attend une string contenant une date au format Fr de type : \"28/12/2009\"
Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru
\"@
Invoke-Expression $MakeMember
} # DemoDynamic
[/code:1]
Le code renseignant la variable $DtPattern permet un usage localisé du filtre, sous réserve que le format de la date passée en argument soit correct.
L'usage de la variable $ThisDate facilite la relecture en décomposant les étapes de construction du code, car la mise au point des deux niveaux de substitution est délicate.
Un exemple d'utilisation :
[code:1]
$property=\"LastWriteTime\"
#construit le générateur de filtre
$Factory= DemoDynamic $property
#Génére un Scriptblock
#$ThisDate=$Factory.ThisDate(\"29/01/2010\"«»)
$FiltreThisDate=$Factory.ThisDate((get-date -format ((Get-Culture).DateTimeFormat.ShortDatePattern)))
#Affiche le code du Scriptblock
$FiltreThisDate
cd $env:Temp
#Utilise le Scriptblock
Get-Childitem \"$pwd\"|Where $FiltreThisDate|Select Name,$property
#ou
# Get-Childitem \"$pwd\"|Where ($Factory.ThisDate((get-date -format \"dd/MM/yyyy\"«»)))|Select Name,$property
[/code:1]
Le code de DemoDynamic paramètre le nom de propriété, on peut l'héberger dans une propriété en utilisant cette autre astuce :
powershell-scripting.com/index.php?optio...=14&id=6052#6052
La version 2 :
[code:1]
function DemoDynamic {
$ThisDate=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"'{0:$((Get-Culture).DateTimeFormat.ShortDatePattern)}' -f ```$_.`$(`$this.PropertyName) -eq '`$(`$Args[0])'`\"«»)\"
$MakeMember=@\"
New-Object PSObject|
Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru
\"@
$Object=Invoke-Expression $MakeMember
$Object|Add-Member ScriptProperty PropertyName -value {\"CreationTime\"} -SecondValue {
#On modifie la valeur du getter
#(\"CreationTime\" est sa valeur d'origine).
$Getter=$ExecutionContext.InvokeCommand.NewScriptBlock(\"`\"$($Args[0])`\"\"«»)
#On réutilise le code du setter
#(ici on est certains de ne récupérer qu'un seul élément).
$Setter=@($this.PsObject.Properties.Match(\"PropertyName\"«»))[0]
#On supprime la propriété actuelle.
[void]$this.PsObject.Properties.Remove(\"PropertyName\"«»)
#Puis on la reconstruit dynamiquement.
$ANewMySelf=New-Object System.Management.Automation.PSScriptProperty(\"PropertyName\",`
$Getter,$Setter.SetterScript)
[void]$this.PsObject.Properties.Add($ANewMySelf)
} -Passthru
} # DemoDynamic
[/code:1]
Un exemple d'utilisation :
[code:1]
cd $env:temp
#construit l'objet
$Factory= DemoDynamic
$Aujourdhui=(get-date -format ((Get-Culture).DateTimeFormat.ShortDatePattern))
$FiltreThisDate=$Factory.ThisDate($Aujourdhui)
Get-Childitem \"$pwd\"|Where $FiltreThisDate|Select Name,\"$($Factory.PropertyName)\"
#On paramètre le générateur de filtre avec une nouvelle propriété
$Factory.PropertyName=\"LastWriteTime\"
$FiltreThisDate2=$Factory.ThisDate($Aujourdhui)
Get-Childitem \"$pwd\"|Where $FiltreThisDate2|Select Name,\"$($Factory.PropertyName)\"
[/code:1]
On peut ajouter une clause Where pour filtrer le type du fichier :
[code:1]
Get-Childitem \"$pwd\"|Where {!$_.psIsContainer}|Where $FiltreThisDate2 |Select Name,\"$($Factory.PropertyName)\"
[/code:1]
Reste à construire ce générateur de filtres.<br><br>Message édité par: Laurent Dardenne, à: 2/02/10 16:10
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6311
- Remerciements reçus 68
il y a 16 ans 1 mois #6090
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Re:Comment construire un objet qui construit du code?
Voici le code du générateur de scriptbloc filtrant des objets sur une propriété de type date :
[code:1]
Function New-FactoryFilterDate( [string] $PropertyName,
[type] $Class,
[switch] $Force) {
#
# Crée un objet générateur de filtres de recherche.
# Les filtres sont basés sur une propriété, de type date, d'un objet
# de n'importe quelle classe (sauf les classes WMI).
# Pour WMI mieux vaut filtrer les instances à l'adie de WQL.
#
#
#Paramètres : Aucun
#
#Cette fonction renvoie un objet de type PSObject, ses membres sont :
# Propriétés :
#
# PropertyName : [String]. Nom de la propriété contenant la date de recherche.
# Comme on utilise des méthodes du framework dotnet,
# faites attention à la casse du nom !
# Son contenu est utilisé en interne uniquement lors de la création d'un scriptblock de recherche.
# Valeur par défaut : CreationTime
#
# Class : [Type]. Nom de la classe contenant la propriété $PropertyName.
# Son contenu est utilisé en interne pour vérifier si la propriété
# $PropertyName existe bien dans la classe ciblée par un des filtres.
# Valeur par défaut : [System.IO.FileSystemInfo]
#
# Force : [Boolean]. A utiliser si la propriété référence un membre synthétique.
# Dans ce cas, on ne teste pas l'existence de ce membre dans la classe,
# de plus le respect de la casse du nom de propriété n'est plus nécessaire.
# Valeur par défaut : False
#
# Description : [String]. Contient le nom de la propriété et le nom de la classe en cours.
#
#
# Méthodes
#
# La pluspart renvoient un scriptblock pouvant être utilisé avec Where-Object.
#
# ThisDate : Recherche les fichiers de la date spécifiée. Les deux opérandes sont de type String.
# Attend un argument de type string contenant une date au format de la culture en cours.
# Fr = \"28/12/2009\"
#
# TheseDates : Recherche les fichiers des dates spécifiées. Les deux opérandes sont de type String.
# Attend un argument de type string contenant une regex référençant des dates au format de la culture en cours.
# Fr : \"(^30/12/2009|^15/01/2009)\" Us : \"(^12/30/2009|^1/15/2009)\"
#
# AfterThisDate : Recherche les fichiers postérieurs ou égaux à la date spécifiée. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif ou zéro. Cf. Notes
#
# BeforeThisDate : Recherche les fichiers antérieurs la date spécifiée. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif ou zéro. Cf. Notes
#
# LastMinutes : Recherche les fichiers agés de n minutes. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# LastHours : Recherche les fichiers agés de n heures. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# LastMonths : Recherche les fichiers agés de n mois. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# LastYears : Recherche les fichiers agés de n années. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# Combine : Crée un filtre contenant plusieurs clauses combinées et utilisant l'opérateur -or
# Attend un argument de type tableau de scriptblock.
#
# ToString : Renvoi une string résultant de l'appel à ThisDate paramétré avec la date du jour.
#
# Set : Affecte une ou plusieurs propriété en une passe.
# L'ordre de passage des paramètres est le suivant :
# PropertyName : [string] ou le résultat de Object.ToString()
# Class : [string] ou [type]
# Force : [string] ou [Boolean]
#
# ReBuildProperty : Méthode privée, ne pas l'utiliser.
#
# Exemples :
# $Filtre= New-FilterDateFile
# #renvoi un scriptblock par défaut
# $sb=$ExecutionContext.InvokeCommand.NewScriptBlock(\"$filtre\"«»)
# Get-Childitem \"$pwd\"|Where $sb|Select Name,\"$($Filtre.PropertyName)\"
#
# #Filtre les fichiers d'il y a une semaine.
# $AfterThisDate=$Filtre.AfterThisDate(-7)
# $AfterThisDate #affiche le code du scriptblock
# Get-Childitem \"$pwd\"|Where $AfterThisDate|Select Name, \"CreationTime\"
#
# #Filtre les fichiers créés le 25 octobre 2009 et ceux créés le 31 octobre 2009
# $TheseDates=$Filtre.TheseDates(\"(^25/10/2009|^31/10/2009)\"«»)
# Get-Childitem \"$pwd\"|Where $TheseDates|Select Name,\"CreationTime\"
#
# #Filtre les fichiers créés le 30 décembre 2009.
# $ThisDate=$Filtre.ThisDate(\"30/12/2009\"«»)
# #Filtre les fichiers créés :
# # Il y a une semaine,
# # ceux du 25 octobre 2009 et ceux du 31 octobre 2009.
# $FiltrePlusieursDates=$Filtre.Combine( @($AfterThisDate, $TheseDates))
# Get-Childitem \"$pwd\"|Where $FiltrePlusieursDates |Select Name,\"CreationTime\"
#
# #Modifie l'ensemble des champs du générateur de filtre.
# $Filtre.Set(\"TimeGenerated\",\"System.Diagnostics.EventLogEntry\",$False)
#
#Note:
# Suppose lors de la recherche que la date du PC est bien le jour calendaire courant.
# Le validité des scriptblocks ne sera connue que lors de son exécution.
# Code généré (Fr) \"'{0:dd/MM/yyyy}' -f `$_.CreationTime -eq '$($Args[0])'\"
# Renvoie lors de l'appel {'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '28/12/2009'}
#On récupère la culture du thread et pas celle du poste.
#Ainsi, lors de l'appel de la création du code, on adapte la localisation au contexte d'exécution
$ThisDate=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"'{0:`$([System.Threading.Thread]::CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern)}' -f ```$_.`$(`$this.PropertyName)\"+\" -eq '`$(`$Args[0])'`\"«»)\"
#On construit dynamiquement du code de création d'un scriptblock
#Le code généré contient l'appel de création d'un scriptblock dont
# le contenu est définie dynamiquement.
#Comme il y a deux niveaux de substition on doit tripler le caractère backtick.
#ce code génére :
# $ExecutionContext.InvokeCommand.NewScriptBlock(\"`$_.MypropertyName\"}
$CodeNewSB=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"```$_.`$(`$this.PropertyName)\"
# Code généré \"`$_.LastWriteTime -match '$($Args[0])'\"
# renvoie lors de l'appel {$_.LastWriteTime -match \"(^10/07/2009|^10/31/2009)\"}
#Conversion explicite de PropertyName afin d'utiliser les informations de la culture courante
#Si on utilise une conversion implicite, PowerShell utilise la culture invariant, c'est-à-dire US.
$TheseDates=$CodeNewSB+\".ToString() -match '`$(`$Args[0])'`\"«»)\"
$AfterThisDate=$CodeNewSB+\" -ge [DateTime]::Today.Adddays(`$(`$Args[0]))`\"«»)\"
$BeforeThisDate=$CodeNewSB+\" -lt [DateTime]::Today.Adddays(`$(`$Args[0]))`\"«»)\"
$LastMinutes=$CodeNewSB+\" -ge [DateTime]::Now.AddMinutes(`$(`$Args[0]))`\"«»)\"
$LastHours=$CodeNewSB+\" -ge [DateTime]::Now.AddHours(`$(`$Args[0]))`\"«»)\"
$LastMonths=$CodeNewSB+\" -ge [DateTime]::Now.AddMonths(`$(`$Args[0]))`\"«»)\"
$LastYears=$CodeNewSB+\" -ge [DateTime]::Now.AddYears(`$(`$Args[0]))`\"«»)\"
#Construction dynamique du code de création de l'objet Filtre
#La plupart des méthodes renvoient un scriptblock
$MakeFilter=@\"
New-Object PSObject|
#Args[0] attend une string contenant une date dans le format
# de la culture courante. Fr = \"28/12/2009\"
Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru|
#Args[0] attend une string contenant une regex référençant des dates dans le format
# de la culture courante. Fr = \"(^31/10/2009|^13/12/2009)\"
Add-Member ScriptMethod TheseDates -value {$TheseDates} -Passthru|
#Args[0] attend un entier négatif ou zéro.
Add-Member ScriptMethod AfterThisDate -value {$AfterThisDate} -Passthru|
#Args[0] attend un entier négatif ou zéro.
Add-Member ScriptMethod BeforeThisDate -value {$BeforeThisDate} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastMinutes -value {$LastMinutes} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastHours -value {$LastHours} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastMonths -value {$LastMonths} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastYears -value {$LastYears} -Passthru|
#Combine deux scriptblocs (créés ou pas par ce générateur)
#La condition de recherche des scriptblokss combinés se base sur un -OR
Add-Member ScriptMethod Combine -value { `$ArraySB=`$Args[0] -as [String[]]|% {\"(`$_)\"}
`$Local:Ofs=\" -or \"
`$sb=`$ExecutionContext.InvokeCommand.NewScriptBlock(\"`$ArraySB\"«»)
`$sb
} -Passthru|
Add-Member ScriptProperty Description -Value {\"Générateur de filtre de recherche sur une date, utilisant la propriété `$(`$this.PropertyName) de la la classe [`$(`$this.Class)].`r`nCe filtre peut être utilisé avec Where-Object.\"} -Passthru
\"@
#Exécution du code de création de l'objet Filtre
$Object=Invoke-Expression $MakeFilter
#Ajoute des propriétés \"dynamiques\",
#A chaque affectation elle se recrée.
#Les valeurs ne peuvent être que d'un type scalaire.
$Object=$Object|Add-Member ScriptMethod ReBuildProperty -value {
#On modifie la valeur du getter
$Getter=$ExecutionContext.InvokeCommand.NewScriptBlock($Args[1])
#On réutilise le code du setter
#(ici on est certains de ne récupérer qu'un seul élément).
$Setter=($this.PsObject.Properties.Match($Args[0]))[0]
#On supprime le membre actuel.
[void]$this.PsObject.Properties.Remove($Args[0])
#Puis on le reconstruit dynamiquement.
$ANewMySelf=New-Object System.Management.Automation.PSScriptProperty($Args[0],$Getter,$Setter.SetterScript)
[void]$this.PsObject.Properties.Add($ANewMySelf)
} -Passthru|
#Args[0] attend une string non $null ni vide.
Add-Member ScriptProperty PropertyName -value {\"CreationTime\"} -SecondValue {
if ([string]::IsNullOrEmpty($args[0]) )
{Throw \"La propriété PropertyName doit être renseignée.\"}
if (!$this.Force)
{ #Contrôle l'existence du nom de propriété
$PropertyInfo=($this.Class).GetMember($Args[0])
if ($PropertyInfo.Count -eq 0)
{Throw \"La propriété $($Args[0]) n'existe pas dans la classe $(($this.Class).ToString()).\"}
elseif ($PropertyInfo[0].PropertyType -ne [System.DateTime])
{Throw \"La valeur affectée à la propriété Propertyname ($($Args[0])) doit être une propriété du type [System.DateTime].\"}
}
$this.ReBuildProperty(\"PropertyName\", \"`\"$($Args[0])`\"\"«»)
} -Passthru|
#Args[0] attend un type.
Add-Member ScriptProperty Class -value {[System.IO.FileSystemInfo]} -SecondValue {
if ($Args[0] -isnot [Type])
{Throw \"La valeur affectée à la propriété Class ($($Args[0])) doit être un nom de type, tel que [System.IO.FileSystemInfo].\"}
$this.ReBuildProperty(\"Class\", \"[$($Args[0] -as [String])]\"«»)
} -Passthru|
#Args[0] attend un boolean.
Add-Member ScriptProperty Force -value {$false} -SecondValue {
if ($Args[0] -isnot [Boolean])
{Throw \"La valeur affectée à la propriété à la propriété Force ($($Args[0])) doit être de type [boolean].\"}
$this.ReBuildProperty(\"Force\", \"`$$($Args[0].ToString())\"«»)
} -Passthru|
Add-Member -Force -MemberType ScriptMethod ToString {
$this.ThisDate((get-date -format ([System.Threading.Thread]::CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern)))
} -PassThru|
#Attend 1, 2 ou 3 paramètres
Add-Member ScriptMethod Set {
if (![string]::IsNullOrEmpty($args[1]))
{ $this.Class=$args[1] -as [Type]}
if (![string]::IsNullOrEmpty($args[0]))
{$this.PropertyName=$args[0] -as [string]}
if (![string]::IsNullOrEmpty($args[2]))
{$this.Force=$args[2] -as [boolean]}
} -PassThru
$Object.Set($PropertyName,$Class,$Force.IsPresent)
$Object
}
[/code:1]
Quelques exemples d'utilisation :
[code:1]
#Crée un générateur de filtre de date
#Par défaut on manipule : [System.IO.FileSystemInfo].CreationTime
$Filtre= New-FactoryFilterDate ; $Filtre
#Crée un filtre recherchant les fichiers
#de la semaine dernière
$AfterThisDate1=$Filtre.AfterThisDate(-7)
#On utilise une autre propriété de
#la classe [System.IO.FileSystemInfo]
$Filtre.PropertyName=\"LastWriteTime\"
$AfterThisDate2=$Filtre.AfterThisDate(-7)
$AfterThisDate1;$AfterThisDate2
cd $env:Temp
Dir|Where $AfterThisDate1
Dir|Where $AfterThisDate2
#crée un scriptblock contenant le résultat de l'appel à
# ThisDate qui est paramétré avec la date du jour.
$sbDefault=$ExecutionContext.InvokeCommand.NewScriptBlock(\"$Filtre\"«») ; $sbDefault
#Crée un générateur de filtre de date
#on précise la classe et la propriété ciblée.
$Filtre= New-FactoryFilterDate \"StartTime\" \"System.Diagnostics.Process\" ; $Filtre
Notepad
$LastMinutes=$Filtre.LastMinutes(-3)
Get-Process |Where-Object $LastMinutes
#Modifie les propriétes d'un objet filtre
$Filtre.Set(\"TimeGenerated\",\"System.Diagnostics.EventLogEntry\",$False) ; $Filtre
# #Filtre les fichiers créés le 10 janvier 2010 et ceux créés le 2 février 2010
Get-Eventlog Application|Where-Object $Filtre.TheseDates(\"(^10/01/2010|^02/02/2010)\"«»)
#Cette appel fonctionne, mais aucun contrôle n'est alors
# effectué sur la valeur de l'argument
#$Filtre.ReBuildProperty(\"Force\",\"Test\"«»)
[/code:1]
Ensuite il est possible de créer des librairies de filtres :
[code:1]
function New-FilterLib($Factory) {
#Construit une librairie de Scritpblock,
# contenant des filtres de date.
$Lib=@{}
$PatternDate=\"{0:$((Get-Culture).DateTimeFormat.ShortDatePattern)}\"
#Date et heure de génération de cette librairie.
$Lib.CreationTime=[system.DateTime]::Now
#Classe et propriété utilisé lors de la génération de cette librairie.
$Lib.Target=\"[$($Factory.Class)].$($Factory.PropertyName)\"
#Attention aux traitements démarrés peu avant minuit et se finissant le lendemain.
$Lib.Today= $Factory.ThisDate($PatternDate -F [system.DateTime]::Today )
$Lib.Tomorrow=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddDays(1))
$Lib.Yesterday=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddDays(-1))
$Lib.BeforeYesterday=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddDays(-2))
#Si le jour courant (Fr) est lundi on renvoie lundi, mais
# pas le jour de la semaine dernière AddDays(-7)
$Lib.FirstDayOfThisWeek=$Factory.ThisDate($PatternDate -F $(
$Date=[system.DateTime]::Today
$DayOfWeek=[int][system.DateTime]::Today.DayOfWeek
$FirstDayOfWeek=[int]([System.Threading.Thread]::CurrentThread.CurrentCulture).DateTimeFormat.FirstDayOfWeek
$Diff = $DayOfWeek - $FirstDayOfWeek
if ($Diff -lt 0)
{ $Diff += 7 }
$Date.AddDays(-1 * $diff).Date
))
$Lib.LastDayOfThisMonth= $Factory.ThisDate($PatternDate -F $(
$now=[System.DateTime]::Now
$nbDays = [System.DateTime]::«»DaysInMonth($Now.Year,$Now.Month)
new-object System.DateTime($now.Year, $now.Month, $nbDays, 0, 0, 0,0)
))
$Lib.FirstDayOfThisMonth=$Factory.ThisDate($PatternDate -F $(
$Today=[System.DateTime]::Today
$Today.AddDays(-($Today.Day - 1))
))
$Lib.OneMonthBefore=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddMonths(-1))
$Lib
}
[/code:1]
La génération des filtres s'adapte à la date en cours lors de la création :
[code:1]
$FileInfoLib= New-FilterLib (New-FactoryFilterDate)
$FileInfoLib
Dir |Where $FileInfoLib.Today
$EventLogLib= New-FilterLib (New-FactoryFilterDate \"TimeGenerated\" \"System.Diagnostics.EventLogEntry\"«»)
$EventLogLib
Get-EventLog Application|Where $EventLogLib.Today
[/code:1]
Une fonction d'aide :
[code:1]
function Get-PropertiesDateTime([Type] $Class){
#Retrouve les propriétés de type date d'une classe
#renvoi une hashtable : $H.NomClass.[Propriétés]
$PropertiesOfType=@{}
$PropertiesOfType.\"$($Class.Name)\"=@( $Class.getmembers()|
Where {($_.MemberType -eq \"property\"«») -and ($_.propertytype -eq [Datetime])}|
Foreach {$_.Name})
$PropertiesOfType
}
$p=Get-PropertiesDateTime \"Microsoft.PowerShell.Commands.HistoryInfo\"
$p+=Get-PropertiesDateTime \"System.Diagnostics.EventLogEntry\"
$p
[/code:1]
Une fois ce code crée on peut également crée une fonction spécialisée de recherche de fichier, voir avec la version 2 créer un proxy basé sur Get-ChildItem.
[code:1]
Function New-FactoryFilterDate( [string] $PropertyName,
[type] $Class,
[switch] $Force) {
#
# Crée un objet générateur de filtres de recherche.
# Les filtres sont basés sur une propriété, de type date, d'un objet
# de n'importe quelle classe (sauf les classes WMI).
# Pour WMI mieux vaut filtrer les instances à l'adie de WQL.
#
#
#Paramètres : Aucun
#
#Cette fonction renvoie un objet de type PSObject, ses membres sont :
# Propriétés :
#
# PropertyName : [String]. Nom de la propriété contenant la date de recherche.
# Comme on utilise des méthodes du framework dotnet,
# faites attention à la casse du nom !
# Son contenu est utilisé en interne uniquement lors de la création d'un scriptblock de recherche.
# Valeur par défaut : CreationTime
#
# Class : [Type]. Nom de la classe contenant la propriété $PropertyName.
# Son contenu est utilisé en interne pour vérifier si la propriété
# $PropertyName existe bien dans la classe ciblée par un des filtres.
# Valeur par défaut : [System.IO.FileSystemInfo]
#
# Force : [Boolean]. A utiliser si la propriété référence un membre synthétique.
# Dans ce cas, on ne teste pas l'existence de ce membre dans la classe,
# de plus le respect de la casse du nom de propriété n'est plus nécessaire.
# Valeur par défaut : False
#
# Description : [String]. Contient le nom de la propriété et le nom de la classe en cours.
#
#
# Méthodes
#
# La pluspart renvoient un scriptblock pouvant être utilisé avec Where-Object.
#
# ThisDate : Recherche les fichiers de la date spécifiée. Les deux opérandes sont de type String.
# Attend un argument de type string contenant une date au format de la culture en cours.
# Fr = \"28/12/2009\"
#
# TheseDates : Recherche les fichiers des dates spécifiées. Les deux opérandes sont de type String.
# Attend un argument de type string contenant une regex référençant des dates au format de la culture en cours.
# Fr : \"(^30/12/2009|^15/01/2009)\" Us : \"(^12/30/2009|^1/15/2009)\"
#
# AfterThisDate : Recherche les fichiers postérieurs ou égaux à la date spécifiée. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif ou zéro. Cf. Notes
#
# BeforeThisDate : Recherche les fichiers antérieurs la date spécifiée. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif ou zéro. Cf. Notes
#
# LastMinutes : Recherche les fichiers agés de n minutes. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# LastHours : Recherche les fichiers agés de n heures. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# LastMonths : Recherche les fichiers agés de n mois. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# LastYears : Recherche les fichiers agés de n années. Les deux opérandes sont de type DateTime.
# Attend un argument de type entier, négatif. Cf. Notes
#
# Combine : Crée un filtre contenant plusieurs clauses combinées et utilisant l'opérateur -or
# Attend un argument de type tableau de scriptblock.
#
# ToString : Renvoi une string résultant de l'appel à ThisDate paramétré avec la date du jour.
#
# Set : Affecte une ou plusieurs propriété en une passe.
# L'ordre de passage des paramètres est le suivant :
# PropertyName : [string] ou le résultat de Object.ToString()
# Class : [string] ou [type]
# Force : [string] ou [Boolean]
#
# ReBuildProperty : Méthode privée, ne pas l'utiliser.
#
# Exemples :
# $Filtre= New-FilterDateFile
# #renvoi un scriptblock par défaut
# $sb=$ExecutionContext.InvokeCommand.NewScriptBlock(\"$filtre\"«»)
# Get-Childitem \"$pwd\"|Where $sb|Select Name,\"$($Filtre.PropertyName)\"
#
# #Filtre les fichiers d'il y a une semaine.
# $AfterThisDate=$Filtre.AfterThisDate(-7)
# $AfterThisDate #affiche le code du scriptblock
# Get-Childitem \"$pwd\"|Where $AfterThisDate|Select Name, \"CreationTime\"
#
# #Filtre les fichiers créés le 25 octobre 2009 et ceux créés le 31 octobre 2009
# $TheseDates=$Filtre.TheseDates(\"(^25/10/2009|^31/10/2009)\"«»)
# Get-Childitem \"$pwd\"|Where $TheseDates|Select Name,\"CreationTime\"
#
# #Filtre les fichiers créés le 30 décembre 2009.
# $ThisDate=$Filtre.ThisDate(\"30/12/2009\"«»)
# #Filtre les fichiers créés :
# # Il y a une semaine,
# # ceux du 25 octobre 2009 et ceux du 31 octobre 2009.
# $FiltrePlusieursDates=$Filtre.Combine( @($AfterThisDate, $TheseDates))
# Get-Childitem \"$pwd\"|Where $FiltrePlusieursDates |Select Name,\"CreationTime\"
#
# #Modifie l'ensemble des champs du générateur de filtre.
# $Filtre.Set(\"TimeGenerated\",\"System.Diagnostics.EventLogEntry\",$False)
#
#Note:
# Suppose lors de la recherche que la date du PC est bien le jour calendaire courant.
# Le validité des scriptblocks ne sera connue que lors de son exécution.
# Code généré (Fr) \"'{0:dd/MM/yyyy}' -f `$_.CreationTime -eq '$($Args[0])'\"
# Renvoie lors de l'appel {'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '28/12/2009'}
#On récupère la culture du thread et pas celle du poste.
#Ainsi, lors de l'appel de la création du code, on adapte la localisation au contexte d'exécution
$ThisDate=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"'{0:`$([System.Threading.Thread]::CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern)}' -f ```$_.`$(`$this.PropertyName)\"+\" -eq '`$(`$Args[0])'`\"«»)\"
#On construit dynamiquement du code de création d'un scriptblock
#Le code généré contient l'appel de création d'un scriptblock dont
# le contenu est définie dynamiquement.
#Comme il y a deux niveaux de substition on doit tripler le caractère backtick.
#ce code génére :
# $ExecutionContext.InvokeCommand.NewScriptBlock(\"`$_.MypropertyName\"}
$CodeNewSB=\"`$ExecutionContext.InvokeCommand.NewScriptBlock(`\"```$_.`$(`$this.PropertyName)\"
# Code généré \"`$_.LastWriteTime -match '$($Args[0])'\"
# renvoie lors de l'appel {$_.LastWriteTime -match \"(^10/07/2009|^10/31/2009)\"}
#Conversion explicite de PropertyName afin d'utiliser les informations de la culture courante
#Si on utilise une conversion implicite, PowerShell utilise la culture invariant, c'est-à-dire US.
$TheseDates=$CodeNewSB+\".ToString() -match '`$(`$Args[0])'`\"«»)\"
$AfterThisDate=$CodeNewSB+\" -ge [DateTime]::Today.Adddays(`$(`$Args[0]))`\"«»)\"
$BeforeThisDate=$CodeNewSB+\" -lt [DateTime]::Today.Adddays(`$(`$Args[0]))`\"«»)\"
$LastMinutes=$CodeNewSB+\" -ge [DateTime]::Now.AddMinutes(`$(`$Args[0]))`\"«»)\"
$LastHours=$CodeNewSB+\" -ge [DateTime]::Now.AddHours(`$(`$Args[0]))`\"«»)\"
$LastMonths=$CodeNewSB+\" -ge [DateTime]::Now.AddMonths(`$(`$Args[0]))`\"«»)\"
$LastYears=$CodeNewSB+\" -ge [DateTime]::Now.AddYears(`$(`$Args[0]))`\"«»)\"
#Construction dynamique du code de création de l'objet Filtre
#La plupart des méthodes renvoient un scriptblock
$MakeFilter=@\"
New-Object PSObject|
#Args[0] attend une string contenant une date dans le format
# de la culture courante. Fr = \"28/12/2009\"
Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru|
#Args[0] attend une string contenant une regex référençant des dates dans le format
# de la culture courante. Fr = \"(^31/10/2009|^13/12/2009)\"
Add-Member ScriptMethod TheseDates -value {$TheseDates} -Passthru|
#Args[0] attend un entier négatif ou zéro.
Add-Member ScriptMethod AfterThisDate -value {$AfterThisDate} -Passthru|
#Args[0] attend un entier négatif ou zéro.
Add-Member ScriptMethod BeforeThisDate -value {$BeforeThisDate} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastMinutes -value {$LastMinutes} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastHours -value {$LastHours} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastMonths -value {$LastMonths} -Passthru|
#Args[0] attend un entier négatif.
Add-Member ScriptMethod LastYears -value {$LastYears} -Passthru|
#Combine deux scriptblocs (créés ou pas par ce générateur)
#La condition de recherche des scriptblokss combinés se base sur un -OR
Add-Member ScriptMethod Combine -value { `$ArraySB=`$Args[0] -as [String[]]|% {\"(`$_)\"}
`$Local:Ofs=\" -or \"
`$sb=`$ExecutionContext.InvokeCommand.NewScriptBlock(\"`$ArraySB\"«»)
`$sb
} -Passthru|
Add-Member ScriptProperty Description -Value {\"Générateur de filtre de recherche sur une date, utilisant la propriété `$(`$this.PropertyName) de la la classe [`$(`$this.Class)].`r`nCe filtre peut être utilisé avec Where-Object.\"} -Passthru
\"@
#Exécution du code de création de l'objet Filtre
$Object=Invoke-Expression $MakeFilter
#Ajoute des propriétés \"dynamiques\",
#A chaque affectation elle se recrée.
#Les valeurs ne peuvent être que d'un type scalaire.
$Object=$Object|Add-Member ScriptMethod ReBuildProperty -value {
#On modifie la valeur du getter
$Getter=$ExecutionContext.InvokeCommand.NewScriptBlock($Args[1])
#On réutilise le code du setter
#(ici on est certains de ne récupérer qu'un seul élément).
$Setter=($this.PsObject.Properties.Match($Args[0]))[0]
#On supprime le membre actuel.
[void]$this.PsObject.Properties.Remove($Args[0])
#Puis on le reconstruit dynamiquement.
$ANewMySelf=New-Object System.Management.Automation.PSScriptProperty($Args[0],$Getter,$Setter.SetterScript)
[void]$this.PsObject.Properties.Add($ANewMySelf)
} -Passthru|
#Args[0] attend une string non $null ni vide.
Add-Member ScriptProperty PropertyName -value {\"CreationTime\"} -SecondValue {
if ([string]::IsNullOrEmpty($args[0]) )
{Throw \"La propriété PropertyName doit être renseignée.\"}
if (!$this.Force)
{ #Contrôle l'existence du nom de propriété
$PropertyInfo=($this.Class).GetMember($Args[0])
if ($PropertyInfo.Count -eq 0)
{Throw \"La propriété $($Args[0]) n'existe pas dans la classe $(($this.Class).ToString()).\"}
elseif ($PropertyInfo[0].PropertyType -ne [System.DateTime])
{Throw \"La valeur affectée à la propriété Propertyname ($($Args[0])) doit être une propriété du type [System.DateTime].\"}
}
$this.ReBuildProperty(\"PropertyName\", \"`\"$($Args[0])`\"\"«»)
} -Passthru|
#Args[0] attend un type.
Add-Member ScriptProperty Class -value {[System.IO.FileSystemInfo]} -SecondValue {
if ($Args[0] -isnot [Type])
{Throw \"La valeur affectée à la propriété Class ($($Args[0])) doit être un nom de type, tel que [System.IO.FileSystemInfo].\"}
$this.ReBuildProperty(\"Class\", \"[$($Args[0] -as [String])]\"«»)
} -Passthru|
#Args[0] attend un boolean.
Add-Member ScriptProperty Force -value {$false} -SecondValue {
if ($Args[0] -isnot [Boolean])
{Throw \"La valeur affectée à la propriété à la propriété Force ($($Args[0])) doit être de type [boolean].\"}
$this.ReBuildProperty(\"Force\", \"`$$($Args[0].ToString())\"«»)
} -Passthru|
Add-Member -Force -MemberType ScriptMethod ToString {
$this.ThisDate((get-date -format ([System.Threading.Thread]::CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern)))
} -PassThru|
#Attend 1, 2 ou 3 paramètres
Add-Member ScriptMethod Set {
if (![string]::IsNullOrEmpty($args[1]))
{ $this.Class=$args[1] -as [Type]}
if (![string]::IsNullOrEmpty($args[0]))
{$this.PropertyName=$args[0] -as [string]}
if (![string]::IsNullOrEmpty($args[2]))
{$this.Force=$args[2] -as [boolean]}
} -PassThru
$Object.Set($PropertyName,$Class,$Force.IsPresent)
$Object
}
[/code:1]
Quelques exemples d'utilisation :
[code:1]
#Crée un générateur de filtre de date
#Par défaut on manipule : [System.IO.FileSystemInfo].CreationTime
$Filtre= New-FactoryFilterDate ; $Filtre
#Crée un filtre recherchant les fichiers
#de la semaine dernière
$AfterThisDate1=$Filtre.AfterThisDate(-7)
#On utilise une autre propriété de
#la classe [System.IO.FileSystemInfo]
$Filtre.PropertyName=\"LastWriteTime\"
$AfterThisDate2=$Filtre.AfterThisDate(-7)
$AfterThisDate1;$AfterThisDate2
cd $env:Temp
Dir|Where $AfterThisDate1
Dir|Where $AfterThisDate2
#crée un scriptblock contenant le résultat de l'appel à
# ThisDate qui est paramétré avec la date du jour.
$sbDefault=$ExecutionContext.InvokeCommand.NewScriptBlock(\"$Filtre\"«») ; $sbDefault
#Crée un générateur de filtre de date
#on précise la classe et la propriété ciblée.
$Filtre= New-FactoryFilterDate \"StartTime\" \"System.Diagnostics.Process\" ; $Filtre
Notepad
$LastMinutes=$Filtre.LastMinutes(-3)
Get-Process |Where-Object $LastMinutes
#Modifie les propriétes d'un objet filtre
$Filtre.Set(\"TimeGenerated\",\"System.Diagnostics.EventLogEntry\",$False) ; $Filtre
# #Filtre les fichiers créés le 10 janvier 2010 et ceux créés le 2 février 2010
Get-Eventlog Application|Where-Object $Filtre.TheseDates(\"(^10/01/2010|^02/02/2010)\"«»)
#Cette appel fonctionne, mais aucun contrôle n'est alors
# effectué sur la valeur de l'argument
#$Filtre.ReBuildProperty(\"Force\",\"Test\"«»)
[/code:1]
Ensuite il est possible de créer des librairies de filtres :
[code:1]
function New-FilterLib($Factory) {
#Construit une librairie de Scritpblock,
# contenant des filtres de date.
$Lib=@{}
$PatternDate=\"{0:$((Get-Culture).DateTimeFormat.ShortDatePattern)}\"
#Date et heure de génération de cette librairie.
$Lib.CreationTime=[system.DateTime]::Now
#Classe et propriété utilisé lors de la génération de cette librairie.
$Lib.Target=\"[$($Factory.Class)].$($Factory.PropertyName)\"
#Attention aux traitements démarrés peu avant minuit et se finissant le lendemain.
$Lib.Today= $Factory.ThisDate($PatternDate -F [system.DateTime]::Today )
$Lib.Tomorrow=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddDays(1))
$Lib.Yesterday=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddDays(-1))
$Lib.BeforeYesterday=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddDays(-2))
#Si le jour courant (Fr) est lundi on renvoie lundi, mais
# pas le jour de la semaine dernière AddDays(-7)
$Lib.FirstDayOfThisWeek=$Factory.ThisDate($PatternDate -F $(
$Date=[system.DateTime]::Today
$DayOfWeek=[int][system.DateTime]::Today.DayOfWeek
$FirstDayOfWeek=[int]([System.Threading.Thread]::CurrentThread.CurrentCulture).DateTimeFormat.FirstDayOfWeek
$Diff = $DayOfWeek - $FirstDayOfWeek
if ($Diff -lt 0)
{ $Diff += 7 }
$Date.AddDays(-1 * $diff).Date
))
$Lib.LastDayOfThisMonth= $Factory.ThisDate($PatternDate -F $(
$now=[System.DateTime]::Now
$nbDays = [System.DateTime]::«»DaysInMonth($Now.Year,$Now.Month)
new-object System.DateTime($now.Year, $now.Month, $nbDays, 0, 0, 0,0)
))
$Lib.FirstDayOfThisMonth=$Factory.ThisDate($PatternDate -F $(
$Today=[System.DateTime]::Today
$Today.AddDays(-($Today.Day - 1))
))
$Lib.OneMonthBefore=$Factory.ThisDate($PatternDate -F [system.DateTime]::Today.AddMonths(-1))
$Lib
}
[/code:1]
La génération des filtres s'adapte à la date en cours lors de la création :
[code:1]
$FileInfoLib= New-FilterLib (New-FactoryFilterDate)
$FileInfoLib
Dir |Where $FileInfoLib.Today
$EventLogLib= New-FilterLib (New-FactoryFilterDate \"TimeGenerated\" \"System.Diagnostics.EventLogEntry\"«»)
$EventLogLib
Get-EventLog Application|Where $EventLogLib.Today
[/code:1]
Une fonction d'aide :
[code:1]
function Get-PropertiesDateTime([Type] $Class){
#Retrouve les propriétés de type date d'une classe
#renvoi une hashtable : $H.NomClass.[Propriétés]
$PropertiesOfType=@{}
$PropertiesOfType.\"$($Class.Name)\"=@( $Class.getmembers()|
Where {($_.MemberType -eq \"property\"«») -and ($_.propertytype -eq [Datetime])}|
Foreach {$_.Name})
$PropertiesOfType
}
$p=Get-PropertiesDateTime \"Microsoft.PowerShell.Commands.HistoryInfo\"
$p+=Get-PropertiesDateTime \"System.Diagnostics.EventLogEntry\"
$p
[/code:1]
Une fois ce code crée on peut également crée une fonction spécialisée de recherche de fichier, voir avec la version 2 créer un proxy basé sur Get-ChildItem.
La pièce jointe New_FactoryFilterDate.zip est absente ou indisponible
Tutoriels PowerShell
Pièces jointes :
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6311
- Remerciements reçus 68
il y a 16 ans 1 mois #6132
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Re:Comment construire un objet qui construit du code?
Une fois le générateur créé on peut spécialiser sous PS v2 le cmdlet Get-ChildItem.
On utilise la possibilité de créer un Proxy de cmdlet :
[code:1]
Function Get-ChildItemProxy {
[CmdletBinding(DefaultParameterSetName='Items', SupportsTransactions=$true)]
param(
[Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
#A l'origine 'Items' et 'LiteralItems' sont mutuellement exclusifs.
#'Container' et 'NoContainer' le sont également, mais il ne peut y avoir qu'un
#seul niveau d'exclusion mutuelle. On place donc cette exclusion sur
#les nouveaux switchs, et on laisse le cmdlet encapsulé gérer l'exclusion d'origine.
#Ce qui fait que le binding réussi dans le proxy, mais générera une erreur lors
#de l'appel au cmdlet encapsulé.
#Autre solution tester, à l'aide d'un If, la présence simultanée des 2 switchs
# 'Container' et 'NoContainer'.
# [Parameter(ParameterSetName='Container')] #Ajout.
# [Parameter(ParameterSetName='NoContainer')] #Ajout
[System.String[]]
${Path},
[Parameter(ParameterSetName='LiteralItems', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
# [Parameter(ParameterSetName='Container')] #Ajout
# [Parameter(ParameterSetName='NoContainer')] #Ajout
[Alias('PSPath')]
[System.String[]]
${LiteralPath},
[Parameter(Position=1)]
[System.String]
${Filter},
[System.String[]]
${Include},
[System.String[]]
${Exclude},
[ValidateNotNullOrEmpty()]
[System.Management.Automation.ScriptBlock] #nouveau
${DateFilterBlock},
[Switch]
${Recurse},
[Switch]
${Force},
[Switch]
${Name},
#Jeux de paramètres exclusifs :
# soit Container soit NoContainer
# [Parameter(ParameterSetName='Container')]
# [Parameter(ParameterSetName='ContainerOnly')]
[Switch] #nouveau. On traite uniquement les répertoires
${ContainersOnly},
# [Parameter(ParameterSetName='Container')]
# [Parameter(ParameterSetName='NoContainerOnly')]
[Switch] #nouveau. On traite uniquement les fichiers
${NoContainersOnly}
)
begin
{
Write-Debug \"[Begin]\"
if ($ContainersOnly -and $NoContainersOnly)
{
$assembly=[appdomain]::currentdomain.GetAssemblies()|Where {$_.location -match \"System.Management.Automation.resources.dll$\"}
$rm=new-object System.Resources.ResourceManager(\"ParameterBinderStrings.$((Get-Culture).TwoLetterISOLanguageName)\",$assembly)
#\"Le jeu de paramètres ne peut pas être résolu à l'aide des paramètres nommés spécifiés.\"
$Msg=$rm.GetString(\"AmbiguousParameterSet\",(Get-Culture))
Throw (new-object System.Management.Automation.ParameterBindingException $Msg)
}
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer) -and $outBuffer -gt 1024)
{
$PSBoundParameters = 1024
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-ChildItem', [System.Management.Automation.CommandTypes]::Cmdlet)
#Initialise la commande
#On fusionne 2 scriptblocs pour une seule clause Where
$ContainerClause,$FilterDateClause,$separatorBegin,$separatorEnd=$null,$null,$null,$null
[string] $Cmds = '& $wrappedCmd @PSBoundParameters '
#retarde la substitution
#La propriété PSIsContainer est ajouté par PS (cf [CmdletProvider].WriteObject)
# sur chaque élément renvoyé par tous les providers.
# Si vous utiliser -Container sur certains providers ne supportant pas la naviguation,
#tous leurs éléments auront la propriété PSIsContainer à $false.
#Il est donc logique que certaines demandes ne renvoient aucun résultat.
$ContainerClause=\"`$separatorBegin```$_.PSIsContainer -eq ```$`$Container`$separatorEnd\"
Write-debug $ContainerClause
$FilterDateClause=$null
#Paramètre la commande
if ($ContainersOnly)
{
[Void]$PSBoundParameters.Remove(\"ContainersOnly\"«»)
$Container=$true
write-debug \"Container true\"
}elseif ($NoContainersOnly)
{
[Void]$PSBoundParameters.Remove(\"NoContainersOnly\"«»)
$Container= $false
write-debug \"Container false\"
}
else
{$ContainerClause=$null; write-debug \"ContainerClause Null\"}
if ($DateFilterBlock)
{
[Void]$PSBoundParameters.Remove(\"DateFilterBlock\"«»)
$FilterDateClause=\"`$separatorBegin`$DateFilterBlock`$separatorEnd\"
write-debug \"Set FilterDateClause\"
}
#Construit la commande d'après les valeurs des paramètres
if ($ContainerClause -and $FilterDateClause)
{
#Les 2 clauses étant précisées, on utilise des séparateurs.
$separatorBegin,$separatorEnd=\"(\",\"«»)\"
$Parameter= \"$ContainerClause -and $FilterDateClause\"
}
elseif ($ContainerClause)
{$Parameter =$ContainerClause}
else
#Si le paramètre FilterDateClause n'est pas lié
#il est à $null
{$parameter =$FilterDateClause}
$PsBoundParameters.GetEnumerator()|Write-debug
write-debug \"Parameter = $Parameter\"
if ($parameter)
{$Cmds += ' | Where-Object {{{0}}}' -F $ExecutionContext.InvokeCommand.ExpandString($Parameter)}
#Pas de filtre Where
write-debug $Cmds
$scriptCmd=[System.Management.Automation.ScriptBlock]::Create($Cmds)
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
Write-Debug \"ParameterSetName=$($PsCmdlet.ParameterSetName)\"
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try
{
Write-Debug \"[Process] $_\"
$steppablePipeline.Process($_)
} catch {
#Les erreurs non bloquantes ne sont traitées dans ce bloc.
throw
}
}
end
{
try {
Write-Debug \"[End]\"
$steppablePipeline.End()
$steppablePipeline.Dispose()
} catch {
throw
}
}
# Redirige l'aide sur l'aide du cmdlet d'origine
<#
.ForwardHelpTargetName Get-ChildItem
.ForwardHelpCategory Cmdlet
#>
}
[/code:1]
Ce proxy est vu comme une commande à part entière, elle est toutefois spécialisée :
[code:1]
#Get-ChildItemProxy -Date $FileInfoLib.Today -nocontainer =
Get-ChildItem @PSBoundParameters |
Where-Object {($_.PSIsContainer -eq $False) -and ('{0:dd/MM/yyyy}' -f $_.CreationTime -eq '08/02/2010')}
[/code:1]
Quelques exemples :
[code:1]
cd $env:temp
del alias:«»xDir
new-alias xDir Get-ChildItemProxy
$Filtre= New-FactoryFilterDate
$DateFilterSB=$Filtre.AfterThisDate(-1)
$FileInfoLib= New-FilterLib (New-FactoryFilterDate)
$DebugPreference=\"Continue\"
#Affiche les fichiers d'hier
xDir . -noCont -Date $DateFilterSB
\"C:\\",\"X:\\",\"C:\temp\"|xDir -Date $FileInfoLib.Today
#Affiche les fichiers d'avant-hier
xDir . -noCont -Date $FileInfoLib.BeforeYesterday
[/code:1]
Tests des jeux de paramètres :
[code:1]
#Tests
#Rejetés par le proxy
xDir -Path . -NoContainersOnly -LiteralPath . -ContainersOnly
xDir -Path . -NoContainersOnly -ContainersOnly
xDir -LiteralPath . -NoContainersOnly -ContainersOnly
xDir -Path . -LiteralPath .
#Rejetés par Get-ChildItem encapsulé
#Le code du proxy est exécuté.
xDir -Path . -NoContainersOnly -LiteralPath .
xDir -Path . -LiteralPath . -ContainersOnly
#Acceptés
xDir -LiteralPath . -ContainersOnly
xDir -LiteralPath . -NoContainersOnly
xDir -Path . -NoContainersOnly
xDir -Path . -ContainersOnly
#Rejetés par le proxy
xDir . -Date $null
xDir . -Date \"\"
xDir -Path . -LiteralPath .
#Acceptés
xDir . -Date $DateFilterSB
xDir . -Date $DateFilterSB
xDir . -Cont -Date $DateFilterSB
xDir . -noCont -Date $DateFilterSB
[/code:1]
[edit]
Voir aussi cette librairie dotnet .
Ajout de fonction pour le type DateTime via un fichier de formatage
Adding lots of useful DateTime functions
Message édité par: Laurent Dardenne, à: 21/02/10 14:02<br><br>Message édité par: Laurent Dardenne, à: 5/06/10 12:10
On utilise la possibilité de créer un Proxy de cmdlet :
[code:1]
Function Get-ChildItemProxy {
[CmdletBinding(DefaultParameterSetName='Items', SupportsTransactions=$true)]
param(
[Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
#A l'origine 'Items' et 'LiteralItems' sont mutuellement exclusifs.
#'Container' et 'NoContainer' le sont également, mais il ne peut y avoir qu'un
#seul niveau d'exclusion mutuelle. On place donc cette exclusion sur
#les nouveaux switchs, et on laisse le cmdlet encapsulé gérer l'exclusion d'origine.
#Ce qui fait que le binding réussi dans le proxy, mais générera une erreur lors
#de l'appel au cmdlet encapsulé.
#Autre solution tester, à l'aide d'un If, la présence simultanée des 2 switchs
# 'Container' et 'NoContainer'.
# [Parameter(ParameterSetName='Container')] #Ajout.
# [Parameter(ParameterSetName='NoContainer')] #Ajout
[System.String[]]
${Path},
[Parameter(ParameterSetName='LiteralItems', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
# [Parameter(ParameterSetName='Container')] #Ajout
# [Parameter(ParameterSetName='NoContainer')] #Ajout
[Alias('PSPath')]
[System.String[]]
${LiteralPath},
[Parameter(Position=1)]
[System.String]
${Filter},
[System.String[]]
${Include},
[System.String[]]
${Exclude},
[ValidateNotNullOrEmpty()]
[System.Management.Automation.ScriptBlock] #nouveau
${DateFilterBlock},
[Switch]
${Recurse},
[Switch]
${Force},
[Switch]
${Name},
#Jeux de paramètres exclusifs :
# soit Container soit NoContainer
# [Parameter(ParameterSetName='Container')]
# [Parameter(ParameterSetName='ContainerOnly')]
[Switch] #nouveau. On traite uniquement les répertoires
${ContainersOnly},
# [Parameter(ParameterSetName='Container')]
# [Parameter(ParameterSetName='NoContainerOnly')]
[Switch] #nouveau. On traite uniquement les fichiers
${NoContainersOnly}
)
begin
{
Write-Debug \"[Begin]\"
if ($ContainersOnly -and $NoContainersOnly)
{
$assembly=[appdomain]::currentdomain.GetAssemblies()|Where {$_.location -match \"System.Management.Automation.resources.dll$\"}
$rm=new-object System.Resources.ResourceManager(\"ParameterBinderStrings.$((Get-Culture).TwoLetterISOLanguageName)\",$assembly)
#\"Le jeu de paramètres ne peut pas être résolu à l'aide des paramètres nommés spécifiés.\"
$Msg=$rm.GetString(\"AmbiguousParameterSet\",(Get-Culture))
Throw (new-object System.Management.Automation.ParameterBindingException $Msg)
}
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer) -and $outBuffer -gt 1024)
{
$PSBoundParameters = 1024
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-ChildItem', [System.Management.Automation.CommandTypes]::Cmdlet)
#Initialise la commande
#On fusionne 2 scriptblocs pour une seule clause Where
$ContainerClause,$FilterDateClause,$separatorBegin,$separatorEnd=$null,$null,$null,$null
[string] $Cmds = '& $wrappedCmd @PSBoundParameters '
#retarde la substitution
#La propriété PSIsContainer est ajouté par PS (cf [CmdletProvider].WriteObject)
# sur chaque élément renvoyé par tous les providers.
# Si vous utiliser -Container sur certains providers ne supportant pas la naviguation,
#tous leurs éléments auront la propriété PSIsContainer à $false.
#Il est donc logique que certaines demandes ne renvoient aucun résultat.
$ContainerClause=\"`$separatorBegin```$_.PSIsContainer -eq ```$`$Container`$separatorEnd\"
Write-debug $ContainerClause
$FilterDateClause=$null
#Paramètre la commande
if ($ContainersOnly)
{
[Void]$PSBoundParameters.Remove(\"ContainersOnly\"«»)
$Container=$true
write-debug \"Container true\"
}elseif ($NoContainersOnly)
{
[Void]$PSBoundParameters.Remove(\"NoContainersOnly\"«»)
$Container= $false
write-debug \"Container false\"
}
else
{$ContainerClause=$null; write-debug \"ContainerClause Null\"}
if ($DateFilterBlock)
{
[Void]$PSBoundParameters.Remove(\"DateFilterBlock\"«»)
$FilterDateClause=\"`$separatorBegin`$DateFilterBlock`$separatorEnd\"
write-debug \"Set FilterDateClause\"
}
#Construit la commande d'après les valeurs des paramètres
if ($ContainerClause -and $FilterDateClause)
{
#Les 2 clauses étant précisées, on utilise des séparateurs.
$separatorBegin,$separatorEnd=\"(\",\"«»)\"
$Parameter= \"$ContainerClause -and $FilterDateClause\"
}
elseif ($ContainerClause)
{$Parameter =$ContainerClause}
else
#Si le paramètre FilterDateClause n'est pas lié
#il est à $null
{$parameter =$FilterDateClause}
$PsBoundParameters.GetEnumerator()|Write-debug
write-debug \"Parameter = $Parameter\"
if ($parameter)
{$Cmds += ' | Where-Object {{{0}}}' -F $ExecutionContext.InvokeCommand.ExpandString($Parameter)}
#Pas de filtre Where
write-debug $Cmds
$scriptCmd=[System.Management.Automation.ScriptBlock]::Create($Cmds)
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
Write-Debug \"ParameterSetName=$($PsCmdlet.ParameterSetName)\"
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try
{
Write-Debug \"[Process] $_\"
$steppablePipeline.Process($_)
} catch {
#Les erreurs non bloquantes ne sont traitées dans ce bloc.
throw
}
}
end
{
try {
Write-Debug \"[End]\"
$steppablePipeline.End()
$steppablePipeline.Dispose()
} catch {
throw
}
}
# Redirige l'aide sur l'aide du cmdlet d'origine
<#
.ForwardHelpTargetName Get-ChildItem
.ForwardHelpCategory Cmdlet
#>
}
[/code:1]
Ce proxy est vu comme une commande à part entière, elle est toutefois spécialisée :
[code:1]
#Get-ChildItemProxy -Date $FileInfoLib.Today -nocontainer =
Get-ChildItem @PSBoundParameters |
Where-Object {($_.PSIsContainer -eq $False) -and ('{0:dd/MM/yyyy}' -f $_.CreationTime -eq '08/02/2010')}
[/code:1]
Quelques exemples :
[code:1]
cd $env:temp
del alias:«»xDir
new-alias xDir Get-ChildItemProxy
$Filtre= New-FactoryFilterDate
$DateFilterSB=$Filtre.AfterThisDate(-1)
$FileInfoLib= New-FilterLib (New-FactoryFilterDate)
$DebugPreference=\"Continue\"
#Affiche les fichiers d'hier
xDir . -noCont -Date $DateFilterSB
\"C:\\",\"X:\\",\"C:\temp\"|xDir -Date $FileInfoLib.Today
#Affiche les fichiers d'avant-hier
xDir . -noCont -Date $FileInfoLib.BeforeYesterday
[/code:1]
Tests des jeux de paramètres :
[code:1]
#Tests
#Rejetés par le proxy
xDir -Path . -NoContainersOnly -LiteralPath . -ContainersOnly
xDir -Path . -NoContainersOnly -ContainersOnly
xDir -LiteralPath . -NoContainersOnly -ContainersOnly
xDir -Path . -LiteralPath .
#Rejetés par Get-ChildItem encapsulé
#Le code du proxy est exécuté.
xDir -Path . -NoContainersOnly -LiteralPath .
xDir -Path . -LiteralPath . -ContainersOnly
#Acceptés
xDir -LiteralPath . -ContainersOnly
xDir -LiteralPath . -NoContainersOnly
xDir -Path . -NoContainersOnly
xDir -Path . -ContainersOnly
#Rejetés par le proxy
xDir . -Date $null
xDir . -Date \"\"
xDir -Path . -LiteralPath .
#Acceptés
xDir . -Date $DateFilterSB
xDir . -Date $DateFilterSB
xDir . -Cont -Date $DateFilterSB
xDir . -noCont -Date $DateFilterSB
[/code:1]
[edit]
Voir aussi cette librairie dotnet .
Ajout de fonction pour le type DateTime via un fichier de formatage
Adding lots of useful DateTime functions
Message édité par: Laurent Dardenne, à: 21/02/10 14:02<br><br>Message édité par: Laurent Dardenne, à: 5/06/10 12:10
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
Temps de génération de la page : 0.074 secondes
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Contributions à la communauté
- Comment construire un objet qui construit du code?