Can i use existing variables in powershell read-host

前端 未结 2 1523
梦谈多话
梦谈多话 2021-01-07 12:18

i am writing a simple script in powershell using "read-host -prompt" so that i can input some text that will then be used to create some environment variables.

相关标签:
2条回答
  • 2021-01-07 12:46

    You cannot do this straight :

    ####[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
    

    My bad, I answered without a good reading :) As @postanote said, If you need to keep a track of the value from each run, you can store it in a file (IMHO, I would avoid the profile.ps1) or in a personal registry key. Then read the file or the registry value to initialize your variable.

    0 讨论(0)
  • 2021-01-07 12:53

    If I understand correctly, you're looking for two features that are not implemented in Read-Host as of PowerShell 7.1:

    • (a) Pre-filling the edit buffer with a default value, which the user can either accept as-is or modify.

      • The alternative is just to inform the user, via the -Prompt string, what value will be used if they don't enter a new one, but that way you won't be able to distinguish between the user choosing the default value or simply wanting to abort the prompt (which they could do with Ctrl-C, however).
    • (b) Keeping a persistent history of user-entered values that remembers (at least) the most recently entered value, across PowerShell sessions.

    Note: Read-Host is currently bare-bones. The module that provides the rich interactive command-line editing experience for PowerShell itself is PSReadLine, and would be great if its features, which include a persistent history and modifying the edit buffer, could be made available to user code for general-purpose prompting - see GitHub proposal #881.
    Surfacing such enhancements via Read-Host is probably the best option, or at least the ability to prefill the edit buffer could be implemented there: see GitHub proposal #14013.

    See - limited - custom implementations of (a) and (b) below.


    (a) is currently only possibly via a workaround, and only on Windows, both in regular console windows and Windows Terminal (it does not work (reliably enough) in the obsolescent PowerShell ISE Thanks, CFou., and in Visual Studio Code's integrated terminal it only works if you place the focus on it by clicking immediately after launching a debug session):

    # 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
    

    Note: The -replace operation is necessary to escape characters in the default value that would otherwise have special meaning to .SendKeys().

    (b) requires you to implement your own persistence mechanism, and the obvious choice is to use a file:

    Here's a simplistic approach that only stores the most recent value entered.

    • Supporting multiple historic values per prompt would also support for recall in Read-Host, such as as using up-arrow and down-arrow to cycle through the history, which is not supported as of 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
    
    0 讨论(0)
提交回复
热议问题