gpt4 book ai didi

powershell - “New-Object WindowsPrincipal([WindowsIdentity]::GetCurrent())”和 “[WindowsPrincipal] [WindowsIdentity]::GetCurrent()”之间的区别

转载 作者:行者123 更新时间:2023-12-01 13:15:13 30 4
gpt4 key购买 nike

我正在尝试检查Powerhell脚本是否以管理员身份运行。
在网上搜索后,我得到了一些运行良好的示例代码。
为了获得WindowsPrincipal对象,我发现了以下两个示例代码。

第一:

New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

第二:

[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

第二个让我感到困惑。

根据 this page,我知道 [ ]是强制转换运算符。
根据 this page,PowerShell是建立在.NET Framework之上的。在我看来,这意味着可以将上述两个PowerShell脚本转换为C#。
所以我尝试一下。
当我将第一个PowerShell脚本转换为C#时。它如下工作正常。
## First PowerShell script
New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

// C#
var wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());

但是,当我尝试将第二个PowerShell脚本转换为C#时。我得到编译错误。 IDE告诉我 WindowsIdentity无法转换为 WindowsPrincipal
## Second PowerShell script
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

// both C# code below cause compile error
var wp = System.Security.Principal.WindowsIdentity.GetCurrent() as System.Security.Principal.WindowsPrincipal;
var wp2 = (System.Security.Principal.WindowsPrincipal)System.Security.Principal.WindowsIdentity.GetCurrent();

就像我在C#上尝试过的一样, System.Security.Principal.WindowsIdentity类型不能直接转换为 System.Security.Principal.WindowsPrincipal类型。但是为什么第二个PowerShell脚本可用?
还是第二个PowerShell脚本中的 [ ]运算符不是类型转换运算符?
也许这个运算符不仅仅可以转换对象类型呢?
第一个PowerShell脚本和第二个PowerShell脚本之间有什么区别?
我还有其他东西吗?

最佳答案

TLDR:PowerShell可以执行魔术。 C#不能做魔术。

PowerShell可以同时处理电锯,保龄球和球。

如果C#是提前定义的,它们只能对它们进行处理。尝试在杂耍例程中添加新的电锯会导致杂耍者(编译器)抱怨。

问题在于功能,对象类型以及如何转换对象类型之间的差异。
System.Security.Principal是基本的.NET库。该库可由C#和PowerShell使用。
WindowsIdentity.GetCurrent()是库中的函数。
WindowsPrincipal是一种对象类型,例如像stringint

调用WindowsIdentity.GetCurrent()将返回一个WindowsIdentity对象,然后可以在您的代码中使用该对象。

由于WindowsIdentity不一定是您要使用的对象类型,因此我们想使用WindowsPrincipal对象。不幸的是我们不能直接从WindowsIdentity转换为WindowsPrincipal对象。我们必须使用WindowsPrincipal构造函数。

在PowerShell中,您可以通过New-Object cmdlet或首次使用变量来创建一个新对象。这样做的方便是因为PowerShell是脚本语言,其中使用了变量,例如$a = 1隐式创建一个新变量。例如

PS C:\> Get-Variable test
Get-Variable : Cannot find a variable with the name 'test'.
At line:1 char:1
+ Get-Variable test
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (test:String) [Get-Variable], ItemNotFoundException
+ FullyQualifiedErrorId : VariableNotFound,Microsoft.PowerShell.Commands.GetVariableCommand

PS C:\> $test = 1
PS C:\> Get-Variable test

Name Value
---- -----
test 1

使用 New-Object示例:
New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

这是正确的方法。您将创建一个类型为 WindowsPrincipal的新对象,并将Windows身份传递给构造函数。

第二种方法:
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

是“错误的”,因为它使用了强制类型转换,并且前面我们说过我们不能直接从 WindowsIdentity强制转换为 WindowsPrincipal对象。那么这是如何工作的呢?好吧,我之前说过,PowerShell可以发挥魔力,好一会儿我会讲到这一点。首先让我们看一下正确的C#代码:

在C#中调用.NET Framework特定功能的语法与PowerShell确实有所不同。导致出现特定编译错误的原因是,因为我们正在尝试投射对象,而我们无法这样做。

这个例子:
using System.Security.Principal;
var wp = WindowsIdentity.GetCurrent() as WindowsPrincipal; // compile error

编译器将其转换为:
WindowsIdentity.GetCurrent()

运行函数 GetCurrent()
as WindowsPrincipal;

期望返回类型为 WindowsPrincipal <-编译时错误。编译错误是因为该函数未返回 WindowsPrincipal类型,而是返回了 WindowsIdentity类型。

第二个示例也是一个变体,因为它无法直接投射对象,因此无法使用。例如
using System.Security.Principal;
var wp = (WindowsPrincipal) WindowsIdentity.GetCurrent(); // compile error

编译器将其转换为:
WindowsIdentity.GetCurrent()

运行 GetCurrent()函数,并返回 WindowsIdentity对象。
(WindowsPrincipal) WindowsIdentity.GetCurrent();

WindowsIdentity对象并将其直接转换为 WindowsPrincipal类型,这是不能的。

正确的 C#代码 也需要new关键字是:
var wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());

编译器将其转换为:
WindowsIdentity.GetCurrent()

运行GetCurrent()函数,并返回WindowsIdentity对象。
new WindowsPrincipal(WindowsIdentity.GetCurrent())

创建一个新的WindowsPrincipal对象,将WindowsIdentity对象传递给构造函数。现在可以使用了。

那么为什么第二个例子呢:
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

通过执行“错误”操作在PowerShell中工作?由于PowerShell是一种脚本语言,并且可以即时进行解释,并且可以使用 Magic ,因此可以解释以上内容并执行一些Type Conversion Magic Quote:
  • 直接分配。 如果您的输入是可直接分配的,只需将您的输入强制转换为该类型。
  • 基于语言的转换。 当目标类型为void, bool(boolean) 值,字符串,数组,哈希表,PSReference(即:[ref]),XmlDocument(即:[xml])时,将完成这些基于语言的转换。委托(delegate)(以支持ScriptBlock到委托(delegate)的转换)和枚举。
  • 解析转换。 如果目标类型定义了接受该输入的Parse()方法,请使用该方法。
  • 静态创建转换。 如果目标类型定义了接受该输入的静态:: Create()方法,请使用该方法。
  • 构造函数转换。 如果目标类型定义了一个接受您输入的构造函数,请使用它。
  • 转换。 如果目标类型从源类型定义了隐式或显式强制转换运算符,请使用该类型。如果源类型为目标类型定义了隐式或显式强制转换运算符,请使用该类型。
  • I可转换。 如果源类型定义了一个IConvertible实现,该实现知道如何转换为目标类型,请使用它。
  • IDictionary转换。 如果源类型是IDictionary(即:哈希表),请尝试使用其默认构造函数创建目标类型的实例,然后使用IDictionary中的名称和值在源对象上设置属性。
  • PSObject属性转换。 如果源类型是PSObject,请尝试使用其默认构造函数创建目标类型的实例,然后使用PSObject中的属性名称和值在源对象上设置属性。 。如果名称映射到方法而不是属性,请使用值作为参数来调用该方法。
  • 类型转换器转换。 如果存在注册的TypeConverter或PSTypeConverter可以处理转换,请执行此操作。您可以通过types.ps1xml文件(请参阅:$ pshome \ Types.ps1xml)或通过Update-TypeData注册TypeConverter。

  • 基本上,每当您在PowerShell中执行类型转换时,它将执行Magic并尝试每种方法为您动态地动态转换类型。这就是为什么它可以处理您在杂耍者身上扔新的电锯或保龄球的原因。 PowerShell可以解释为我们不是在试图将电锯转换为球,而是将电锯只是另一个对象,并且我们已经知道如何处理对象。

    这种解释不是.NET的一部分,因此C#无法做到这一点,因此我们必须显式定义所有内容,并正确执行所有操作。这意味着您可以将所有C#和.NET代码转换为有效的PowerShell代码,但不能反过来。

    关于powershell - “New-Object WindowsPrincipal([WindowsIdentity]::GetCurrent())”和 “[WindowsPrincipal] [WindowsIdentity]::GetCurrent()”之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55732190/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com