首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >“New-Object WindowsPrincipal([WindowsIdentity] :: GetCurrent())”和“[WindowsPrincipal] [WindowsIdentity] :: GetCurrent()”之间的区别

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

Stack Overflow用户
提问于 2019-04-23 04:21:48
回答 1查看 0关注 0票数 0

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

第一:

代码语言:javascript
复制
New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

第二:

代码语言:javascript
复制
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

第二个让我感到困惑。

根据这个页面,我知道[ ]是一个转型运算子。根据此页面,PowerShell构建于.NET Framework之上。在我看来,这意味着上面两个PowerShell脚本可以转换为C#。 所以我试试吧。 当我将第一个PowerShell脚本转换为C#时。它工作正常如下。

代码语言:javascript
复制
## First PowerShell script
New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

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

但是当我尝试将第二个PowerShell脚本转换为C#时。我得到编译错误。IDE告诉我WindowsIdentity无法转换为WindowsPrincipal

代码语言:javascript
复制
## 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脚本有什么区别?

EN

回答 1

Stack Overflow用户

发布于 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是一种对象类型,例如stringint

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

由于WindowsIdentity不一定是你要使用的对象类型,我们希望使用WindowsPrincipal对象。不幸的是我们无法直接将WindowsIdentity对象转换为WindowsPrincipal对象。必须使用WindowsPrincipal构造函数。

在PowerShell中,可以通过New-Objectcmdlet 创建新对象,也可以通过首次使用变量来创建新对象。这种方便是因为PowerShell是一种脚本语言,使用变量例如$a = 1隐式创建一个新变量。例如

代码语言:javascript
复制
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示例:

代码语言:javascript
复制
New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

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

第二种方法:

代码语言:javascript
复制
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

是“错误的”,因为它使用了铸造,而早先我们说过我们不能直接从WindowsIdentity铸造到WindowsPrincipal对象。那么这是如何工作的呢?好吧,我之前说过,PowerShell会做Magic,我会在一分钟内完成。首先让我们看看正确的C#代码:

在C#中调用.NET Framework特定函数在语法上与PowerShell不同。你得到的特定编译错误的原因是因为我们正在尝试转换对象,我们不能。

例子:

代码语言:javascript
复制
using System.Security.Principal;
var wp = WindowsIdentity.GetCurrent() as WindowsPrincipal; // compile error

编译器将其转换为:

代码语言:javascript
复制
WindowsIdentity.GetCurrent()

功能 GetCurrent()函数

代码语言:javascript
复制
as WindowsPrincipal;

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

第二个示例也是一个不起作用的变体,因为它无法直接转换对象。例如

代码语言:javascript
复制
using System.Security.Principal;
var wp = (WindowsPrincipal) WindowsIdentity.GetCurrent(); // compile error

编译器将其转换为:

代码语言:javascript
复制
WindowsIdentity.GetCurrent()

运行函数GetCurrent()并返回WindowsIdentity对象。

代码语言:javascript
复制
(WindowsPrincipal) WindowsIdentity.GetCurrent();

WindowsIdentity对象并直接将其转换为WindowsPrincipal的类型。

正确的 C#代码也需要new关键字:

代码语言:javascript
复制
var wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());

编译器将其转换为:

代码语言:javascript
复制
WindowsIdentity.GetCurrent()

运行函数GetCurrent()并返回WindowsIdentity对象。

代码语言:javascript
复制
new WindowsPrincipal(WindowsIdentity.GetCurrent())

创建一个将WindowsPrincipal对象传递WindowsIdentity给构造函数的新对象。哪个现在有效。

那么为什么第二个例子:

代码语言:javascript
复制
[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

做一些“错误”的事情在PowerShell中工作?因为PowerShell是一种脚本语言,并且可以动态解释,并且可以使用Magic,它可以解释上面的内容并执行一些Type Conversion Magic Quote:

  1. 直接分配。如果您的输入可以直接分配,只需将输入转换为该类型即可。
  2. 基于语言的转换。当目标类型为void,Boolean,String,Array,Hashtable,PSReference(即:[ref]),XmlDocument(即:[xml])时,将完成这些基于语言的转换。委托(支持ScriptBlock委派转换)和Enum。
  3. 解析转换。如果目标类型定义了获取该输入的Parse()方法,请使用该方法。
  4. 静态创建转换。如果目标类型定义了一个采用该输入的static :: Create()方法,请使用它。
  5. 构造函数转换。如果目标类型定义了一个获取输入的构造函数,请使用它。
  6. 转换转换。如果目标类型从源类型定义隐式或显式强制转换运算符,请使用它。如果源类型为目标类型定义隐式或显式强制转换运算符,请使用它。
  7. IConvertible转换。如果源类型定义了一个知道如何转换为目标类型的IConvertible实现,请使用它。
  8. IDictionary转换。如果源类型是IDictionary(即:Hashtable),请尝试使用其默认构造函数创建目标类型的实例,然后使用IDictionary中的名称和值来设置源对象的属性。
  9. PSObject属性转换。如果源类型是PSObject,请尝试使用其默认构造函数创建目标类型的实例,然后使用PSObject中的属性名称和值来设置源对象的属性。。如果名称映射到方法而不是属性,则以值作为其参数调用该方法。
  10. TypeConverter转换。如果有可以处理转换的已注册TypeConverter或PSTypeConverter,请执行此操作。您可以通过types.ps1xml文件(请参阅:$ pshome \ Types.ps1xml)或通过Update-TypeData注册TypeConverter。

基本上,无论何时在PowerShell中进行类型转换,它都会执行Magic并尝试每种方法为您动态转换类型。这就是为什么它能够处理你在变戏法者身上扔新的电锯或保龄球的原因。PowerShell可以解释我们没有尝试将链锯转换为球,而是链锯只是另一个对象,我们已经知道如何处理对象。

这种解释不是.NET的一部分,因此C#不能这样做,我们必须明确定义所有内容,并正确地完成所有事情。这意味着您可以将所有C#和.NET代码转换为有效的PowerShell代码,但不是相反。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100006656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档