我正在尝试检查Powerhell脚本是否以管理员身份运行。在搜索网络后,我得到了一些工作正常的示例代码。
为了得到这个WindowsPrincipal
对象,我发现了两个示例代码如下。
第一:
New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
第二:
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
第二个让我感到困惑。
根据这个页面,我知道[ ]
是一个转型运算子。根据此页面,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脚本有什么区别?
发布于 2019-04-23 14:21:20
TLDR:PowerShell可以做Magic。C#不能做magic。
PowerShell可以同时兼顾juggle Chainsaws,bowling和balls。
如果提前定义C#,它们只能juggle balls。试图将新的链锯添加到杂耍程序中会导致编译器抱怨。
问题是函数,对象类型和如何转换对象类型之间的差异。
System.Security.Principal
是基础.NET库。该库可以由C#和PowerShell使用。
WindowsIdentity.GetCurrent()
是库中的一个函数。
WindowsPrincipal
是一种对象类型,例如string
或int
。
调用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会做Magic,我会在一分钟内完成。首先让我们看看正确的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:
基本上,无论何时在PowerShell中进行类型转换,它都会执行Magic并尝试每种方法为您动态转换类型。这就是为什么它能够处理你在变戏法者身上扔新的电锯或保龄球的原因。PowerShell可以解释我们没有尝试将链锯转换为球,而是链锯只是另一个对象,我们已经知道如何处理对象。
这种解释不是.NET的一部分,因此C#不能这样做,我们必须明确定义所有内容,并正确地完成所有事情。这意味着您可以将所有C#和.NET代码转换为有效的PowerShell代码,但不是相反。
https://stackoverflow.com/questions/-100006656
复制相似问题