2017-06-09 5 views
2

Je tente d'utiliser dynamiquement l'espace de noms Microsoft.Web.Administration dans une cmdlet powershell.Powershell: collecte dynamique des types de données pour la validation des éléments de configuration IIS

Existe-t-il un moyen d'ajouter une variable dans une déclaration Namespace.Class. J'utilise l'espace de noms [Microsoft.Web.Administration] et sa classe [Microsoft.Web.Administration.ApplicationPool], il possède une propriété "Recycling" que vous pouvez accéder à l'aide d'une méthode GetProperty.

[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling") 

Si vous crachez la propriété de ce qui précède en utilisant ce

[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling").PropertyType.FullName 

Vous obtenez ce résultat,

Microsoft.Web.Administration.ApplicationPoolRecycling

qui est une autre classe. Je veux maintenant accéder dynamiquement à cette classe dans la cmdlet. Comment accéder à cette classe à partir du code, je veux que le code découvre dynamiquement la nouvelle classe de l'objet, puis accède à cette classe. Mais je ne peux pas trouver un moyen d'accomplir cela.

psuedocode pour ce que je suis en train

[System.Reflection.Assembly]::LoadFrom("C:\windows\system32\inetsrv\Microsoft.Web.Administration.dll") 
$appPoolProperty = [Microsoft.Web.Administration.ApplicationPool].GetProperty($Property) 
$subClassName = $appPoolProperty.PropertyType.FullName 

#This is the step I'm lost on 
$subClass = New-Object $subClassName 

Je ne sais pas s'il y a un moyen d'avoir un TypeName pour un objet mis en valeur comme une chaîne et je ne peux pas sembler trouver un manière de lancer la variable comme toute autre chose. Désolé si c'est correctif, je suis un codeur cultivé sous-sol et j'apprends juste les choses comme je vais.

EDIT: Comme demandé par Mathias ci-dessous dans les commentaires, un aperçu de ce que j'essaie d'atteindre.

J'ai un script qui automatise la configuration de nombreux composants IIS. Actuellement, j'essaie d'ajouter une validation à la cmdlet Set-AppPoolConfiguration que j'ai créée et qui permet d'ajouter une configuration à la cmdlet qui configure un AppPool (ceci est utilisé pour déployer des sites Web/weapplications dans un environnement Web distribué) . En utilisant les détails à l'intérieur de Microsoft.Web.Administration, je peux obtenir des valeurs enum, ainsi que les types des nombreux composants de configuration d'un AppPool. Cela me fait gagner du temps là où je n'ai pas besoin de coder en dur dans les types de données et je peux juste les découvrir dynamiquement et faire une validation sur les valeurs quand l'élément de configuration spécifique est choisi.

Par exemple. Si une planification de recyclage AppPool doit être configurée, je dois la valider par rapport à un type de données TimeSpan. S'il ne s'agit pas d'un type de données TimeSpan, des problèmes se poseront lors de l'ajout à ScheduleCollection. Donc, je cherche à valider la valeur fournie avant d'essayer de l'ajouter. Comme il y a beaucoup d'éléments de configuration AppPool, je ne veux pas avoir à créer un énorme commutateur ou une chaîne if/elseif qui vérifie chaque élément de configuration et dicte statiquement le type de données à valider. Je veux que la classe elle-même fournisse dynamiquement cette information pour simplifier le code.

Je peux obtenir la majorité de ces types de données en accédant simplement à la chaîne de propriétés dans l'espace de noms.Par exemple, si vous voulez savoir quel type est nécessaire pour la QueueLength, utilisez ceci:

[Microsoft.Web.Administration.ApplicationPool].GetProperty("QueueLength").PropertyType.Name 

Et vous obtiendrez Int64.

Il est également extrêmement utile pour obtenir des énumérations. Toutefois, en tentant cela avec Schedule et vous rencontrez un petit problème car il retourne ScheduleCollection. Cela est vrai pour tous les éléments de configuration faisant partie d'une collection. Toutefois, la connaissance que l'élément de planification dans le ScheduleCollection n'est accessible qu'à partir de la classe Schedule est connue. Mon code vérifie actuellement s'il s'agit d'une collection, et si c'est le cas, il tente d'accéder à cette collection/classe et d'obtenir les informations requises. Pour en savoir que le calendrier est un TimeSpan vous devez accéder est instance de classe spécifique:

[Microsoft.Web.Administration.Schedule].GetProperty('Time').PropertyType.Name 

Maintenant AppPools sont simples, il n'y a qu'un seul groupe de collection qui est normalement modifié, si dur de codage en ce que si vous essayez pour définir un nouveau planning de recyclage, TimeSpan n'est pas un gros problème, mais lorsque nous passons aux configurations WebSite/WebApplication, il devient plus fastidieux de déclarer statiquement les types de données pour chaque élément de configuration faisant partie d'une collection , et devient plus utile pour essayer de les découvrir dynamiquement en fonction de l'élément de configuration sélectionné.

C'était mon approche initiale, je viens d'inclure ce qui précède pour plus de clarté. Je vais prendre du recul et jeter un autre regard sur la façon d'attaquer cela car cela ne semble pas être aussi facile que je l'espérais, je posterai ma solution ici.

+1

Je ne vois pas pourquoi quelqu'un voudrait créer un nouveau objet 'ApplicationPoolRecycling'. La réponse à "Une façon d'avoir un TypeName pour un objet mis en valeur de chaîne" est '-dans $ DynamicType' (si elle peut être castée). Mais vous voulez probablement obtenir une instance de 'ApplicationPoolRecycling' à partir de votre' ApplicationPool' et modifier les propriétés sur celle-ci. – BenH

+0

Avez-vous essayé '' '[Activator] :: CreateInstance()' ''? –

+0

@BenH ce que vous indiquez serait idéal aussi bien, et est un peu où mon psuedocode va. J'essaye d'obtenir une instance de la classe ApplicationPoolRecycling, mais je ne peux pas sembler créer dynamiquement cette instance en utilisant une entrée de chaîne du nom de classe. J'ai essayé différentes variantes de la méthode [Activator] :: CreateInstance (string, string), mais jusqu'à présent, je suis juste en train de courir sur les erreurs que je suis en train de résoudre. – Paolis

Répondre

0

Vous pouvez récupérer le constructeur à partir du type littéral et invoquez comme ceci:

$type = [Microsoft.Web.Administration.ApplicationPoolRecycling] 
$ctor = $type.GetConstructor('NonPublic,Instance',$null,@(),$null) 
$appPoolRecyclingInstance = $ctor.Invoke($null) 
+0

Votre exemple a la même question que mon code actuel est le cas, votre type de $ n'est pas dynamique, il sera toujours cette classe spécifique. J'ai besoin d'être dynamique. Je ne sais pas quelle classe mon code va découvrir dans cet espace de noms, il pourrait s'agir de l'une des classes de l'espace de noms Microsoft.Web.Administration. – Paolis

+0

Pourriez-vous clarifier ce que vous essayez d'accomplir. Quel est le but de l'applet de commande souhaitée? –

+0

J'ai ajouté plus de détails à l'article d'origine. Je vous remercie. – Paolis

0

Bien qu'il puisse y avoir un moyen de faire ce qui précède, afin de compléter les mises à jour de mon cmdlet et avanceront avec mon projet je suis allé un itinéraire hybride. La raison pour laquelle j'ai commencé à explorer l'espace de noms [Microsoft.Web.Administration] était qu'il fournissait des informations sur les types de données dans lesquels la façon habituelle de manipuler les paramètres IIS échouait à l'aide de Get/Set/Add-WebConfigurationProperty.

La défaillance spécifique consiste à signaler des types de données valides pour Enums. Prenez par exemple ProcessModel.IdentityTypes. Il existe un ensemble d'entrées valides pour un IdentityType. Cependant, ce qui suit ne vous fournit pas ces types valides, vous devez donc créer des instances statiques à l'intérieur de votre cmdlet ou d'une autre source de données externe, alors que Microsoft voulait les fournir soit via IIS soit via les classes attachés à ces éléments de configuration de sorte que l'applet de commande ne nécessite qu'une mise à jour minimale au fur et à mesure que les versions/éléments de configuration IIS changent.

Ce code renvoie Boolean

(Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[@name='$AppPool']" -name "AutoStart").Value.GetType().Name 

Cependant, ce code retourne la chaîne, ce qui est vrai, mais je devais savoir qu'il est un ENUM et je devais connaître les valeurs appropriées.

(Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[@name='$AppPool']" -name "processModel").identityType.GetType().Name 

L'utilisation d'un mélange des deux l'espace de noms et le traditionnel Get-WebConfigurationProperty commandes je peux tester avec succès maintenant pour les types de données, ainsi que de recueillir des valeurs appropriées pour énumérations dynamiquement dans le code. S'il y a un intérêt, je peux publier le code de validation complet ici que j'utilise pour cette applet de commande.