Question Gestion d'événement perso dans 1 objet synthétique

Plus d'informations
il y a 15 ans 10 mois #6607 par Laurent Dardenne
Cette fonction permet d'implémenter une gestion d'événement au sein d'un objet synthétique.

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.

Plus d'informations
il y a 15 ans 10 mois #6608 par Laurent Dardenne
Le fichier script.

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.

Plus d'informations
il y a 15 ans 10 mois #6746 par Laurent Dardenne
Un complément d'informations concernant la libération des ressources et les limites d'usages.

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 \&quot;ObjEvt\&quot; $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 \&quot;ObjEvt\&quot; $sbPre $sbPost
$ObjEvt=$null
get-eventSubscriber

#Problème : pas de maj des propriétés de l'objet
$ObjEvt=New-CustomObject \&quot;ObjEvt\&quot; $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 \&quot;Obj2\&quot; $sbPre $sbPost
$Obj2[/code:1]

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 15 ans 10 mois #6749 par Arnaud Petitjean
Merci Laurent pour ton post mais je t'avoue ne pas y piper grand chose. Normal tu vas me répondre, je ne suis pas développeur ;-)

Concrêtement je pense que ça ne me servira jamais, car je ne sais même pas ce qu'est un objet synthétique :lol:

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.

Plus d'informations
il y a 15 ans 10 mois #6752 par Laurent Dardenne
Arnaud écrit:

Normal tu vas me répondre, je ne suis pas développeur

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.
Arnaud écrit:

car je ne sais même pas ce qu'est un objet synthétique

Tu connais Add-Member, mais on utilise peut être pas le même mot pour désigner un objet PowerShell personnalisé.
Arnaud écrit:

Ca aidera certainement un public de développeurs.

Je ne pense pas.
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.

Plus d'informations
il y a 15 ans 10 mois #6755 par Arnaud Petitjean

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.

Je pourrais utiliser le C#, mais quel intérêt pour le scripting ? Aucun.

C'est bien ce que je pensais mais je n'osais pas te le dire... :)

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.

Temps de génération de la page : 0.058 secondes
Propulsé par Kunena