2

I'm attempting to dynamically use the Microsoft.Web.Administration namespace within a powershell cmdlet.

Is there a way to add a variable into a Namespace.Class declaration.

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.ApplicationPool].GetProperty("Recycling")

If you spit out the PropertyType of the above using this

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

You get this result,

Microsoft.Web.Administration.ApplicationPoolRecycling

which is another class. I now want to access this class dynamically within the 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. 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.

I have a script that automates the configuration of many IIS components. 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). 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. 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. If it is not a TimeSpan data type issues will arise when being added to the 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. 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:

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

And you'll get 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. 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. 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:

[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.

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.

4

2 回答 2

0

您可以从类型文字中检索构造函数并像这样调用它:

$type = [Microsoft.Web.Administration.ApplicationPoolRecycling]
$ctor = $type.GetConstructor('NonPublic,Instance',$null,@(),$null)
$appPoolRecyclingInstance = $ctor.Invoke($null)
于 2017-06-10T13:42:47.573 回答
0

尽管可能有一种方法可以完成上述操作,但为了完成对我的 cmdlet 的更新并继续我的项目,我采用了混合路线。

我开始探索 [Microsoft.Web.Administration] 命名空间的原因是它提供了有关我使用 Get/Set/Add-WebConfigurationProperty 操作 IIS 设置的典型方式失败的数据类型的信息。

具体的失败在于报告 Enums 的有效数据类型。以 ProcessModel.IdentityTypes 为例。IdentityType 有一组有效条目。但是,以下内容没有为您提供这些有效类型,因此您必须在 cmdlet 或其他一些外部数据源中创建它们的静态实例,而我希望 Microsoft 通过 IIS 本身或通过类来提供它们附加到这些配置元素,因此当 IIS 版本/配置元素更改时,cmdlet 需要最少的更新。

此代码返回布尔值

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

但是,此代码返回字符串,这是真的,但我需要知道它是一个枚举,并且我需要知道正确的值。

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

结合使用命名空间和传统的 Get-WebConfigurationProperty 命令,我现在可以成功地测试数据类型,并在代码中动态地为枚举收集适当的值。如果有兴趣,我可以在此处发布我用于此 cmdlet 的整个验证代码。

于 2017-06-12T18:52:26.020 回答