我试图了解.GetNewClosure()如何在PowerShell 2中的脚本cmdlet上下文中工作。
本质上,我有一个返回像这样的对象的函数:
function Get-AnObject {
param(
[CmdletBinding()]
[Parameter(....)]
[String[]]$Id
..
[ValidateSet('Option1','Option2')]
[String[]]$Options
)
...
$T = New-Object PSCustomObject -Property @{ ..... }
$T | Add-Member -MemberType ScriptProperty -Name ExpensiveScriptProperty -Value {
$this | Get-ExpensiveStuff
}.GetNewClosure()
..
}
Run Code Online (Sandbox Code Playgroud)
如果我没有验证集选项,那么关闭似乎可以正常工作。如果包含它,则新的关闭失败并显示以下错误。
“使用” 0“参数调用” GetNewClosure“的异常:”无法添加属性,因为这将导致带有值的变量Options变得无效。“
大概闭包正在尝试捕获对Cmdlet的调用的上下文。由于参数“ Options”根本没有绑定,因此在参数验证中效果不佳。
我想可以通过将验证作为代码放置在Cmdlet的正文中而不是使用[Validate *()]装饰器来避免这种情况,但这似乎很讨厌并且晦涩难懂。有没有办法融合这两个想法?
我把#Requires -Version我的脚本放在顶部,但需要弄清楚我需要什么版本.我希望查询PowerShell的哪个版本引入了我调用的每个cmdlet.但我没有在Get-Help -verbose其中一个cmdlet 的输出中看到它.我没有找到适合它的规范网页列表.
任何人都知道是否有标准的方法来查找哪个版本的PowerShell引入了特定的cmdlet?或者,有没有更好的方法来完成我想要做的事情?
我知道我们可以在Powershell V3.0中使用参数-File,但是如何在Powershell V2中只获取带有Get-childitem cmdlet的文件?
我想使用PowerShell设置嵌套对象属性的值。当您尝试设置第一级属性的值时,这很简单:
$propertyName = "someProperty"
$obj.$propertyName = "someValue" # ? It works
Run Code Online (Sandbox Code Playgroud)
对于嵌套属性,它不起作用:
$propertyName = "someProperty.someNestedProperty"
$obj.$propertyName = "someValue" # ? It doesn't work and raises an error.
Run Code Online (Sandbox Code Playgroud)
如何使用PowerShell通过属性名称设置嵌套对象属性的值?
MCVE
对于那些想重现问题的人,这是一个简单的示例:
$Obj= ConvertFrom-Json '{ "A": "x", "B": {"C": "y"} }'
# Or simply create the object:
# $Obj= @{ A = "x"; B = @{C = "y"} }
$Key = "B.C"
$Value = "Some Value"
$Obj.$Key = $Value
Run Code Online (Sandbox Code Playgroud)
运行命令,您将收到一个错误:
“在此对象上找不到属性'BC'。请验证该属性存在并且可以设置。”
调用cmdlet时,是否可以以某种方式扩展powershell变量的值,以便它充当cmdlet的参数(具有关联值)?
这是我正在尝试的一个例子:
$CREDENTIALED_SECTION = "-Username $USER_NAME -Password $PASSWORD"
.
.
.
Invoke-Sqlcmd -ServerInstance "$SERVER_NAME" -Query "$SQL_STATEMENT" "$CREDENTIALED_SECTION" -Database "$DATABASE"
Run Code Online (Sandbox Code Playgroud)
当Invoke-Sqlcmd运行时出现问题.它告诉我,找不到接受"-Username my username-Password my password" 的位置参数所以它正在扩展变量但没有正确地将它作为一组参数发送.有没有办法做我在这里尝试的事情?
我正在编写与Google Apps API接口并需要Oauth2身份验证的Cmdlet.如果用户尝试在未经过身份验证的情况下运行Cmdlet,并且不仅仅是刷新令牌,我还需要他们输入从浏览器提供的访问代码.(这一切都得到了解决.)我想在必要时暂停cmdlet,等待他们的输入,然后只有经过验证才能继续.
但是,我现在只能通过抛出一个错误来退出当前的Cmdlet,然后指示用户将访问代码作为参数传递给另一个Cmdlet(clunky).
我一直在寻找一种方法来调用类似C#的Console.Readline(这只是在执行cmdlet时跳过)或尝试调用Read-Host cmdlet ; 一旦我从用户那里获得访问代码,代码就可以继续正常执行.我知道它不一定是'Powershell Way',但是为了这些工具,我觉得它是用户的最佳选择.
如果我尝试这种方法:
ReadHostCommand read = new ReadHostCommand();
read.prompt = "Access Code";
foreach (string s in read.Invoke<string>()) {
WriteObject(s);
}
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:无法直接调用从PSCmdlet派生的Cmdlet.
搜索该错误导致我尝试创建一个新的 Host对象,如下所示我得到另一个错误(也是如下):
PowerShell ps = PowerShell.Create();
ps.AddCommand("Read-Host");
foreach (PSObject result in ps.Invoke()) {
WriteObject(result);
}
Run Code Online (Sandbox Code Playgroud)
Read-Host:由于主机程序或命令类型不支持用户交互而提示用户失败的命令.尝试支持用户交互的主机程序(如Windows PowerShell控制台或Windows PowerShell ISE),并从不支持用户交互的命令类型(如Windows PowerShell工作流)中删除与提示相关的命令.
有没有办法暂停cmdlet从用户获取字符串?
编辑:为了澄清,我正在编写Cmdlet以在Powershell控制台或ISE或类似程序中运行,并且需要从用户mid-cmdlet执行中获取输入.
我正在运行Windows 7 Home Premium.我安装了.Net4.5.1和Powershell 4.0它安装成功.我可以验证,因为此命令返回:
PS C:\Users\Aubrey\Documents> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
4 0 -1 -1
Run Code Online (Sandbox Code Playgroud)
但是我无法运行命令或脚本:
PS C:\Users\Aubrey\Documents> Get-NetAdapter
Get-NetAdapter : The term 'Get-NetAdapter' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if
a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-NetAdapter
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-NetAdapter:String) [], CommandNotFoundException
+ …Run Code Online (Sandbox Code Playgroud) 我编写了一个调用New-Service cmdlet来创建Windows服务的脚本:
New-Service -Name $Name -BinaryPathName $ExecutablePath `
-Credential $Credential -DisplayName $DisplayName `
-Description $Description -StartupType $StartupType
Run Code Online (Sandbox Code Playgroud)
我的描述有问题.如果$ Description是一个空字符串或$ null我得到一个错误:
Cannot validate argument on parameter 'Description'.
The argument is null or empty. Provide an argument that is not null or empty,
and then try the command again.
Run Code Online (Sandbox Code Playgroud)
如果我完全省略-Description参数,那么命令运行时没有错误:
New-Service -Name $Name -BinaryPathName $ExecutablePath `
-Credential $Credential -DisplayName $DisplayName `
-StartupType $StartupType
Run Code Online (Sandbox Code Playgroud)
我可以通过以下方法解决此问题:
if ($Description)
{
New-Service -Name $Name -BinaryPathName $ExecutablePath `
-Credential $Credential -DisplayName $DisplayName `
-Description $Description -StartupType $StartupType …Run Code Online (Sandbox Code Playgroud) 我正在 Windows 7 下使用 Powershell 4,我的 cmdlet 定义如下:
Function Transfer-File {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[System.Management.Automation.PSCustomObject]
$source,
# other parameters removed for brevity
)
# actual logic does not matter
}
Run Code Online (Sandbox Code Playgroud)
我这样称呼它:
$hasError = Transfer-File -source $source -destination $cfg.Destination -logfile $logFile
Run Code Online (Sandbox Code Playgroud)
$source 是通过解析 JSON 文件获得的,如下所示:
@{Path=some path string here; Pack=False}
Run Code Online (Sandbox Code Playgroud)
Write-Host $source.GetType() 输出:
System.Management.Automation.PSCustomObject
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
无法将“System.Management.Automation.PSCustomObject”类型的“@{Path=some path string here; Pack=False}”值转换为“System.Management.Automation.PSCustomObject”类型。
在绝望地尝试凭经验解决它时,我替换System.Management.Automation.PSCustomObject了psobject它,它似乎工作正常。
问题:为什么我的System.Management.Automation.PSCustomObject似乎不适合System.Management.Automation.PSCustomObjectcmdlet 原型?
创建对象的完整代码:
### Configuration ###
$cfg = New-Object –TypeName PSObject …Run Code Online (Sandbox Code Playgroud) 我用C#编写了一个简单的 PowerShell cmdlet来展示我遇到的问题。随意克隆 repo,或 fork 并使其工作并提交 PR,或者只是查看源代码以确切了解我在做什么。
我已经使用PowerShellStandard.Library NuGet 包创建了一个简单的 PowerShell Core cmdlet 。我正在使用 xUnit 并尝试针对我创建的 PowerShell cmdlet 运行单元测试。问题是当我调用.Invoke()cmdlet 实例的方法时,它抛出一个NullReferenceException.
这是我创建的 cmdlet:
[Cmdlet(VerbsCommon.Get, "RepeatedString")]
[OutputType(typeof(string))]
public class GetRepeatedStringCmdlet : Cmdlet
{
[Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[Alias("Word")]
[ValidateNotNullOrEmpty()]
public string Phrase { get; set; }
[Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true)]
[Alias("Repeat")]
public int NumberOfTimesToRepeatPhrase { get; set; }
protected …Run Code Online (Sandbox Code Playgroud) cmdlet ×10
powershell ×10
c# ×2
arguments ×1
closures ×1
cmdlets ×1
input ×1
parameters ×1
unit-testing ×1
validation ×1
windows ×1