Question Gestion d'événement perso dans 1 objet synthétique
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Pour cet exemple on ne peut gérer qu'une seule instance, étant donnée que la déclaration d'un événements personnalisé est globale :
[code:1]
function New-CustomObject {
Param(
[ValidateNotNullOrEmpty()]
[string]$VariableName,
[Scriptblock] $PreModification=$null,
[Scriptblock] $PostModification=$null)
#On crée un objet à partir des membres d'un module.
#Le module sert à encapsuler des membres privés.
$CustomObject=New-Module -AsCustomObject -ScriptBlock {
#Crée une variable en lecture seule
New-Variable Events -Option ReadOnly -Value ([String[]]@(
\"PSPreModification\",\"PSPostModification\"«»))
#On mémorise le nom de la variable hébergeant ce module
New-Variable Name -Option ReadOnly -Value ([String]\"$($args[0])\"«»)
#Crée des variables accessible dans la portée
#de ce module dynamique.
[int] $script:_Nombre=0
#Contient un scriptblock lié à
#l'événement personnel nommée PSPreModification.
[Scriptblock] $script:«»PreModification=$null
[Scriptblock] $script:«»PostModification=$null
$script:module= $ExecutionContext.SessionState.Module
#Accesseur, permet de se placer dans la portée du module.
function GetModuleMember{
param([String]$MemberName) invoke-expression \"Return `$script:$MemberName\"}
function SetModuleMember{
param([String]$MemberName,$Value) invoke-expression \"`$script:$MemberName=`$Value\"}
#Gestion de l'affectation des événements et de leur scriptblock associé.
#Cette fonction crée l'abonnement à l'événement spécifiée s'il n'existe pas.
#S'il existe, on l'annule puis on supprime le job associé avant de recréer
#l'abonnement.
#
#ex : La variable PostModification héberge une copie du scriptblock
# affecté à l'événement PSPostModification.
function AssignScriptBlock{
param([String]$Eventname,[ScriptBlock]$sb)
if ($Script:Events -notcontains $Eventname)
{Throw \"'$EventName' nom d'événement inconnu. La variable $($Script:Name) ne supporte que les événements suivants : \"+
\"$($oldOfs=$Ofs;$Ofs=', ';\"$Script:Events\";$ofs=$oldOfs)\"}
$JobResult=$null
#Le préfixe \"PS\" est une convention de nommage
#des événements personnel.
# 1 evénement personnel = \"PS\"+nom_de_la_propriété_scriptblock
$PropertyName=($Eventname -Split \"PS\"«»)[1]
#Syntaxe d'appel interne
#On affecte la valeur seulement si c'est nécessaire.
if (((GetModuleMember $PropertyName) -eq $null) -and $sb -eq $null) {return}
#Récupére l'abonné $Eventname s'il existe
$Subcriber=Get-EventSubscriber $Eventname -ea SilentlyContinue
if ($Subcriber)
{
$Job=$Subcriber.Action.Id
#on récupére, avant son arrêt, les possibles
#données émisent par le job.
$JobResult=Receive-Job $Job
#On arrête le job de l'abonnement,
#on se désabonne implicitement
Stop-Job $Job
#On supprime le job qui était associé
# l'abonnement de l'événement $Eventname
Remove-Job $Job
}
#Maj de la propriété privée
SetModuleMember $PropertyName $sb
if ($sb -ne $null)
{
#On se réabonne à l'événement avec
#le nouveau scriptblock
$null=Register-EngineEvent $Eventname $sb
}
# Si le scriptblock est à $null on a
# déjà annulé l'abonnement
#on réémet les possibles données précédement
#émisent par le job ($Subcriber.Action)
$JobResult
}
#Initialise si besoin les abonnements
if ($args[1] -ne $null)
{ AssignScriptBlock \"PSPreModification\" $args[1]}
if ($args[2] -ne $null)
{ AssignScriptBlock \"PSPostModification\" $args[2]}
Export-ModuleMember -Function AssignScriptBlock,GetModuleMember,SetModuleMember `
-Variable Name,Events,OnPreModification,OnPostModification
} -ArgumentList $VariableName,$PreModification,$PostModification
#On ajoute des propriété synthétiques pour bénéficier des accesseurs getter et setter.
#Elles accédent au propriétés privées du module à l'aide des fonctions publiques
# GetModuleMember et SetModuleMember.
#Leurs syntaxe d'appel différe lors d'un usage à l'extérieur du module.
$CustomObject|add-member -membertype ScriptProperty -Name Nombre -value {$this.GetModuleMember(\"_Nombre\"«»)} `
-secondvalue {
param([int]$Value)
$Oldvalue=$this.GetModuleMember(\"_Nombre\"«»)
$this.SetModuleMember(\"_Nombre\",$Value)
#Si un abonnement existe on déclenche l'événement
if (Get-EventSubscriber \"PSPreModification\"«»)
{ New-Event \"PSPreModification\" (gv $this.Name) @{Old=$OldValue} \"Valeur de la propriété Nombre avant modification \" }
if (Get-EventSubscriber \"PSPostModification\"«»)
{ New-Event \"PSPostModification\" (gv $this.Name) @{Old=$OldValue;New=$Value} \"Valeur de la propriété Nombre après modification \" }
} -pass|
#Propriété permettant d'affecter le traitement associé à un événement.
#On masque ainsi la gestion des abonnements d'événement tout en la facilitant.
add-member -membertype ScriptProperty -Name OnPreModification -value {$this.GetModuleMember(\"PreModification\"«»)} -secondvalue {
Param ([Scriptblock] $Value)
$this.AssignScriptBlock(\"PSPreModification\",$Value) } -pass|
add-member -membertype ScriptProperty -Name OnPostModification -value {$this.GetModuleMember(\"PostModification\"«»)} -secondvalue {
Param ([Scriptblock] $Value)
$this.AssignScriptBlock(\"PSPostModification\",$Value) } -pass|
add-member -membertype ScriptMethod -Name DisposeAndRemove -value {
#S'ils sont déclarés, on supprime
#les abonnements en cours
if ($this.OnPreModification -ne $null)
{$this.OnPreModification=$null}
if ($this.OnPostModification -ne $null)
{$this.OnPostModification=$null}
#Last but not least
#Supprime la variable dans la portée parente
Remove-Variable $this.Name -Scope 1
}
$CustomObject
}
[/code:1]
Un exemple d'utilisation :
[code:1]
#Initialisation
$sbPre={
Write-Host (\"[PreProcess] Old={0}\" –F $Event.SourceArgs[0].Old) -Fore green
}
$sbPost={
Write-Host (\"[PostProcess] Old={0}`tNew={1}\" –F $Event.SourceArgs[0].Old, $Event.SourceArgs[0].New) -Fore green
}
$ObjEvt=New-CustomObject \"ObjEvt\" $sbPre $sbPost
$ObjEvt
$ObjEvt.Nombre
$ObjEvt.Nombre=2
[/code:1]<br><br>Message édité par: Laurent Dardenne, à: 28/04/10 13:58
Tutoriels PowerShell
Pièces jointes :
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
La pièce jointe CustomEventObject.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
-
- Messages : 6311
- Remerciements reçus 68
Avec le script précédent on doit impérativement appeler la méthode DisposeAndRemove() afin de libérer les ressources (job/abonnement) liées à l'objet :
[code:1]
#Pour la création voir en fin de premier post
get-eventSubscriber
get-job
$MonObjet.OnPreModification
$MonObjet.OnPreModification=$null
$MonObjet.Nombre=12
get-eventSubscriber
get-job
gv $MonObjet.Name
$MonObjet.DisposeAndRemove()
get-eventSubscriber
get-job
gv $MonObjet.Name[/code:1]
Comme l'objet connait le nom de la variable qui le contient, la méthode DisposeAndRemove la supprime la dans la portée courante.
Ensuite quelque cas de figure :
[code:1]
#Aucun problème.
#Seul les jobs à l'état Stopped sont concernés
$MonObjet.Nombre=-1
$ObjEvt=New-CustomObject \"ObjEvt\" $sbPre $sbPost
$ObjEvt
Remove-job
[/code:1]
Ceux-ci ne libérent pas les ressources ( job/abonnement) :
[code:1]
#Problème : pas de suppression des abonnements ni des jobs
$ObjEvt=New-CustomObject \"ObjEvt\" $sbPre $sbPost
$ObjEvt=$null
get-eventSubscriber
#Problème : pas de maj des propriétés de l'objet
$ObjEvt=New-CustomObject \"ObjEvt\" $sbPre $sbPost
$ObjEvt
Unregister-Event *
Remove-job *
#Problème : on écrase les abonnements des objets précédents,
# car tous les objets partagent les mêmes noms d'identifiant d'événement
$Obj2=New-CustomObject \"Obj2\" $sbPre $sbPost
$Obj2[/code:1]
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Arnaud Petitjean
-
- Hors Ligne
- Modérateur
-
Concrêtement je pense que ça ne me servira jamais, car je ne sais même pas ce qu'est un objet synthétique
Mais en tout cas, merci pour ta contribution. Ca aidera certainement un public de développeurs.
@+
Arnaud
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
C'est plus un cas d'étude de ce qu'on peut faire ou pas avec la V2 autour d'un ensemble de technique simple. C'est sur que ça ne sert pas à grand chose, mais il a 2-3 trucs qui pourront reservir. Il faut juste que je les détaille.Normal tu vas me répondre, je ne suis pas développeur
Arnaud écrit:
Tu connais Add-Member, mais on utilise peut être pas le même mot pour désigner un objet PowerShell personnalisé.car je ne sais même pas ce qu'est un objet synthétique
Arnaud écrit:
Je ne pense pas.Ca aidera certainement un public de développeurs.
Je pourrais utiliser le C#, mais quel intérêt pour le scripting ? Aucun.
En procédant ainsi j'appréhende mieux les limites de PowerShell et approfondi l'usage de certaines nouveautés.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Arnaud Petitjean
-
- Hors Ligne
- Modérateur
-
Tu connais Add-Member, mais on utilise peut être pas le même mot pour désigner un objet PowerShell personnalisé.
Oui je m'en sers régulièrement, mais effectivement je ne savais pas que je manipulais des objets synthétiques.
C'est bien ce que je pensais mais je n'osais pas te le dire...Je pourrais utiliser le C#, mais quel intérêt pour le scripting ? Aucun.
En procédant ainsi j'appréhende mieux les limites de PowerShell et approfondi l'usage de certaines nouveautés.
Ok, compris
@+
Arnaud
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Connexion ou Créer un compte pour participer à la conversation.
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Contributions à la communauté
- Gestion d'événement perso dans 1 objet synthétique