Powershell 为什么一个CmdLet的文本输出是格式化的,而另一个CmdLet的文本输出不是格式化的?
我已经编写了两个cmdlet,用于在Guid和Oracle的等效Guid之间进行转换,即它为用于存储Guid的原始列显示的字符串。第一个,Powershell 为什么一个CmdLet的文本输出是格式化的,而另一个CmdLet的文本输出不是格式化的?,powershell,formatting,powershell-5.0,cmdlets,Powershell,Formatting,Powershell 5.0,Cmdlets,我已经编写了两个cmdlet,用于在Guid和Oracle的等效Guid之间进行转换,即它为用于存储Guid的原始列显示的字符串。第一个,Convert GuidToRaw,接受GUID字符串param并输出原始字符串: var raw = GuidConverter.Core.GuidConverter.ToRaw(Input); WriteObject(raw); 其中raw具有类型string。运行此cmdlet时,我会得到一个简单的字符串输出: PS D:\SANRAL\NRA2>
Convert GuidToRaw
,接受GUID字符串param并输出原始字符串:
var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);
其中raw
具有类型string
。运行此cmdlet时,我会得到一个简单的字符串输出:
PS D:\SANRAL\NRA2> New-Guid | Convert-GuidToRaw
DD8386EE09231A43B7731880CCAD6B87
PS D:\SANRAL\NRA2>
我的另一个cmdlet,Convert RawToGuid
,接受表示GUID的原始字符串参数并输出原始GUID:
var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);
其中guid
具有类型guid
。运行此cmdlet时,我会将输出格式化为表:
PS D:\SANRAL\NRA2> Convert-RawToGuid DD8386EE09231A43B7731880CCAD6B87
Guid
----
ee8683dd-2309-431a-b773-1880ccad6b87
PS D:\SANRAL\NRA2>
在这两种情况下,我都输出一个对象,而不是一个列表,并且在这两种情况下,对象都很容易用一个简单的字符串表示。为什么在返回Guid
类型时会得到表格输出
值得注意的是,Convert-GuidToRaw
cmdlet及其简单、未格式化的字符串输出似乎无法正确写入管道。两个cmdlet都从管道中获取一个参数。我希望下面的此cmdlet管道输出GUID,而管道中的最后一个cmdlet正在查找输入:
PS C:\WINDOWS\system32> New-Guid | Convert-GuidToRaw | Convert-RawToGuid
cmdlet Convert-RawToGuid at command pipeline position 3
Supply values for the following parameters:
Input:
为什么Convert RawToGuid
没有从Convert GuidToRaw
获取“流水线”字符串?按如下方式交换管道顺序,会导致预期行为:
PS C:\WINDOWS\system32> Convert-RawToGuid F3BD9411DE8E4F4BBCACECFCED6D305D | Convert-GuidToRaw
F3BD9411DE8E4F4BBCACECFCED6D305D
PS C:\WINDOWS\system32>
Convert-RawToGuid
cmdlet如下所示:
[Cmdlet(VerbsData.Convert, "RawToGuid")]
public class ConvertRawToGuidCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public string Input { get; set; }
protected override void ProcessRecord()
{
if (string.IsNullOrEmpty(Input) || Input.Length != 32)
{
throw new ArgumentException("Input must be a 32 character hex string");
}
var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);
}
}
[Cmdlet(VerbsData.Convert, "GuidToRaw")]
public class ConvertGuidToRawCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public Guid Input { get; set; }
protected override void ProcessRecord()
{
var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);
}
}
<View>
<Name>System.Guid</Name>
<ViewSelectedBy>
<TypeName>System.Guid</TypeName>
</ViewSelectedBy>
<TableControl>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Guid</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
Convert-GuidToRaw
cmdlet如下所示:
[Cmdlet(VerbsData.Convert, "RawToGuid")]
public class ConvertRawToGuidCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public string Input { get; set; }
protected override void ProcessRecord()
{
if (string.IsNullOrEmpty(Input) || Input.Length != 32)
{
throw new ArgumentException("Input must be a 32 character hex string");
}
var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);
}
}
[Cmdlet(VerbsData.Convert, "GuidToRaw")]
public class ConvertGuidToRawCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public Guid Input { get; set; }
protected override void ProcessRecord()
{
var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);
}
}
<View>
<Name>System.Guid</Name>
<ViewSelectedBy>
<TypeName>System.Guid</TypeName>
</ViewSelectedBy>
<TableControl>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Guid</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
第1部分 在这两种情况下,我都输出一个对象,而不是一个列表,并且在这两种情况下,对象都很容易用一个简单的字符串表示。为什么在返回Guid类型时会得到表格输出 当交互会话中的命令返回未分配的值时,PowerShell会将其传递给默认值以在写入控制台之前生成文本。PowerShell预先配置了一些特定类型的格式化命令,并且是这些类型中的一种 例如:
PS>[Guid]::NewGuid()
指南
----
ee737b6f-7f68-4015-8841-1278b37a6420
各种类型的默认格式化程序在PowerShell 5.1中的*.Format.ps1xml文件中进行配置,并按照从PowerShell 6开始烘焙到源代码中
在PowerShell 5.1中,System.Guid的默认格式化程序配置可以在$PSHOME\dotnetypes.format.ps1xml
中找到,如下所示:
[Cmdlet(VerbsData.Convert, "RawToGuid")]
public class ConvertRawToGuidCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public string Input { get; set; }
protected override void ProcessRecord()
{
if (string.IsNullOrEmpty(Input) || Input.Length != 32)
{
throw new ArgumentException("Input must be a 32 character hex string");
}
var guid = GuidConverter.Core.GuidConverter.FromRaw(Input);
WriteObject(guid);
}
}
[Cmdlet(VerbsData.Convert, "GuidToRaw")]
public class ConvertGuidToRawCommand : System.Management.Automation.Cmdlet
{
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true)]
public Guid Input { get; set; }
protected override void ProcessRecord()
{
var raw = GuidConverter.Core.GuidConverter.ToRaw(Input);
WriteObject(raw);
}
}
<View>
<Name>System.Guid</Name>
<ViewSelectedBy>
<TypeName>System.Guid</TypeName>
</ViewSelectedBy>
<TableControl>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Guid</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
如果要将默认格式化命令的结果捕获到字符串变量中(例如写入日志文件),可以执行以下操作:
PS>$text=[Guid]::NewGuid()|输出字符串
PS>$text
指南
----
ee737b6f-7f68-4015-8841-1278b37a6420
第二部分
为什么Convert-RawToGuid不能从Convert-GuidToRaw获取“管道化”字符串?按如下方式交换管道顺序,会导致预期行为:
PS C:\WINDOWS\system32> Convert-RawToGuid F3BD9411DE8E4F4BBCACECFCED6D305D | Convert-GuidToRaw
F3BD9411DE8E4F4BBCACECFCED6D305D
PS C:\WINDOWS\system32>
我无法重现您的问题,但以下内容对我很有用(需要注意的是,我找不到具有类GuidConverter.Core.GuidConverter
的库,所以我假设它是一个私有实现,我使用默认字符串fomat代替它-例如:“024673b5-9c65-447a-be87-dae5f11f5142”)。您可以在本地尝试,看看是否得到相同的结果或您报告的问题,然后从那里开始
- 在Visual Studio中使用.Net Framework 4.7.2创建新的C#类库解决方案
- 添加对Microsoft.PowerShell.5.1.ReferenceAssembles NuGet包的引用
- 将以下代码添加到新类文件中并生成项目:
使用系统;
使用系统、管理、自动化;
命名空间MyCmdlet
{
[Cmdlet(VerbsData.Convert,“RawToGuid”)]
公共类ConvertRawToGuidCommand:Cmdlet
{
[参数(必需=真,位置=1,ValueFromPipeline=真)]
公共字符串输入{get;set;}
受保护的覆盖无效ProcessRecord()
{
if(string.IsNullOrEmpty(this.Input)| | this.Input.Length!=36)
{
抛出新ArgumentException(“输入必须是36个字符的十六进制字符串”);
}
var guid=新的guid(this.Input);
WriteObject(guid);
}
}
[Cmdlet(VerbsData.Convert,“GuidToRaw”)]
公共类ConvertGuidToRawCommand:Cmdlet
{
[参数(必需=真,位置=1,ValueFromPipeline=真)]
公共Guid输入{get;set;}
受保护的覆盖无效ProcessRecord()
{
var raw=this.Input.ToString();
WriteObject(原始);
}
}
}
如果我构建此代码,我可以从PowerShell引用它,并且以下代码可以正常工作:
PS> Import-Module ".\MyCmdlet.dll"
PS> New-Guid | Convert-GuidToRaw | Convert-RawToGuid
Guid
----
15591624-44c9-4c55-acd7-22b7a2d0bee0
感谢您提供有关格式设置的所有信息。我在问题中添加了我的
Convert RawToGuid
实现。这是C#而不是PowerShell脚本。有趣的是,您使用.NET调用来获取新的GUID,其中我有一个new GUID
cmdlet,它似乎是内置的。@ProfK-re[GUID]::NewGuid-我来自C#背景-默认情况下我倾向于下拉到.NET类:-)。我也来自一个较长的C#背景,但是我总是忘记在PS中使用.Net类有多么容易。谢谢你的提醒。你也可以发布转换GuidToRaw的代码吗?我应该想在转换RawToGuid的同时要求这样做-S@mclayton我已经这样做了。我尝试用一个新的Visual Studio解决方案(C#类库,.Net Framework 4.7.2)重新解决这个问题,添加NuGet包Microsoft.PowerShell.5.1.ReferenceAssembly
,然后将代码粘贴到两个新的类文件中(序列化格式除外-使用Input.ToString()
和新Guid(this.Input)
转换值)。然后,在PowerShell导入模块中“\MyCmdlet.dll”;新Guid |转换GuidToRaw |转换RawToGuid
和