【发布时间】:2021-09-01 16:36:29
【问题描述】:
我正在编写一个二进制 PowerShell 模块,该模块与 ActiveDirectory 模块非常相似,它将具有许多 cmdlet 和类型,这些 cmdlet 和类型可能会返回比默认属性集更多的属性 - 而这些属性 (100+) 取决于用户请求。就像 AD 模块一样,我想返回具有所请求属性的类型,以便它对用户透明,即不是一个包含许多他们没有请求的空属性的巨大类。
我正在查看 ActiveDirectory 模块的文档,我注意到像 ADUser 和 ADComputer 这样的东西最终是从 ADPropertyCollection 继承的.
这并没有真正解释 PowerShell 如何灵活地呈现 AD 类型,即
(Get-ADUser -Identity some.user).GetType()
(Get-ADUser -Identity some.user -Properties *).GetType()
# Both return a type of ADUser, despite have drastically different amounts of properties.
直到我查看了 AD 模块的 Types ps1xml 文件,它呈现如下内容:
<Types>
<!-- other types -->
<Type>
<Name>Microsoft.ActiveDirectory.Management.ADUser</Name>
<TypeAdapter>
<TypeName>Microsoft.ActiveDirectory.Management.ADEntityAdapter</TypeName>
</TypeAdapter>
</Type>
</Types>
所以我猜“magic”属性的来源是ADEntityAdapter,它继承自抽象类PSPropertyAdapter。
我现在的问题是我不确定如何实现它,并且没有任何易于搜索的示例来实现它。我很欣赏它是一个真正的边缘案例。我在下面的一个非常粗略的实现中做了一个小的尝试,请忽略任何代码错误——我当然不会真正编写下面的代码。我只是想至少尝试表明我已经考虑过这一点。
using System.Collections.Generic;
namespace Sample
{
public class PropertyCollection
{
public string Id { get; set; }
public Dictionary<string, object> Attributes { get; set; }
public PropertyCollection()
{
this.Id = "SampleID";
this.Attributes = new Dictionary<string, object>();
for (var i = 0; i < 10; i++)
{
this.Attributes.Add("KeyAttribute" + i, i);
}
for (var i = 10; i < 100; i++)
{
this.Attributes.Add("OtherAttribute" + i, i);
}
}
}
}
namespace Sample
{
public class ReturnedClass : PropertyCollection
{
public string SomeName { get; set; }
public ReturnedClass() : base() { }
}
}
using System;
using System.Collections.ObjectModel;
using System.Management.Automation;
namespace Sample
{
public class PropertyEntityAdapter : PSPropertyAdapter
{
public override Collection<PSAdaptedProperty> GetProperties(object baseObject)
{
PropertyCollection pc = baseObject as PropertyCollection;
if (pc == null)
{
throw new Exception("Some Exception");
}
Collection<PSAdaptedProperty> collection = new Collection<PSAdaptedProperty>();
foreach (string name in pc.Attributes.Keys)
{
collection.Add(new PSAdaptedProperty(name, null));
}
return collection;
}
public override PSAdaptedProperty GetProperty(object baseObject, string propertyName)
{
PropertyCollection pc = baseObject as PropertyCollection;
if (pc.Attributes.TryGetValue(propertyName, out object pcValue))
{
return new PSAdaptedProperty(propertyName, pcValue);
}
throw new Exception("Prop not found");
}
public override string GetPropertyTypeName(PSAdaptedProperty adaptedProperty)
{
if (adaptedProperty == null)
{
throw new Exception("prop null");
}
PropertyCollection pc = adaptedProperty.BaseObject as PropertyCollection;
if (pc == null)
{
throw new Exception("not found");
}
if (pc.Attributes.TryGetValue(adaptedProperty.Name, out object pcValue))
{
return pcValue.GetType().FullName;
}
return pc.GetType().FullName;
}
public override object GetPropertyValue(PSAdaptedProperty adaptedProperty)
{
if (adaptedProperty?.BaseObject == null || adaptedProperty?.Name == null)
{
throw new Exception("prop null");
}
PropertyCollection pc = adaptedProperty.BaseObject as PropertyCollection;
if (pc == null)
{
throw new Exception("not found");
}
if (pc.Attributes.TryGetValue(adaptedProperty.Name, out object pcValue))
{
return pcValue;
}
return null;
}
public override bool IsGettable(PSAdaptedProperty adaptedProperty)
{
if (adaptedProperty == null)
{
throw new Exception("prop null");
}
PropertyCollection pc = adaptedProperty.BaseObject as PropertyCollection;
if (pc == null)
{
throw new Exception("not found");
}
if (pc.Attributes.ContainsKey(adaptedProperty.Name))
{
return true;
}
return false;
}
public override bool IsSettable(PSAdaptedProperty adaptedProperty)
{
return false;
}
public override void SetPropertyValue(PSAdaptedProperty adaptedProperty, object value)
{
throw new System.NotImplementedException();
}
}
}
** 我故意没有为 Set* 方法添加任何代码以减少此处所需的代码。如果上面看起来是对的,那么我确定我知道该怎么做。
以前有人做过吗?有没有非常基本的例子?我是在正确的道路上,还是我误解了?提前致谢。
【问题讨论】:
-
是否值得添加
activedirectory标签来吸引合适的受众? -
嗨@SantiagoSquarzon,是的,我想过,但这只是对所需行为的说明,而不是对 ActiveDirectory 本身的查询。我想将此通用保留为二进制 cmdlet。我可以反编译模块 dll,但这些代码库通常令人困惑(我不知道我在做什么),我希望有人能说我的基本理解是正确的,建议修复或链接到我的示例或许有机会了解。 :-)
标签: c# powershell