Question [BUG] WMI et la méthode Put()

Plus d'informations
il y a 16 ans 9 mois #4722 par Laurent Dardenne
Etant en train d'écrire un tutoriel sur l'usage de WMI sous PowerShell, j'ai découvert un bug qui n'est pas référencé mais est corrigé dans la version de PS v2 livrée avec la RC1 de Windows Seven.
Le code suivant, une adaptation d'un fichier MOF , utilise la propriété __path d'une nouvelle instance WMI
[code:1]$ClassDataProv= [wmiclass]\"root\TestVues:__Win32Provider\"
$DataProv= $ClassDataProv.CreateInstance()
$DataProv.Name = \"MS_VIEW_INSTANCE_PROVIDER\";
$DataProv.ClsId = \"{AA70DDF4-E11C-11D1-ABB0-00C04FD9159E}\"
$DataProv.ImpersonationLevel = 1
$DataProv.PerUserInitialization = $True
$DataProv.HostingModel = \"NetworkServiceHost\"
$DataProv.put()[/code:1]
Sous PowerShell V1 l’accés aux propriétés système de la nouvelle instance WMI nécessite de forcer l’adaptation de l'objet WMI, encapsulé dans un objet dotnet.
Ceci est corrigé avec la version de Powershell v2 livrée avec la RC1 de Windows Seven.

Sous PS v1, on peut, d'après mes tests, forcer l'adaptation ainsi
[code:1]
$DataProv.Put()
$DataProv|SELECT __* > $NULL
[/code:1]
Sans cette instruction, sous PS v1 et PS v2 CTP 3, l’accès en lecture de la propriété __path renvoie une valeur nulle.
Ce qui pose problème pour la séquence de code suivante :
[code:1]$ClassProvReg= [wmiclass]\"root\TestVues:__InstanceProviderRegistration\"
$ProvReg= $ClassProvReg.CreateInstance()
#C’est une référence, on pointe sur le chemin de l’instance WMI
# et pas sur la variable PowerShell
$ProvReg.Provider =$DataProv.__Path
$ProvReg.SupportsPut = $True
$ProvReg.SupportsGet = $True
$ProvReg.SupportsDelete = $True
$ProvReg.SupportsEnumeration =$True
$ProvReg.QuerySupportLevels =@(\"WQL:UnarySelect\"«»)
$ProvReg.put()
[/code:1]
Dans ce cas le contenu de la variable $DataProv.__Path sera à égale $null, ce qui provoquera une erreur lors de l'appel à $ProvReg.Put().

On peut corriger ceci, pour la propriété __Path, en utilisant la valeur de retour de l'appel à la méthode Put() :
[code:1]...
$Result=$DataProv.put()
...
$ProvReg.Provider =$Result.Path
...[/code:1]
C'est sûr que ce code n'est pas d'un usage courant, mais pour ceux utilisant des fonctionnalités avancées de WMI, autre que la simple lecture d'instance, cette information pourra leur faire gagner du temps.

ps
Je posterais le code complet une fois celui-ci testé
[code:1]
$ClassNS = [wmiclass]\"root:__Namespace\"
$NS = $ClassNS.CreateInstance()
$NS.Name = \"TestVues\"
$NS.put()

$ClassDataProv= [wmiclass]\"root\TestVues:__Win32Provider\"
$DataProv= $ClassDataProv.CreateInstance()
$DataProv.Name = \"MS_VIEW_INSTANCE_PROVIDER\";
$DataProv.ClsId = \"{AA70DDF4-E11C-11D1-ABB0-00C04FD9159E}\"
$DataProv.ImpersonationLevel = 1
$DataProv.PerUserInitialization = $True
$DataProv.HostingModel = \"NetworkServiceHost\"
$Result=$DataProv.put()

$ClassProvReg= [wmiclass]\"root\TestVues:__InstanceProviderRegistration\"
$ProvReg= $ClassProvReg.CreateInstance()
#C’est une référence, on pointe sur le chemin de l’instance WMI
# et pas sur la variable PowerShell
$ProvReg.Provider =$Result.Path
$ProvReg.SupportsPut = $True
$ProvReg.SupportsGet = $True
$ProvReg.SupportsDelete = $True
$ProvReg.SupportsEnumeration =$True
$ProvReg.QuerySupportLevels =@(\"WQL:UnarySelect\"«»)
$ProvReg.put()

$ClassMethodProvReg=[wmiclass]\"root\TestVues:__MethodProviderRegistration\"
$MethodProvReg = $ClassMethodProvReg.CreateInstance()
$MethodProvReg.Provider =$Result.Path
$MethodProvReg.put()

#TODO création d'une 'jointure WMI'
[/code:1]

Quelqueq infos sur la création d'instance WMI.
Savoir si une classe peut être créée, supprimée, modifiée :
[code:1]([wmiclass]\"Win32_Environment\"«»).psbase.Qualifiers|? {
$_.name -match \"^Supports\"}| Select name[/code:1]

Name
----
SupportsCreate
SupportsDelete
SupportsUpdate

Pour connaître le mode de création d’une instance d’une classe :
[code:1]\"Win32_Process\",\"Win32_Environment\"|`
Foreach {
([wmiclass]\"$_\"«»).psbase.Qualifiers| `
Where {$_.name -match \"By$\"}|`
Select Name,value
}[/code:1]

Name Value
----


CreateBy Create # Win32_Process
DeleteBy DeleteInstance
CreateBy PutInstance # Win32_Environment
DeleteBy DeleteInstance

<br><br>Message édité par: Laurent Dardenne, à: 1/06/09 11:57

Tutoriels PowerShell

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

Plus d'informations
il y a 16 ans 9 mois #4740 par Laurent Dardenne
La jointure, classe WMI, ne peut être créée dynamiquement, enfin je n'ai pas trouvé comment faire.
Le fichier texte de déclaration de la classe de jointure :

#pragma namespace(\&quot;\\\\.\\root\\TestVues\&quot;)

[
JoinOn(\&quot;Win32_DiskPartition.DiskIndex = Win32_DiskDrive.Index\&quot;),
ViewSources{
\&quot;SELECT DiskIndex, Index, DeviceID FROM Win32_DiskPartition\&quot; ,
\&quot;SELECT Index, Caption, Model FROM Win32_DiskDrive\&quot;},
ViewSpaces{
\&quot;\\\\.\\root\\cimv2\&quot;,
\&quot;\\\\.\\root\\cimv2\&quot;},
dynamic: ToInstance,
provider(\&quot;MS_VIEW_INSTANCE_PROVIDER\&quot;)
]

class JoinedPartitionDisk
{
[PropertySources{\&quot;DiskIndex\&quot;, \&quot;Index\&quot;}] UInt32 ID;
[PropertySources{\&quot;\&quot;, \&quot;Caption\&quot;}] String Caption;
[PropertySources{\&quot;DeviceID\&quot;, \&quot;\&quot;},Key] String DeviceId;
[PropertySources{\&quot;\&quot;, \&quot;Model\&quot;}] String Model;
};

Puis on compile la classe dans l'espace de nom porté par le fichier précédent, \root\TestVues
[code:1]
mofcomp JoinedPartitionDisk.Mof
[/code:1]
Ensuite on peut récupérer les instances :
[code:1]gwmi -namespace \&quot;root\TestVues\&quot; -class \&quot;JoinedPartitionDisk\&quot;[/code:1]
L'ajout d'un cmdlet Join-Object ou Merge-object aurait été appréciable, bien qu'ici la création des instances soit prise en charge par WMI.<br><br>Message édité par: Laurent Dardenne, à: 3/06/09 14:27

Tutoriels PowerShell

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

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