【问题标题】:PowerShell analysing variables and objectsPowerShell 分析变量和对象
【发布时间】:2020-02-15 09:27:01
【问题描述】:

我发现我经常使用.GetType()| Get-Member,有时我忘记了它是.GetType,我尝试.Get-Type duh!错误!),所以我一直在编写一个函数来尝试快速收集该信息。事实证明,这在控制台上工作时非常有用(我确保将核心命令放在每个输出之前,这样我就永远不会忘记与实际命令的连接,所以更多的技术摘要可以让我与语言保持联系)。

我很好奇是否有额外的复合命令来提取有用的通用信息,我们可以使用这些信息来报告给定对象的结构(我们可以以非常紧凑的摘要格式快速获得的东西,即使更复杂的命令是需要对给定对象进行一些有用的见解)?

$a = @(1,2,"x") ; obj $a。这将返回 71 个方法(System.String 和 System.Int32)类型,因此我已将重复项删除到 50 个(很高兴快速查看可用的内容,但也许还可以以某种方式提及包含在该数组中的不同类型?) .

• 某些输入当然会破坏功能,但即使是这样的 ScriptBlock 示例也可以正常工作obj {$a; $x}。您甚至可以执行obj "".GetType() 之类的操作来查看其中的方法和属性。

• 在GetType() 中使用.Module 可能是多余的,因为通常输出CommonLanguageRuntimeLibrary,但可能来自这些成员的其他有用信息(当然,每件事在不同的时间都有用,但我很好奇通用摘要输出)?

• 一般而言,您使用或可能有助于在快速摘要视图中破解开放对象信息的任何改进或其他复合命令会很高兴知道吗? :-)

更新为@Clint 建议的-Force

function obj ($cmd) {
    if ($cmd -eq $null) { Write-Host "Object is `$null" ; return } 
    Write-Host "Contents:" -F Cyan
    $cmd
    ""
    Write-Host "(`$object).GetType()" -F Cyan -NoNewline ; Write-Host " :: [BaseType|Name|IsPublic|IsSerial|Module]"
    ($cmd).GetType() | % { "$($_.BaseType), $($_.Name), $($_.IsPublic), $($_.IsSerializable), $($_.Module)" }
    ""
    Write-Host "`$object | Get-Member -Force" -F Cyan
    $m = "" ; $p = "" ; $pp = "" ; $np = "" ; $sp = ""
    $msum = 0 ; $psum = 0 ; $ppsum = 0 ; $npsum = 0 ; $spsum = 0
    $($cmd | Get-Member -Force) | % {
        if ($_.MemberType -eq "Method") { if(!($m -like "*$($_.Name),*")) { $m += "$($_.Name), " ; $msum++ } }
        if ($_.MemberType -eq "Property") { if(!($p -like "*$($_.Name),*")) { $p += "$($_.Name), " ; $psum++ } }
        if ($_.MemberType -eq "ParameterizedProperty") { if(!($pp -like "*$($_.Name),*")) { $pp += "$($_.Name), " ; $ppsum++} }
        if ($_.MemberType -eq "NoteProperty") { if(!($np -like "*$($_.Name),*")) { $np += "$($_.Name), " ; $npsum++ } }
        if ($_.MemberType -eq "ScriptProperty") { if(!($sp -like "*$($_.Name),*")) { $sp += "$($_.Name), " ; $npsum++ } }
    }
    if($msum -ne 0) { Write-Host ":: Method [$msum] => $($m.TrimEnd(", "))" }
    if($psum -ne 0) { Write-Host ":: Property [$psum] => $($p.TrimEnd(", "))" }
    if($ppsum -ne 0) { Write-Host ":: ParameterizedProperty [$ppsum] => $($pp.TrimEnd(", "))" }
    if($npsum -ne 0) { Write-Host ":: NoteProperty [$npsum] => $($np.TrimEnd(", "))" }
    if($spsum -ne 0) { Write-Host ":: ScriptProperty [$spsum] => $($sp.TrimEnd(", "))" }
    ""
}

输出示例:

C:\> $a = @(123,"x")
C:\> def $a
Contents:
123
x

($object).GetType() :: [BaseType|Name|IsPublic|IsSerial|Module]
array, Object[], True, True, CommonLanguageRuntimeLibrary

$object | Get-Member -Force
:: Method [50] => CompareTo, Equals, GetHashCode, GetType, GetTypeCode, ToBoolean, ToByte, ToChar, ToDateTime, ToDecimal, ToDouble, ToInt16,
ToInt32, ToInt64, ToSByte, ToSingle, ToString, ToType, ToUInt16, ToUInt32, ToUInt64, Clone, Contains, CopyTo, EndsWith, GetEnumerator,
get_Chars, get_Length, IndexOf, IndexOfAny, Insert, IsNormalized, LastIndexOf, LastIndexOfAny, Normalize, PadLeft, PadRight, Remove, Replace,
Split, StartsWith, Substring, ToCharArray, ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant, Trim, TrimEnd, TrimStart
:: Property [1] => Length
:: ParameterizedProperty [1] => Chars

【问题讨论】:

  • 是强制的 -F 吗?
  • 它是-ForegroundColor 的简写,只要不与另一个开关冲突,PowerShell 允许您截断任何开关,所以我使用-F 表示ForegroundColour,使用-B 表示-BackgroundColor。节省打字! :)
  • 啊我明白了,你可以使用-Force然后

标签: powershell console


【解决方案1】:

你已经总结的很好了,你不妨补充一下

  • object | gm -Force # To add members that are usually hidden by default
    

    Get-Member 命令使用 Force 参数添加内在 成员和编译器生成的对象的成员来显示。 Get-Member 获取这些成员,但默认隐藏它们。

    内在成员(PSBase、PSAdapted、PSObject、PSTypeNames)

    编译器生成的 get_ 和 set_ 方法

    MSDN文档

  • object.PSObject #Wraps the information pertaining to different members
    object.PSObject | Select-Object -ExpandProperty Properties #You can do the same for other members 
    
  • $object |gm -force -static #even with force the static members are not listed by default, so we need to explicitly mention static 
    
  • 也许还可以以某种方式提及该数组中包含的不同类型?)。

    $object | ForEach-Object {$_.GetType().FullName}
    
  • OffTopic,另外,如果你想捕捉函数执行所花费的时间

    $sw = [Diagnostics.Stopwatch]::StartNew()    
    $sw.Stop()
    Write-Host "Execution time" $sw.Elapsed.Milliseconds "ms"
    

【讨论】:

  • 有趣,我不知道,那已经是一件有用的事情了!希望人们可以向我展示更多用于探索对象的技巧和完全不同的命令(或优化方法)。我看到对于一个数组,-Force 公开了两个额外的方法:get_Chars, get_Length,由于Chars(ParameterizedProperty)和Length(属性),这部分是多余的,但很高兴知道。
  • @YorSubs 您好,您好,只是签到以了解这是否回答了您的查询,或者您是否希望改进其他任何内容,否则如果您可以将其标记为已解决,那就太好了 :)
  • 克林特肯定有部分原因。我只是想知道另一个重要的答案。我对以这样的方式利用 PowerShell 感到好奇,并且也在考虑对这个问题进行赏金。 :)
  • @YorSubs,啊,好吧,合理的赏金将是吸引注意力的明智之举:D
  • @YorSubs,我会尝试在这个主题上挖掘更多内容,看看我能找到什么;)
【解决方案2】:

知道 PowerShell 在显示对象时不是很清楚(例如:''$Null@()@{$Null) 都会导致空行,或什么都没有 em>),我认为您需要从问题的第一段开始,并可视化所讨论对象的类型和结构,然后关注可能在每个问题上都不同的方法 对象结构中的级别。

*注意:您还可以使用.PSTypeNames 来显示类型,这在$Null 上不会出错(假设strict mode 没有打开)。

举个更高级的例子:$a = @($Null, 1, '2', @(3))

Write-Host

Write-Host cmdlet(由您的函数使用)并没有透露太多关注类型和对象结构的位置: (除了你应该尽量避免Write-Host,因为它是主机特定的)

PS C:\> $a
1
2
3

PS C:\> Write-Host $a
 1 2 3

为了更好地理解这样的对象,您可能需要序列化它。 Quote from WikiPedia:

在计算机科学中,在数据存储方面,序列化(或 序列化)是翻译数据结构或对象的过程 将状态转换为可以存储的格式(例如,在文件中或 内存缓冲区)或传输(例如,通过网络 连接链接)和稍后重建(可能在不同的 电脑环境)

这意味着对象的字符串表示基本上包含了重建(和理解)对象(或至少到一定程度)的所有信息。

这里可能会用到一些序列化程序:

ConvertTo-Json

ConvertTo-Json cmdlet 将任何对象转换为 JavaScript 对象表示法 (JSON) 格式的字符串,因此可能有助于了解结构,但不适用于 PowerShell 类型:

PS C:\> ConvertTo-Json $a
[
  null,
  1,
  "2",
  [
    3
  ]
]

ConvertTo-Xml

ConvertTo-Xml cmdlet 创建一个非常冗长的对象的基于 XML 的表示:

PS C:\> ConvertTo-Xml $a -as String
<?xml version="1.0" encoding="utf-8"?>
<Objects>
  <Object Type="System.Object[]">
    <Property />
    <Property Type="System.Int32">1</Property>
    <Property Type="System.String">2</Property>
    <Property Type="System.Object[]">
      <Property Type="System.Int32">3</Property>
    </Property>
  </Object>
</Objects>**strong text**

PSSerializer

此 (.Net) 类提供用于序列化 PSObject 的公共功能,并由 PowerShell 在内部使用:

PS C:\> [System.Management.Automation.PSSerializer]::Serialize($a)
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Object[]</T>
      <T>System.Array</T>
      <T>System.Object</T>
    </TN>
    <LST>
      <Nil />
      <Obj RefId="1">
        <I32>1</I32>
      </Obj>
      <S>2</S>
      <Obj RefId="2">
        <TNRef RefId="0" />
        <LST>
          <I32>3</I32>
        </LST>
      </Obj>
    </LST>
  </Obj>
</Objs>

ConvertTo-Expression

ConvertTo-Expression cmdlet 源自以下问题:Save hash table in PowerShell object notation (PSON),并为您提供对象的 PowerShell 表示:

隐式

PS C:\> ConvertTo-Expression $a
$Null,
1,
'2',
(,3)

显式

PS C:\> ConvertTo-Expression $a -Strong
[array](
        $Null,
        [int]1,
        [string]'2',
        [array][int]3
)

对于非 PowerShell 原生的资源管理器 .Net 类:
*请注意,您可能无法从 -Explore 表达式重构

PS C:\> Get-Service | Select -First 1 | ConvertTo-Expression -Strong -Explore
[System.ServiceProcess.ServiceController]@{
        'UserName' = [string]''
        'Description' = [string]'Runtime for activating conversational agent applications'
        'DelayedAutoStart' = [bool]$False
        'BinaryPathName' = [string]'C:\WINDOWS\system32\svchost.exe -k AarSvcGroup -p'
        'StartupType' = [Microsoft.PowerShell.Commands.ServiceStartupType]3
        'CanPauseAndContinue' = [bool]$False
        'CanShutdown' = [bool]$False
        'CanStop' = [bool]$False
        'DisplayName' = [string]'Agent Activation Runtime_131b90'
        'DependentServices' = [System.ServiceProcess.ServiceController[]]@()
        'MachineName' = [string]'.'
        'ServiceName' = [string]'AarSvc_131b90'
        'ServicesDependedOn' = [System.ServiceProcess.ServiceController[]]@()
        'StartType' = [System.ServiceProcess.ServiceStartMode]3
        'ServiceHandle' = $Null
        'Status' = [System.ServiceProcess.ServiceControllerStatus]1
        'ServiceType' = [System.ServiceProcess.ServiceType]224
        'Site' = $Null
        'Container' = $Null
}

要深入了解已知(加速)PowerShell 类型

PS C:\>Get-Date | Select-Object -Property * | ConvertTo-Expression
Date        : 1963-10-07 12:00:00 AM
DateTime    : Monday, October 7, 1963 10:47:00 PM
Day         : 7
DayOfWeek   : Monday
DayOfYear   : 280
DisplayHint : DateTime
Hour        : 22
Kind        : Local
Millisecond : 0
Minute      : 22
Month       : 1
Second      : 0
Ticks       : 619388596200000000
TimeOfDay   : 22:47:00
Year        : 1963

【讨论】:

  • 这很棒@iRon。我看到我的简单脚本完全破坏了像$a = @($Null, 1, '2', @(3)) 这样的更复杂的对象。我可能永远不会创建如此复杂的对象,但是,拥有一个可以解构对象的脚本会很好(至少在合理可行的范围内!)。 JSON 更适合我的紧凑性,这比我的“内容”输出要好得多,所以我肯定会在那里使用 ConvertTo-Json 并使用你的其他注释。很棒的东西,谢谢。
猜你喜欢
  • 2020-06-05
  • 2019-04-06
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多