【问题标题】:Can i use existing variables in powershell read-host我可以在 powershell 读取主机中使用现有变量吗
【发布时间】:2020-11-07 17:16:12
【问题描述】:

我正在使用“read-host -prompt”在 powershell 中编写一个简单的脚本,以便我可以输入一些文本,然后用于创建一些环境变量。

有没有办法在脚本的后续运行时,读取主机消息将显示变量的现有值(如果存在)?如果不是我想要的,那么接受我的新输入来更改该变量?

例如...

$myvar = read-host -prompt "whats your value" 然后我输入 10 将 $myvar 值设置为 10

下次运行脚本时,“whats your value”将显示 10,如果我按 Enter 而不更改值,它将再次使用值 10 .. 如果我输入新值,它会将 $myvar 更新为新价值

感谢您的帮助

【问题讨论】:

  • 你试过了吗? [grin] 是的,您可以在 Read-Host 通话中使用 $Var。看看-Prompt参数...
  • 请澄清“脚本运行的后续时间”,scipt 完成后是否关闭/退出?如果是这样,那么$myvar 的值将不会持续存在。您要么必须让脚本自行修改(不建议),要么必须加载一个外部配置文件来拉取先前的值并将新值推送到脚本关闭之前。
  • 嗨 .. 感谢您的回复.. 有没有办法将变量设置为用户变量,以便它在 powershell 会话之间持续存在......可以从 cmd 提示符等中看到?跨度>
  • 没有。你不能用任何语言做到这一点。代码、变量、函数等仅存在于调用它们的作用域、会话中。要执行您所要求的操作,您需要将此信息保存在文件系统(txt、csv、xml、json、ini)或注册表,然后您可以根据需要重新读取。
  • 如果您想要在开始会话时初始定义为某个值的内容,请将定义放入您的 $profile 文件中。如果要在两次访问之间以半永久方式存储值,请使用环境变量。如果您希望将变量初始化为半永久值,请同时使用这两种技术。

标签: powershell


【解决方案1】:

如果我理解正确,您正在寻找在 PowerShell 7.1 中在Read-Host 中实现的两个功能:

  • (a) 默认值预填充编辑缓冲区,用户可以按原样接受或修改。

    • 另一种方法是通过-Prompt 字符串通知用户,如果他们不输入新值,将使用什么值,但这样你将无法区分用户选择了 default 值还是仅仅想要 abort 提示(但是他们可以使用 Ctrl-C 来做到这一点)。
  • (b)保留用户输入值的持久历史,以记住(至少)最近输入的值,跨 PowerShell 会话.

注意:Read-Host 目前是准系统。为 PowerShell 本身提供丰富的交互式命令行编辑体验的模块是 PSReadLine,如果它的功能(包括持久历史记录和修改编辑缓冲区)可以提供给 的用户代码使用,那就太好了通用提示 - 请参阅 GitHub proposal #881
通过Read-Host 显示这些增强功能可能是最好的选择,或者至少可以在那里实现预填充编辑缓冲区的功能:请参阅GitHub proposal #14013

请参阅下面的 (a) 和 (b) 的有限自定义实现。


(a) 目前只能通过 workaround,并且只能在 Windows 上,在 常规控制台窗口Windows终端(它在obsolescentPowerShell ISE 中工作(足够可靠)谢谢CFou.,在 Visual Studio Code 的集成终端中它仅当您在启动调试会话后立即单击将焦点放在它上面时才有效):

# The (default) value to pre-fill the Read-Host buffer with.
$myVar = 'This is a default value.'

# Workaround: Send the edit-buffer contents as *keystrokes*
# !! This is not 100% reliable as characters may get dropped, so we send
# !! multiple no-op keys first (ESC), which usually works.
(New-Object -ComObject WScript.Shell).SendKeys(
  '{ESC}' * 10 + ($myVar -replace '[+%^(){}]', '{$&}')
)

$myVar = Read-Host 'Enter a value'  # Should display prompt with value of $myVar

注意:-replace 操作对于转义默认值中的字符是必要的,否则对.SendKeys() 具有特殊意义。

(b) 要求你实现自己的持久化机制,显而易见的选择是使用文件

这是一个简单的方法,只存储最近输入的值。

  • 每个提示支持多个历史值也将支持Read-Host 中的recall,例如使用向上箭头和向下箭头循环浏览历史,这是不 从 PowerShell 7.1 开始支持。
# Choose a location for the history file.
$historyFile = "$HOME/.rhhistory"

# Read the history file (which uses JSON), if it exists yet.
$history = Get-Content -Raw -ErrorAction Ignore $historyFile | ConvertFrom-Json
$defaultValue = 'This is a default value.'

# Get the 'myVar' entry, if it exists, otherwise create it and use the default value.
$myVar = 
  if (-not $history) { # no file yet; create the object to serialize to JSON later
    $history = [pscustomobject] @{ myVar = '' }
    $defaultValue
  } elseif (-not $history.myVar) { # file exists, but has no 'myVar' entry; add it.
    $history | Add-Member -Force myVar ''
    $defaultValue
  } else {  # return the most recently entered value.
    $history.myVar
  }

# Prompt the user.
(New-Object -ComObject WScript.Shell).SendKeys(
  '{ESC}' * 10 + ($myVar -replace '[+%^(){}]', '{$&}')
)
$myVar = Read-Host 'Enter a value'

# Validate the value...

# Update the history file with the value just entered.
$history.myVar = $myVar
$history | ConvertTo-Json > $historyFile

【讨论】:

  • 这也可以在'直接'Powershell中完成:[System.Windows.Forms.SendKeys]::SendWait("Jim"); $a = read-host -prompt 'Name' 它需要:Add-Type -AssemblyName System.Windows.Forms
  • @jimbirch,是的,但这并不比使用(New-Object -ComObject WScript.Shell).SendKeys() 更“直接”,它的优点是不需要单独的Add-Type 调用。
【解决方案2】:

你不能直接这样做:

####[int]$myVar = 10           Read too fast the question :)
#$myVar = Get-ItemProperty ...
#or
#myVar = Get-Content ...
$tempVar = Read-Host "Enter the value ($myVar is default)"
if ($tempVar)
{
   $myVar = $tempVar
}
$myVar
# Store $myVar in the registry or in the file for next run

我的错,我没有好好阅读就回答了 :) 正如@postanote 所说, 如果您需要跟踪每次运行的值,您可以将其存储在文件中(恕我直言,我会避免使用 profile.ps1)或个人注册表项。 然后读取文件或注册表值来初始化你的变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    相关资源
    最近更新 更多