今天我突然想到,经过这么多年习惯性地传递-NoTypeInformation
给Export-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 ,并且在这两种情况下,您都有反序列化的对象,这些对象不包含原始对象的方法,也没有以任何方式连接或代理原始对象。#TYPE
CSV:
System.Management.Automation.PSCustomObject
String
显然,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
.