简体   繁体   English

Powershell:动态收集数据类型以进行IIS配置元素验证

[英]Powershell: Dynamically gather data types for IIS configuration element validation

I'm attempting to dynamically use the Microsoft.Web.Administration namespace within a powershell cmdlet. 我正在尝试在Powershell cmdlet中动态使用Microsoft.Web.Administration命名空间。

Is there a way to add a variable into a Namespace.Class declaration. 有没有一种方法可以将变量添加到Namespace.Class声明中。

I'm using the namespace [Microsoft.Web.Administration] and it's class [Microsoft.Web.Administration.ApplicationPool], it has a property under it 'Recycling' that you can access using a GetProperty method. 我使用的是命名空间[Microsoft.Web.Administration],它的类为[Microsoft.Web.Administration.ApplicationPool],它具有“回收”属性,您可以使用GetProperty方法对其进行访问。

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

If you spit out the PropertyType of the above using this 如果您使用此方法吐出上面的PropertyType

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

You get this result, 你得到这个结果,

Microsoft.Web.Administration.ApplicationPoolRecycling Microsoft.Web.Administration.ApplicationPoolRecycling

which is another class. 这是另一类。 I now want to access this class dynamically within the cmdlet. 我现在想在cmdlet中动态访问此类。 How do access this class from within the code, I want the code to dynamically discover the new class of the object and then access that class. 如何从代码中访问此类,我希望代码动态发现对象的新类,然后访问该类。 But I can't find a way to accomplish this. 但是我找不到实现此目的的方法。

Psuedocode for what I'm trying 我正在尝试的伪代码

[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

So I'm not sure if there's a way to have a TypeName for an object put in as a string value and I can't seem to find a way to cast the variable as anything else. 所以我不确定是否有一种方法可以将对象的TypeName作为字符串值放入,而且我似乎找不到找到将变量转换为其他任何方法的方法。 Sorry if this is remedial, I'm a basement grown coder and just learn things as I go. 对不起,如果这是补救措施,我是一名地下室开发人员,并且在学习过程中学习一些东西。

EDIT: As requested by Mathias below in the comments, an overview of what I'm trying to achieve. 编辑:根据Mathias在下面的评论中的要求,概述了我要实现的目标。

I have a script that automates the configuration of many IIS components. 我有一个脚本,可以自动配置许多IIS组件。 At this time I'm attempting to add validation to the cmdlet Set-AppPoolConfiguration that I've created that allows a configuration to be fed into the cmdlet that configures an AppPool (this is used to deploy websites/weapplications throughout a distributed web environment). 目前,我正在尝试将验证添加到我创建的cmdlet Set-AppPoolConfiguration中,该配置允许将配置输入到配置AppPool的cmdlet中(用于在整个分布式Web环境中部署网站/ weapplications) 。 Utilizing the details inside the Microsoft.Web.Administration I'm able to get enum values, as well as types of the many configuration components of an AppPool. 利用Microsoft.Web.Administration内部的详细信息,我可以获取枚举值以及AppPool的许多配置组件的类型。 This is saving me time to where I don't have to hard code in the data types and can just dynamically discover them and do validation on the values when the specific configuration element is chosen. 这为我节省了时间,不必在数据类型中进行硬编码,而可以在选择特定的配置元素时动态地发现它们并对值进行验证。

For example. 例如。 If an AppPool Recycle schedule is need to be configured, I need to validate it against a TimeSpan data type. 如果需要配置AppPool回收计划,则需要针对TimeSpan数据类型对其进行验证。 If it is not a TimeSpan data type issues will arise when being added to the ScheduleCollection. 如果不是TimeSpan数据类型,则将其添加到ScheduleCollection时会出现问题。 So I'm looking to validate the value provided before attempting to add it. 因此,我试图在尝试添加提供的值之前对其进行验证。

Since there are many AppPool configuration elements, I don't want to have to create a massive switch or if/elseif chain that checks each configuration element and statically dictate what data type it is for validation. 由于有许多AppPool配置元素,因此我不必创建大量的开关或if / elseif链来检查每个配置元素并静态指示要验证的数据类型。 I want the class itself to dynamically provide this information to simplify the code. 我希望类本身可以动态提供此信息以简化代码。

I can get the majority of these data types by simply accessing the property chain within the namespace. 通过简单地访问命名空间中的属性链,我可以获得大多数这些数据类型。 For example, if you want to know what type is required for the QueueLength, use this: 例如,如果您想知道QueueLength需要什么类型,请使用以下命令:

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

And you'll get Int64. 然后您将获得Int64。

It's also extremely useful for getting enums. 这对于获取枚举也非常有用。

[Microsoft.Web.Administration.ApplicationPool].GetProperty("ManagedPipelineMode").PropertyType.GetEnumNames()

However attempting this with Schedule and you run into a small issue as it returns ScheduleCollection. 但是,尝试使用Schedule进行操作,会遇到一个小问题,因为它返回ScheduleCollection。 This is true of any of the configuration elements that are part of a collection. 对于集合中的任何配置元素都是如此。

[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling").PropertyType.GetProperty('PeriodicRestart').PropertyType.GetProperty('Schedule').PropertyType.Name

However the knowledge that the schedule item inside the ScheduleCollection is only accessible from within the Schedule class. 但是,只能从Schedule类中访问ScheduleCollection内部的计划项的知识。 My code currently checks to see if it is a collection, and then if it is, it is attempting to access that collection/class and get the information that is required. 我的代码当前正在检查它是否是一个集合,如果是,则试图访问该集合/类并获取所需的信息。 To find out that schedule is a TimeSpan you have to access it's specific class instance: 要找出时间表是一个TimeSpan,您必须访问它的特定类实例:

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

Now AppPools are simple, there's only a single collection group that is normally edited, so hard coding in that if you're attempting to set a new recycle schedule it will be a TimeSpan isn't that big of a deal, however when we move over to WebSite/WebApplication configurations, it becomes more tedious to statically declare data types for each configuration element that is part of a collection, and becomes more useful to try and discover these dynamically based on the configuration element selected. 现在,AppPools很简单,通常只编辑一个收集组,因此采用硬编码,因为如果您尝试设置新的回收时间表,那么TimeSpan没什么大不了的,但是当我们移动时到WebSite / WebApplication配置,为集合的每个配置元素静态声明数据类型变得更加繁琐,并且根据所选的配置元素动态地发现这些数据变得更加有用。

This was my initial approach, I just included the above for clarity. 这是我最初的方法,为清楚起见,我仅包括了上述内容。 I'm going to step back and take another look at how to attack this as this does not appear to be as easy as I had hoped, I'll post my solution here. 我将退后一步,再看看如何进行攻击,因为这似乎并不像我希望的那么容易,我将在此处发布解决方案。

You can retrieve the constructor from the type literal and invoke it like so: 您可以从类型文字中检索构造函数并按如下方式调用它:

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

Though there may be a way to do the above, in order to complete the updates to my cmdlet and proceed forward with my project I went a hybrid route. 尽管可能有上述方法,但是为了完成对我的cmdlet的更新并继续进行我的项目,我选择了一条混合路线。

The reason why I started exploring the [Microsoft.Web.Administration] namespace was that it provided information on the data types where the typical way I was manipulating IIS settings failed using Get/Set/Add-WebConfigurationProperty. 我开始探索[Microsoft.Web.Administration]命名空间的原因是,它提供了有关数据类型的信息,在这些数据类型中,使用Get / Set / Add-WebConfigurationProperty操作IIS设置的典型方法失败了。

The specific failure is in reporting back valid data types for Enums. 特定的失败是报告了Enums的有效数据类型。 Take for instance ProcessModel.IdentityTypes. 以ProcessModel.IdentityTypes为例。 There is a set of valid entries for an IdentityType. IdentityType有一组有效的条目。 However the following doesn't provide you with those valid types, so you either have to create static instances of them inside your cmdlet, or some other external data source, whereas I wanted Microsoft to provide them either through IIS itself, or through the classes attached to these configuration elements so the cmdlet would need minimal updating as IIS versions/configuration elements change. 但是,以下内容没有为您提供这些有效的类型,因此您必须在cmdlet或其他外部数据源中创建它们的静态实例,而我希望Microsoft通过IIS本身或通过类提供它们附加到这些配置元素,因此随着IIS版本/配置元素的更改,该cmdlet将需要进行最少的更新。

This code returns Boolean 此代码返回布尔值

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

However, this code returns string, which is true, but I needed to know that it is an enum and I needed to know the proper values. 但是,此代码返回的是字符串,这是正确的,但我需要知道它是一个枚举,并且需要知道正确的值。

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

Using a mix of both the Namespace and the traditional Get-WebConfigurationProperty commands I can successfully now test for data types, as well as gather proper values for enums dynamically in code. 现在,结合使用命名空间和传统的Get-WebConfigurationProperty命令,我现在可以成功测试数据类型,并在代码中动态收集枚举的正确值。 If there is interest I can post the entire validation code here that I'm using for this cmdlet. 如果有兴趣,我可以在此cmdlet上张贴完整的验证代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM