首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否有办法使Powershell对函数的输出使用特定的格式?

是否有办法使Powershell对函数的输出使用特定的格式?
EN

Stack Overflow用户
提问于 2021-06-15 16:19:56
回答 1查看 281关注 0票数 1

我想为PowerShell函数的输出建议一种特定的格式(也许是强制的,但我对语义还不太确定)。

Format.ps1xml ( PowerShell 7.1版本)说:“从PowerShell 6开始,默认视图在PowerShell源代码中定义。PowerShell 5.1和早期版本的Format.ps1xml文件在PowerShell 6和更高版本中不存在。”本文接着解释了如何使用Format.ps1xml文件来更改对象的显示等等。这一点并不十分明确:‘不存在’-ne‘不能存在’.

这就引出了几个问题:

  1. 尽管Format.ps1xml文件“不存在”,但是否可以在大于5.1的PowerShell版本中创建/使用它们?
  2. 无论它们是否可以,是否有更好的做法向PowerShell建议某个函数应该如何格式化返回的数据?请注意,“建议”中固有的是,--PowerShell输出的管道性质必须保留:用户必须仍然能够将函数的输出输送到格式化列表或ForEach-Object等。

例如,Get-ADUser cmdlet返回由Format-List格式化的对象。如果我编写了一个名为Search-ADUser的函数,该函数在内部调用Get-ADUser并返回其中的一些对象,则输出也将格式化为list。在返回之前将输出传递到Format-Table并不满足我的要求,因为输出将不会在管道中被视为单独的对象。

示例代码:

代码语言:javascript
运行
复制
function Search-ADUser {
  param (
    $Name,
    [ValidateNotNullOrEmpty()][string[]]$Properties = @('Enabled', 'SamAccountName', 'Name', 'emailAddress', 'proxyAddresses')
  )
  return Get-ADUser -Filter ('name -like "*{0}*"' -F $Name) -Properties $Properties | Select-Object $Properties
}

最好的答案应该解决这两个问题,尽管第二个问题更突出。

不可接受的答案包括建议该函数不应强制执行格式,和/或用户应将函数的输出输送到他们选择的格式化程序。这是一种非常主观的立场,它是否为多数人所持有,与问题无关。

我在发帖之前搜索了force function format #powershell-7.0,但搜索结果似乎都与此无关。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-15 17:45:18

尽管Format.ps1xml文件“不存在”,但是否可以在大于5.1的PowerShell版本中创建/使用它们?

  • 是的;事实上,任何第三方代码都必须使用它们来定义自定义格式。
代码语言:javascript
运行
复制
- That `*.ps1xml` _files_ are invariably needed for such definitions is unfortunate; [GitHub issue #7845](https://github.com/PowerShell/PowerShell/issues/7845) asks for an in-memory, API-based alternative (which for _type_ data already exists, via the [`Update-TypeData`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/update-typedata) cmdlet).
代码语言:javascript
运行
复制
- However, in the context of [_modules_](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Modules), the need for files is less inconvenient, as they can be bundled with the module and are automatically loaded when referenced from the [module manifest](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Module_Manifests)'s `FormatsToProcess` entry.
  • 现在只有PowerShell附带的格式化数据才被硬编码到PowerShell (核心)可执行文件中,这大概是出于性能原因。

是否有更好的做法向PowerShell建议某个函数应该如何格式化返回的数据?

由于缺乏基于API的格式数据定义方法,需要采用以下方法:

  • 确定应用格式设置的.NET类型的全名。
代码语言:javascript
运行
复制
- If it is `[pscustomobject]` instances that the formatting should apply to, you need to (a) _choose_ a unique (virtual) type name and (b) assign it to the `[pscustomobject]` instances via PowerShell's [ETS (Extended Type System)](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Types.ps1xml); e.g.:
代码语言:javascript
运行
复制
    - For `[pscustomobject]` instances created by the [`Select-Object`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/select-object) cmdlet:

将虚拟类型名称"MyVirtualType“分配给对象输出#:Select ChildItem *.txt *.txt Select名称,长度为ForEach-Object { $_.pstypenames.Insert(0,'MyVirtualType');$_ }

代码语言:javascript
运行
复制
    - For `[pscustomobject]` _literals_, specify the type name via a `PSTypeName` entry:

pscustomobject @{ PSTypeName = 'MyVirtualType‘foo =1 bar =2}

  • 为该类型创建一个*.ps1mxl文件并将其加载到每个会话中。
代码语言:javascript
运行
复制
- If the commands that rely on this formatting data are defined in a _module_, you can incorporate the file into your module so that it is automatically automatically when the module is imported.
代码语言:javascript
运行
复制
- For help on authoring such files, see:
代码语言:javascript
运行
复制
    - [Formatting File Overview](https://learn.microsoft.com/en-us/powershell/scripting/developer/format/formatting-file-overview)
    - [Format XML Reference](https://learn.microsoft.com/en-us/powershell/scripting/developer/format/format-schema-xml-reference)

GitHub提案#10463要求提供一种大大简化的体验,支持指定所需格式的扩展[OutputType()]属性。

应用于示例函数

  • 以下函数在会话的第一次调用时为其输出类型创建(临时) *.ps1xml文件,以确保为所有5个属性(默认情况下,5个或更多属性导致(隐式) Format-List格式设置)应用(隐式)Format-List格式设置。
代码语言:javascript
运行
复制
- As you can see, creating the XML for the formatting definitions is verbose and cumbersome, even without additional settings, such as column width and alignment.
代码语言:javascript
运行
复制
- A better, but more elaborate solution would be to package your function in a [_module_](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Modules) into whose folder you can place the `*.ps1mxl` file (e.g., `SearchAdUserResult.Format.ps1xml`) and then instruct PowerShell to load the file on module import, via the `FormatsToProcess` key in the [module manifest](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/new-modulemanifest) (`*.psd1`) - e.g., `FormatsToProcess = 'SearchAdUserResult.Format.ps1xml'`
  • 请注意,您也可以为*.ps1mxl输出的Microsoft.ActiveDirectory.Management.ADUser实例直接创建Get-ADUser文件,但这样做会将格式化会话应用于任何发出此类对象的命令。
代码语言:javascript
运行
复制
function Search-ADUser {
  param (
    $Name,
    [ValidateNotNullOrEmpty()][string[]]$Properties = @('Enabled', 'SamAccountName', 'Name', 'emailAddress', 'proxyAddresses')
  )

  # The self-chosen ETS type name.
  $etsTypeName = 'SearchAdUserResult'

  # Create the formatting data on demand.
  if (-not (Get-FormatData -ErrorAction Ignore $etsTypeName)) {

    # Create a temporary file with formatting definitions to pass to 
    # Update-FormatData below.
    $tempFile = Join-Path ([IO.Path]::GetTempPath()) "$etsTypeName.Format.ps1xml"

    # Define a table view with all 5 properties.
    @"
<Configuration>
<ViewDefinitions>
    <View>
      <Name>$etsTypeName</Name>
      <ViewSelectedBy>
        <TypeName>$etsTypeName</TypeName>
      </ViewSelectedBy>
      <TableControl>
        <TableRowEntries>
          <TableRowEntry>
            <TableColumnItems>
              <TableColumnItem>
                <PropertyName>Enabled</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>SamAccountName</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Name</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>emailAddress</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>proxyAddresses</PropertyName>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
      </TableControl>
    </View>
  </ViewDefinitions>
</Configuration>
"@ > $tempFile

    # Load the formatting data into the current session.
    Update-FormatData -AppendPath $tempFile

    # Clean up.
    Remove-Item $tempFile
  }

  # Call Get-ADUser and assign the self-chosen ETS type name to the the output.
  # Note: To test this with a custom-object literal, use the following instead of the Get-ADUser call:
  #      [pscustomobject] @{ Enabled = $true; SamAccountName = 'jdoe'; Name = 'Jane Doe'; emailAddress = 'jdoe@example.org'; proxyAddresses = 'janedoe@example.org' }
  Get-ADUser -Filter ('name -like "*{0}*"' -F $Name) -Properties $Properties | Select-Object $Properties | ForEach-Object {
     $_.pstypenames.Insert(0, $etsTypeName); $_
  }

}

然后,您将看到所需的基于格式数据的表格输出;例如:

代码语言:javascript
运行
复制
Enabled SamAccountName Name     emailAddress     proxyAddresses
------- -------------- ----     ------------     --------------
True    jdoe           Jane Doe jdoe@example.org janedoe@example.org
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67990004

复制
相关文章

相似问题

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