Rob Berry
Rob Berry

Reputation: 315

How to change cursor position in powershell console

I currently assign the current CursorPosition to a variable in Powershell so that I can overwrite the same space when performing a count down for example in a script, as below:

$errorPos = $host.UI.RawUI.CursorPosition
for ($i=5; $i -ge 0; $i--) {
    $host.UI.RawUI.CursorPosition = $errorPos
    Write-Host -NoNewline -BackgroundColor Yellow -ForegroundColor Black "$i"
    Start-Sleep -Seconds 1
}

What I'd like to do, it take the current position of the cursor and move it forward two spaces, then assign it to another variable. I could just use:

write-host "  "

but I don't want to overwrite the text currently occupying that space.

I think it can be accomplished using X and Y coordinate but am not having much success.

Upvotes: 5

Views: 17882

Answers (2)

Maybe
Maybe

Reputation: 965

The accepted answer isn't working for me on PowerShell 5.1 or 7.4, I'm not sure if something changed with conhost.exe or if it really just never worked.

While editing the properties of $Host.UI.RawUI.CursorPosition doesn't work, assigning it a hashtable with x & y keys does work:

for ($i=5; $i -ge 0; $i--) {
  Write-Host -NoNewline -BackgroundColor Yellow -ForegroundColor Black "$i"
  $x, $y = $Host.UI.RawUI.CursorPosition -split ','
  # Splitting the positions into $x & $y prevents this line from being very long:
  $Host.UI.RawUI.CursorPosition = @{  x = $x - 1  ;  y = $y  }
  Start-Sleep 1
}

HOWEVER, $Host.UI.RawUI.CursorPosition often doesn't function properly outside of the parent scope. You can use [Console]::SetCursorPosition instead; just make sure that the arguments you provide it are integers:

# This should cause the cursor to move diagonally to the lower right:
&{
  for ($i=0; $i -lt 3; $i++) {
    Start-Sleep 1
    $x, $y = $Host.UI.RawUI.CursorPosition -split ',' -as 'int[]'
    [Console]::SetCursorPosition(  $x + 1  ,  $y + 1  )
  }
}

I don't really like mixing the use of $Host.UI.RawUI and [Console] together, though; so, here's an alternative version that utilizes [Console]::GetCursorPosition():

# This should cause the cursor to move diagonally to the lower right:
&{
  for ($i=0; $i -lt 3; $i++) {
    Start-Sleep 1
    $x, $y = [Console]::GetCursorPosition() -split '\D' -ne '' -as 'int[]'
    [Console]::SetCursorPosition(  $x + 1  ,  $y + 1  )
  }
}

Upvotes: 2

colsw
colsw

Reputation: 3326

If you just want to move the 'X' forward by 2 you can just do this after creating your errorPos variable:

$errorPos.X += 2

You can modify the variable directly by using $errorPos.X and .Y.

Upvotes: 4

Related Questions