3

今天我突然想到,经过这么多年习惯性地传递-NoTypeInformationExport-Csv/ConvertTo-Csv以防止发出不受欢迎的评论行之后,也许Import-Csv/ConvertFrom-Csv能够重建具有原始属性类型的对象(而不是所有对象String),只要我没有压制那种类型的信息。我试了一下...

PS> Get-Service | ConvertTo-Csv

...并且,很长一段时间没有真正看到通过省略 发出的内容-NoTypeInformation,提醒它只包括输入对象的类型(实际上只是第一个对象),而不是成员的类型......

#TYPE System.ServiceProcess.ServiceController
"Name","RequiredServices","CanPauseAndContinue","CanShutdown","CanStop","DisplayName","DependentServices","MachineName","ServiceName","ServicesDependedOn","ServiceHandle","Status","ServiceType","StartType","Site","Container"
...

将序列化的结果类型信息进行比较,然后反序列化...

PS> Get-Service | ConvertTo-Csv | ConvertFrom-Csv | Get-Member


   TypeName: CSV:System.ServiceProcess.ServiceController

Name                MemberType   Definition
----                ----------   ----------
Equals              Method       bool Equals(System.Object obj)
GetHashCode         Method       int GetHashCode()
GetType             Method       type GetType()
ToString            Method       string ToString()
CanPauseAndContinue NoteProperty string CanPauseAndContinue=False
CanShutdown         NoteProperty string CanShutdown=False
CanStop             NoteProperty string CanStop=True
Container           NoteProperty object Container=null
DependentServices   NoteProperty string DependentServices=System.ServiceProcess.ServiceController[]
DisplayName         NoteProperty string DisplayName=Adobe Acrobat Update Service
MachineName         NoteProperty string MachineName=.
Name                NoteProperty string Name=AdobeARMservice
RequiredServices    NoteProperty string RequiredServices=System.ServiceProcess.ServiceController[]
ServiceHandle       NoteProperty string ServiceHandle=
ServiceName         NoteProperty string ServiceName=AdobeARMservice
ServicesDependedOn  NoteProperty string ServicesDependedOn=System.ServiceProcess.ServiceController[]
ServiceType         NoteProperty string ServiceType=Win32OwnProcess
Site                NoteProperty string Site=
StartType           NoteProperty string StartType=Automatic
Status              NoteProperty string Status=Running

...到没有类型信息的序列化然后反序列化的结果...

PS> Get-Service | ConvertTo-Csv -NoTypeInformation | ConvertFrom-Csv | Get-Member


   TypeName: System.Management.Automation.PSCustomObject

Name                MemberType   Definition
----                ----------   ----------
Equals              Method       bool Equals(System.Object obj)
GetHashCode         Method       int GetHashCode()
GetType             Method       type GetType()
ToString            Method       string ToString()
CanPauseAndContinue NoteProperty string CanPauseAndContinue=False
CanShutdown         NoteProperty string CanShutdown=False
CanStop             NoteProperty string CanStop=True
Container           NoteProperty object Container=null
DependentServices   NoteProperty string DependentServices=System.ServiceProcess.ServiceController[]
DisplayName         NoteProperty string DisplayName=Adobe Acrobat Update Service
MachineName         NoteProperty string MachineName=.
Name                NoteProperty string Name=AdobeARMservice
RequiredServices    NoteProperty string RequiredServices=System.ServiceProcess.ServiceController[]
ServiceHandle       NoteProperty string ServiceHandle=
ServiceName         NoteProperty string ServiceName=AdobeARMservice
ServicesDependedOn  NoteProperty string ServicesDependedOn=System.ServiceProcess.ServiceController[]
ServiceType         NoteProperty string ServiceType=Win32OwnProcess
Site                NoteProperty string Site=
StartType           NoteProperty string StartType=Automatic
Status              NoteProperty string Status=Running

...唯一的区别是TypeName从(以 为前缀的注释CSV:System.ServiceProcess.ServiceController指定的相同类型)更改为. 所有成员都是相同的,所有属性都是 type ,并且在这两种情况下,您都有反序列化的对象,这些对象不包含原始对象的方法,也没有以任何方式连接或代理原始对象。#TYPECSV:System.Management.Automation.PSCustomObjectString

显然,Microsoft 认为在 CSV 输出中包含这种类型的信息不仅是可取的,而且默认情况下也应该这样做。由于我不能真正问“他们为什么这样做?”,我想知道这些信息如何可能有用?序列化 cmdlet是否将它用于设置每个对象*-Csv之外的任何其他用途?TypeName为什么我希望这种类型的信息在 CSV 输出中“带内”传达,而不是仅仅......知道这个包含服务信息的文件来自System.ServiceProcess.ServiceController实例,或者甚至只是不关心原始类型是什么,只要它有我期望的属性吗?

我能想到的唯一两个用例是,如果您收到一个由未知 PowerShell 脚本创建的 CSV 文件,那么拥有类型信息可以帮助确定用于生成数据的应用程序/库/模块,或者如果您有一个可笑的试图根据类型信息刷新任意输入的通用脚本,像这样......

Import-Csv ... `
    | ForEach-Object -Process {
        # Original type name of the first record, not necessarily this record!
        $firstTypeName = $_.PSObject.TypeNames[0];

        if ($firstTypeName -eq 'CSV:System.ServiceProcess.ServiceController')
        {
            Get-Service ...
        }
        elseif ('CSV:System.IO.DirectoryInfo', 'CSV:System.IO.FileInfo' -contains $firstTypeName)
        {
            Get-ChildItem ...
        }
        elseif ($firstTypeName -eq 'CSV:Microsoft.ActiveDirectory.Management.ADObject')
        {
            Get-ADObject ...
        }
        ...
    }

...但这些都不是非常有说服力的例子,尤其是考虑到,正如我所指出的,这种类型的信息被认为非常重要,以至于默认包含在内。还有其他我没有想到的用例吗?或者这仅仅是“包含它而不需要它比需要它而不包含它更好(而且便宜)”的情况?

相关: PowerShell GitHub 问题,讨论了-NoTypeInformation在未来版本(6.0,根据 cmdlet 文档)中设置默认值,以及一个明显的共识,即没有必要省略-NoTypeInformation.

4

1 回答 1

2

如果您的 athing了解标头并且还知道如何构造other thing该类型的 an,那么thing可以想象,首先可以other thing从字符串表示中创建一个或多个 those 。我并不是说它很有用,但我说的是,如果 .csv 可能在另一种类型的文件可能不可用的情况下可用,那么这是一种潜在用途。出于类似于我在此处回答您的问题时提到的原因,我实际上可能会或可能不会这样做。

于 2018-08-08T01:18:52.003 回答