我有一个接受PSCredential对象的Powershell函数。如果PSCredential为null,我希望自己在函数中特别处理这个问题。但是,最终发生的情况是我得到了一个PSCredential提示符(与运行Get-Credential
时相同)。
在下面的脚本中,我为Credential
参数集设置了所需的参数,并希望用[AllowNull()]
使其为空,但这并没有阻止提示符出现。
这是我的功能:
<#
.description
Create a new Connection String Builder object
.parameter existingCSB
Use the passed CSB as the base, but allow it to be overridden.
.parameter property
Hashtable containing named properties for a connection string builder.
Will override values on -existingCSB.
.parameter credential
Use these credentials. Will override values on -existingCSB and any values
passed as -property.
NOTE: If this parameter is null, or if EITHER the username OR password in
the credential is an empty string, use a trusted connection aka
integrated security instead
.parameter username
Use this username. Will override values on -existingCSB and any values
passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a
trusted connection / integrated security instead
.parameter password
Use this password. Can be a string or a SecureString object. Will override
values on -existingCSB and any values passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a
trusted connection / integrated security instead
#>
function New-DbConnectionStringBuilder {
[cmdletbinding(DefaultParameterSetName="NoCredential")] param(
[System.Data.Common.DbConnectionStringBuilder] $existingCSB,
[Hashtable] $property,
[Parameter(Mandatory=$true, ParameterSetName="Credential")]
[AllowNull()] [System.Management.Automation.PSCredential] $credential,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
[AllowEmptyString()] [string] $username,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
[AllowNull()] $password
)
$newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
if ($existingCSB.Keys.Count -gt 0) {
$existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
}
if ($property.Keys.Count -gt 0) {
$property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
}
if ($PsCmdlet.ParameterSetName -notmatch "NoCredential") {
if ($credential) {
$username = $credential.UserName
$password = $credential.Password
}
if ($password -and $password.GetType().FullName -eq "System.Security.SecureString") {
$password = Decrypt-SecureString $password
}
if ($username -and $password) {
$newDbCSB["Uid"] = $username
$newDbCSB["Pwd"] = $password
$newDbCSB.Remove("Trusted_Connection") | Out-Null
}
else {
$newDbCSB["Uid"] = $null
$newDbCSB["Pwd"] = $null
$newDbCSB["Trusted_Connection"] = "yes"
}
}
return $newDbCSB
}
下面是一些调用它的代码:
$csb = New-DbConnectionStringBuilder -credential $null
Write-Host "UID: $($csb['Uid'])"
Write-Host "Trusted_Connection: $($csb['Trusted_Connection'])"
如果您感兴趣,我这么做的原因是为了与现有代码兼容。我们有一些脚本可以从签入Git的加密文件中获取凭据。如果没有凭据,则现有代码将返回$null作为应该使用集成安全性的指示。
概括起来,我想要的行为是:如果根本没有传递凭据,就不要向CSB添加凭据信息;如果凭据是传递的,而是$null,则使用集成安全性(也称为“可信连接”);如果凭据被传递,而不是null,则在CSB中使用它们。
发布于 2016-05-04 18:06:27
没有什么叫空值PSCredential
-parameter。它将迫使您输入某种类型的凭据。最简单的解决方案是检查要传递给-Credential
的输入,如果输入是$null
,则将其替换为[pscredential]::Empty
。例如。
$creds = $null
if($creds -eq $null) { $creds = ([System.Management.Automation.PSCredential]::Empty) }
$csb = New-DbConnectionStringBuilder -credential $creds
此外,还可以使用以下方法简化密码部分:
if ($credential) {
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password
}
修改后的解决方案:
function New-DbConnectionStringBuilder {
[cmdletbinding(DefaultParameterSetName="NoCredential")] param(
[System.Data.Common.DbConnectionStringBuilder] $existingCSB,
[Hashtable] $property,
[Parameter(Mandatory=$true, ParameterSetName="Credential")]
[System.Management.Automation.PSCredential] $credential,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
[string] $username,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
$password
)
$newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
if ($existingCSB.Keys.Count -gt 0) {
$existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
}
if ($property.Keys.Count -gt 0) {
$property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
}
if($PsCmdlet.ParameterSetName -ne "NoCredential") {
if ($PsCmdlet.ParameterSetName -eq "Credential" -and $credential -ne [System.Management.Automation.PSCredential]::Empty) {
$username = $credential.UserName.Split("\")[-1]
$password = $credential.GetNetworkCredential().Password
}
if ($username -and $password) {
$newDbCSB["Uid"] = $username
$newDbCSB["Pwd"] = $password
$newDbCSB.Remove("Trusted_Connection") | Out-Null
}
else {
$newDbCSB["Uid"] = $null
$newDbCSB["Pwd"] = $null
$newDbCSB["Trusted_Connection"] = "yes"
}
}
$newDbCSB
}
演示:
Write-host
Write-host Null creds
Write-host
$creds = $null
if($creds -eq $null) { $creds = ([System.Management.Automation.PSCredential]::Empty) }
$csb = New-DbConnectionStringBuilder -credential $creds
Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"
Write-host
Write-host Creds
Write-host
$creds = New-Object System.Management.Automation.PSCredential "frode", (ConvertTo-SecureString -String "lol" -AsPlainText -Force)
if($creds -eq $null) { $creds = ([System.Management.Automation.PSCredential]::Empty) }
$csb = New-DbConnectionStringBuilder -credential $creds
Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"
Write-host
Write-host Username and password
Write-host
$csb = New-DbConnectionStringBuilder -username frode -password pass
Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"
Write-host
Write-host Nothing
Write-host
$csb = New-DbConnectionStringBuilder
Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"
输出:
Null creds
UID:
pass:
Trusted_Connection: yes
Creds
UID: frode
pass: lol
Trusted_Connection:
Username and password
UID: frode
pass: pass
Trusted_Connection:
Nothing
UID:
pass:
Trusted_Connection:
编辑:实际上,您可以使用[object]
参数来接受空值凭据,并验证它是否是脚本中的PSCredential
-object,但是在编写New-DbConnectionStringBuilder -Credential "frode"
时将失去提示输入密码的好处。
我更喜欢上面的解决方案,并验证调用方脚本中的输入(修复空值)。这样,函数仍然是“最佳实践”,用户(您)将负责清理/验证输入,就像您应该做的那样。
function New-DbConnectionStringBuilder {
[cmdletbinding(DefaultParameterSetName="NoCredential")] param(
[System.Data.Common.DbConnectionStringBuilder] $existingCSB,
[Hashtable] $property,
[Parameter(ParameterSetName="Credential")]
[object] $credential,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
[string] $username,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
$password
)
#Validate credential-type
if($credential -ne $null -and $credential -isnot [System.Management.Automation.PSCredential]) { Write-Error -Message "credential parameter is not null or PSCredential" -Category InvalidArgument -ErrorAction Stop }
$newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
if ($existingCSB.Keys.Count -gt 0) {
$existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
}
if ($property.Keys.Count -gt 0) {
$property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
}
Write-Host ($credential -eq [System.Management.Automation.PSCredential]::Empty)
if($PsCmdlet.ParameterSetName -ne "NoCredential") {
if ($credential -ne $null -and $credential -ne [System.Management.Automation.PSCredential]::Empty) {
$username = $credential.UserName.Split("\")[-1]
$password = $credential.GetNetworkCredential().Password
}
if ($username -and $password) {
$newDbCSB["Uid"] = $username
$newDbCSB["Pwd"] = $password
$newDbCSB.Remove("Trusted_Connection") | Out-Null
}
else {
$newDbCSB["Uid"] = $null
$newDbCSB["Pwd"] = $null
$newDbCSB["Trusted_Connection"] = "yes"
}
}
$newDbCSB
}
$creds = $null
$csb = New-DbConnectionStringBuilder -credential $creds
Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"
发布于 2016-05-04 21:50:16
通过简单地从参数中省略类型注释,我就能够接近我想要的东西了。当我这样做时,Powershell不会启动PSCredential弹出,我只需处理函数中的所有内容。
也许不是最优雅的解决方案,但它确实有效。
这是我的密码:
<#
.description
Create a new Connection String Builder object
.parameter existingCSB
Use the passed CSB as the base, but allow it to be overridden.
.parameter property
Hashtable containing named properties for a connection string builder. Will override values on -existingCSB.
.parameter credential
Use these credentials. Will override values on -existingCSB and any values passed as -property.
NOTE: If this parameter is null, or if EITHER the username OR password in the credential is an empty string, use a trusted connection / integrated security instead
.parameter username
Use this username. Will override values on -existingCSB and any values passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a trusted connection / integrated security instead
.parameter password
Use this password. Can be a string or a SecureString object. Will override values on -existingCSB and any values passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a trusted connection / integrated security instead
#>
function New-DbConnectionStringBuilder {
[cmdletbinding(DefaultParameterSetName="NoCredential")] param(
[System.Data.Common.DbConnectionStringBuilder] $existingCSB,
[Hashtable] $property,
# Do not give a type, so that this may be $null or a PSCredential object
# NOTE that there is no such thing as a null PSCredential object - the closest thing is [PSCredential]::Empty
[Parameter(Mandatory=$true, ParameterSetName="Credential")]
# [System.Management.Automation.PSCredential]
[AllowNull()] $credential,
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
[AllowEmptyString()] [string] $username,
# Do not give a type, so that this might be a string or a SecureString
[Parameter(Mandatory=$true, ParameterSetName="UserPass")]
[AllowNull()] $password
)
$newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
if ($existingCSB.Keys.Count -gt 0) {
$existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
}
if ($property.Keys.Count -gt 0) {
$property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
}
if ($PsCmdlet.ParameterSetName -eq "Credential") {
if ($credential) {
# Note that we assume this is a PSCredential object, but it could be anything with a string UserName property and a string or SecureString Password property
$tmpUser = $credential.UserName
$tmpPass = $credential.Password
}
else {
$tmpUser = $tmpPass = $null
}
}
elseif ($PsCmdlet.ParameterSetName -eq "UserPass") {
$tmpUser = $username
$tmpPass = $password
}
if ($PsCmdlet.ParameterSetName -notmatch "NoCredential") {
if ($tmpPass -and $tmpPass.GetType().FullName -eq "System.Security.SecureString") {
$tmpPass = Decrypt-SecureString $tmpPass
}
if ($tmpUser -and $tmpPass) {
$newDbCSB["Uid"] = $tmpUser
$newDbCSB["Pwd"] = $tmpPass
$newDbCSB.Remove("Trusted_Connection") | Out-Null
}
else {
$newDbCSB["Uid"] = $null
$newDbCSB["Pwd"] = $null
$newDbCSB["Trusted_Connection"] = "yes"
}
}
return $newDbCSB
}
https://stackoverflow.com/questions/37034752
复制相似问题