我有一个针对 Windows PowerShell 5.1 运行的现有 PowerShell 模块。它在很大程度上取决于Invoke-WebRequest和Invoke-RestMethodcmdlet,它们在 5.1 和 PowerShell Core 6 之间有一些相当重大的变化。
我已经设法使大部分代码在版本(桌面/核心)之间工作,但我遇到的最后一件事是处理 HTTP 失败响应引发的异常。现有的代码看起来或多或少像这样。
try {
$response = Invoke-WebRequest @myparams -EA Stop
# do more stuff with the response
} catch [System.Net.WebException] {
# parse the JSON response body for error details
}
Run Code Online (Sandbox Code Playgroud)
除了服务器 HTTP 响应代码失败生成的异常之外,我不一定想捕获任何异常。核心版返回的异常类型与桌面版不同,需要单独的代码路径来解析响应。所以最初我尝试了这个:
try {
$response = Invoke-WebRequest @myparams -EA Stop
# do more stuff with the response
} catch [System.Net.WebException] {
# Desktop: parse the JSON response body …Run Code Online (Sandbox Code Playgroud) 我有一个PowerShell模块,它同时针对Windows PowerShell 5.1和PowerShell Core 6.0.在Windows PowerShell(桌面版)方面,它具有对.NET Framework 4.7.1的额外依赖性,以便正常工作.
当我最初创作模块时,我认为使用模块清单中的DotNetFrameworkVersion条目就足以认为PowerShell会强制执行最小化.
DotNetFrameworkVersion键
指定模块所需的最低.NET Framework版本.
我已经知道没有强制执行,我甚至不确定该字段的用途.在任何情况下,我都在尝试减少当人们尝试使用没有安装最低.NET Framework版本的模块时提交的支持问题.
在最近的版本中,我在模块的PSM1文件中添加了一些代码,这些代码将在加载模块时检查.NET Framework版本,如果找不到最小版本则抛出错误.
这似乎很有效,但只有手动导入模块时才有效Import-Module.如果您只是尝试运行其中一个模块函数并让PowerShell自动加载进行导入,则会导致导入错误被抑制,而您会得到一个相对一般的错误,例如:
Get-Blah:'Get-Blah'命令在模块'MyModule'中找到,但无法加载模块.有关更多信息,请运行"Import-Module MyModule".
我想相信用户会阅读消息,通过手动导入模块来执行它所说的内容,然后阅读/理解真正的错误消息.但我已经让用户提交了相反的问题.
所以现在我想知道.有没有更好的方法来解决这个问题?我是否将我的版本检查代码移出PSM1并进入每个公共功能?有什么比我更缺的东西吗?
我意识到"输出变量"可能是错误的术语,这就是为什么我的谷歌搜索失败了.我猜它是围绕明确设置变量范围,但我已经尝试阅读about_Scopes文档,它只是没有点击我.
基本上我要做的是在我自己的模块函数中实现与Invoke-RestMethod相同的-SessionVariable参数.换句话说,我需要一个字符串参数,该参数在调用者的范围内变成一个变量.
function MyTest
{
param([string]$outvar)
# caller scoped variable magic goes here
set-variable -Name $outvar -value "hello world"
# normal function output to pipeline here
Write-Output "my return value"
}
# calling the function initially outputs "my return value"
MyTest -outvar myvar
# referencing the variable outputs "hello world"
$myvar
Run Code Online (Sandbox Code Playgroud)
对于奖励积分,如果我正在包装具有自己的输出变量的现有函数并且我想有效地通过输出变量名称,那么事情如何改变(如果有的话)?
function MyWrapper
{
param([string]$SessionVariable)
Invoke-RestMethod -Uri "http://myhost" -SessionVariable $SessionVariable
# caller scoped variable magic goes here
set-variable -Name $SessionVariable -value $SessionVariable
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个脚本来对 json 对象数组进行一些处理。源 json 的简化版本如下所示。请注意第二个对象中转义的双引号。
[
{
"id": "1a-2b",
"name": "my job name",
"description": "my job description"
},
{
"id": "3c-4d",
"name": "my \"quoted\" job name",
"description": "my \"quoted\" job description"
}
]
Run Code Online (Sandbox Code Playgroud)
我的脚本当前尝试使用我在搜索中其他地方找到的“读取时”惯用法来迭代源代码,如下所示。
while read job; do
# fetch individual values into variables
jobname=`echo $job | jq -r '.name'`
# do processing on the individual values
echo $jobname
done < <(cat jobs | jq -c '.[]')
Run Code Online (Sandbox Code Playgroud)
问题似乎是转义的引号在紧凑输出以及随后的 $job 变量中未转义。因此,当我在循环内使用 jq 重新处理单个对象时,每个具有引用值的对象都会出现 jq 解析错误。
我目前正在使用 jq 1.4,并且一直在尝试 tojson/fromjson/@sh/tostring 的各种组合,但尚未找到正确的组合。我不反对迁移到 jq …
我发现自己最近处理了大量 DNS 数据,并且我一直在使用自定义排序表达式按名称的每个虚线部分对 FQDN 进行反向排序,以便同一区域/子区域中的记录彼此相邻排序。例如:
# Build some fake data that normally comes from API call results
# There are generally more columns in the results and they're not always the same
$fqdns = @'
"fqdn","otherdata"
"a.example.com","foo"
"a.example.org","foo"
"example.com","foo"
"example.org","foo"
"www.example.com","foo"
"www.example.org","foo"
"www.sub.example.com","foo"
"www.sub.example.org","foo"
'@ | ConvertFrom-Csv
$fqdns | sort @{E={$a=$_.fqdn.Split('.'); [array]::Reverse($a); $a -join '.'}}
Run Code Online (Sandbox Code Playgroud)
sort 表达式效果很好,但是在 shell 中以交互方式工作时需要输入很多内容。我想弄清楚如何将它作为变量或函数添加到我的配置文件中,以便我可以通过更少的输入重新使用它。关键是我正在执行初始 Split 的 string 属性不会总是被调用fqdn。所以我需要一些我仍然可以指定该值的东西。我设想能够输入这样的东西:
$fqdns | sort (fqdnsort fqdn)
Run Code Online (Sandbox Code Playgroud)
PS 我不一定要在表达式本身中寻找效率改进,但如果您有想法,也欢迎这些想法。
我有一个生成3行输出的命令,如
$ ./mycommand
1
asdf
qwer zxcv
Run Code Online (Sandbox Code Playgroud)
我想将这3行分配给3个不同的变量($ a,$ b,$ c)
$ echo $a
1
$ echo $b
asdf
$ echo $c
qwer zxcv
Run Code Online (Sandbox Code Playgroud)
我熟悉while循环方法,它通常用于从包含3行组的输出一次读取3行.但考虑到我的命令只输出3行,这似乎不太优雅.
我尝试使用各种值的组合IFS=和选项read -r a b c,将命令输出作为stdin发送,但我只能得到它将第一行设置为第一个变量.一些例子:
IFS= read -r a b c < <(./mycommand)
IFS=$'\n' read -r a b c < <(./mycommand)
IFS= read -r -d $'\n' < <(./mycommand)
Run Code Online (Sandbox Code Playgroud)
如果我修改我的命令以便3行用空格而不是换行符分隔,只要每个前一行被正确引用,我就可以成功地使用这个变量:
read -r a b c < <(./mycommand)
Run Code Online (Sandbox Code Playgroud)
虽然这对我目前的项目来说是有效的,但是我仍然不知道我无法以其他方式工作.所以我想知道是否有人能够通过3行输出看到并解释我在原始尝试中缺少的内容.