Powershell prompt at bottom - powershell

I'd like to get my prompt in powershell to be at the bottom instead of "from top to bottom".
There is a workaround for cmd (https://superuser.com/questions/644326/start-conemu-with-prompt-at-the-bottom) but I can't find a way to make it work in powershell.
Does anyone have an idea?
Thanks a lot!

Thought, more "clean" version of prompt function. No need of New-Object ... Just add/modify your prompt in the $profile.
function prompt {
# put cursor at the bottom of the buffer
$rawUI = (Get-Host).UI.RawUI
$cp = $rawUI.CursorPosition
$cp.Y = $rawUI.BufferSize.Height - 1
$rawUI.CursorPosition = $cp
# and the prompt itself
Write-Host -NoNewline -ForegroundColor Cyan "PS "
Write-Host -NoNewline -ForegroundColor Yellow $(get-location).ProviderPath
return ">"
}

I'm not sure this is what you want, but this works fairly well for me. Save this as a .ps1 file somewhere that makes sense or convert it into a cmdlet if you like. Then stick it in your profile so it runs when you open a powershell session:
cls
$Ui = (Get-Host).UI.RawUI
$Height = $UI.WindowSize.Height
$Coordinates = New-Object System.Management.Automation.Host.Coordinates 0,($Height - 1)
$Ui.CursorPosition = $Coordinates
Create an alias for it.
New-Alias -Name cl -Value \\Path_to_the_script_or_the_cmdlet
Use the alias to clear your screen rather than clear or cls.

Related

Powershell, pass an answer to a script that requires a choice

I have a PowerShell script that has a y/n question asked in the script. I cannot change the script as it is downloaded from a url, but I would like to run it such that my choice is passed to the script and processing continues unattended.
I found this question, which is on a similar topic, but more related to cmdlets (and I tried everything here, but no luck).
Here is the relevant code (say this is in a script test.ps1)
function Confirm-Choice {
param ( [string]$Message )
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Yes";
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "No";
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no);
$caption = "" # Did not need this before, but now getting odd errors without it.
$answer = $host.ui.PromptForChoice($caption, $message, $choices, 1) # Set to 0 to default to "yes" and 1 to default to "no"
switch ($answer) {
0 {return 'yes'; break} # 0 is position 0, i.e. "yes"
1 {return 'no'; break} # 1 is position 1, i.e. "no"
}
}
$unattended = $false # default condition is to ask user for input
if ($(Confirm-Choice "Prompt all main action steps during setup?`nSelect 'n' to make all actions unattended.") -eq "no") { $unattended = $true }
i.e. Without altering the script, I would like to pass 'n' to this so that it will continue processing. Something like test.ps1 | echo 'n' (though, as before, this specific syntax does not work unfortunately, and I'm looking for a way to do this).
PromptForChoice appears to read input directly from the console host, so it can't be supplied with input from stdin.
You may override the function Confirm-Choice instead, by defining an alias that points to your own function which always outputs 'n'. This works because aliases take precedence over functions.
function MyConfirm-Choice {'no'}
New-Alias -Name 'Confirm-Choice' -Value 'MyConfirm-Choice' -Scope Global
.\test.ps1 # Now uses MyConfirm-Choice instead of its own Confirm-Choice
# Remove the alias again
Remove-Item 'alias:\Confirm-Choice'

powershell parameters command line menu

I wish to create a script which accepts input from the command line and based on the first value, it then determines the next parameters on offer.
Such as to determine if you are to do a single Run or a Batch run for a Password change operation:
./script.ps1 -singleMODE -UserName -Password
./script.ps1 -batchMODE -filename
What i am confused about whilst learning Powershell is what this is? I have looked at Parameters and can read them into variables from command line...but what i want as above has some logic and i am a bit lost. Can someone give me a nudge as to what this is called....and then i can continue my googling! :)
I am thinking somehow i combine Params and Functions so it flicks to different blocks...but i am guessing
any help appreciated! :)
cheers
What you need are Parameter Sets
This is a demo with a function but it works just as well with a script (just put the param block at the top.)
function Demo {
param(
[Parameter(ParameterSetName='Funk')][switch]$Funk,
[Parameter(ParameterSetName='Rock')][switch]$Rock,
[Parameter(ParameterSetName='Funk')][string]$WriteFunk,
[Parameter(ParameterSetName='Rock')][string]$WriteRock
)
if($Funk){
foreach ($C in $WriteFunk.ToCharArray()){
$N = 0..15 | Get-Random
Write-Host $C -ForegroundColor $N -BackgroundColor $(15-$N) -NoNewline
}
Write-Host ''
}
if($Rock){
Write-Host $WriteRock -ForegroundColor Gray -BackgroundColor DarkGray
}
}
Demo -Funk -WriteFunk "Melt your brain"
Demo -Rock -WriteRock "Riders on the storm"

Change currently running script

Is there any way to add text to specific part of script to the currently running script?
If i have a menu with options:
Install All
Add item
Quit
Could the Add item be possible?
Learning to use powershell (heavy user of batches).
When entering Add item, then a read-host would pop up, adding a row between the long row of ### addwifi -wnm $USERINPUT afterwards 'restarting' the script.
Current script:
#cmd: title Add****
$host.ui.RawUI.WindowTitle = "Add Wi-Fi networks"
#When Show-Menu –Title 'SetupWi-Fi' is called
function Show-Menu
{
# NOTE if changing warible from somewhere else (Show-Menu -WARIBLE VALUE) then param part must be included
param (
[string]$Title = 'SetupWi-Fi'
)
Clear-Host
#cls and echo on #echo off
Write-Host "================ $Title ================"
Write-Host "a: Add Wi-Fi networks."
Write-Host "q: Quit."
}
#Do this until x
#For future shortening purposes
function addwifi
{
param (
[string]$wnm
#wnm= wifi name
)
netsh wlan add profile filename="$wnm.xml"
#for some reason (nice for this script) . stops the warible name
}
do
{
# call Show-Menu and optionally change varible: –Title 'Warible' changes the $title varible
Show-Menu
# makin varible chaase equal user input, placing Selection before it
$chaase = Read-Host "Selection:"
#switch according to the varible chaase
switch ($chaase)
{
'a' {
#'single quote' acts as echo, now executing commands of 'a' varible
'Adding Wi-Fi networks.'
$host.ui.RawUI.WindowTitle = "Adding Wi-Fi networks"
#note the upper function is called with warible
#add below here! #####################################################################
addwifi -wnm laptopidee
#add above here! #####################################################################
}
#close a execution
#close switch
}
#close do
}
#until x: selection == input q
until ($chaase -eq 'q')
One possibility is to use placeholders that you replace at runtime, though I'm not sure how well it will hold up for more complex scripts.
For example, if you have the following script:
$scriptPath = "$PsScriptRoot\$($MyInvocation.MyCommand.Name)"
$scriptContent = Get-Content "$PsScriptRoot\$($MyInvocation.MyCommand.Name)" -Raw
$newItem = Read-Host "Please enter new command"
##Placeholder
$scriptContent -replace "$([char]0x0023)$([char]0x0023)Placeholder", "$([char]0x0023)$([char]0x0023)Placeholder$([char]0x000D)$([char]0x000A)$newItem" |
Set-Content -Path $scriptPath
Each time you run it, you will be prompted for a new command, which will be added below the ##Placeholder. So, if you enter Get-Process when prompted, the script would end up on-disk like this:
$scriptPath = "$PsScriptRoot\$($MyInvocation.MyCommand.Name)"
$scriptContent = Get-Content "$PsScriptRoot\$($MyInvocation.MyCommand.Name)" -Raw
$newItem = Read-Host "Please enter new command"
##Placeholder
Get-Process
$scriptContent -replace "$([char]0x0023)$([char]0x0023)Placeholder", "$([char]0x0023)$([char]0x0023)Placeholder$([char]0x000D)$([char]0x000A)$newItem" |
Set-Content -Path $scriptPath
Next time you run the script you will be prompted for a new command, which is added to the list, and all commands already on the list will be executed.
Yes. Use external files as sources to be pulled in. The Add Item menu option creates another file to be read in at next execution.
Many people did this with batch files using .ini files to hold parameters. Similar construct.

how to make powershell shorten the long directory before ">"

for example, if I set an alias in profile.ps1
$ws='C:\Users\Jack\folder0\folder1\folder2'
After I cd to the workspace locationcd $ws
It shows as below
PS C:\Users\Jack\folder0\folder1\folder2\>
Now, I'm wondering if there is a way to let it show as below or similar
PS $ws>
It's my first time ask questions on StackOverflow. if there is anything unsuitable, please give me some advice.
You can modify the prompt-function to do whatever you want. If you only want to check a single variable, you can do this:
$ws = "c:\users\frode"
function prompt {
$CurrentLocation = $executionContext.SessionState.Path.CurrentLocation.Path
if($CurrentLocation -like "$ws*") {
$CurrentLocation = $CurrentLocation -replace [regex]::Escape($ws), '$ws'
}
"PS $($CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";
}
Output:
PS C:\Users> cd .\frode
PS $ws> cd .\Desktop
PS $ws\Desktop>
If you need to support multiple variables, you can store the paths in a hashtable and check that or use Get-Variable to search through variables that contains a valid path. Remember to exclude ex $PWD which is always your current location.

How to pin to start menu using PowerShell

I can pin some programs to taskbar on Win7 using PowerShell.
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace('C:\Windows')
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Tas&kbar'}
if ($verb) {$verb.DoIt()}
How do I modify the above code to pin a program to the Start menu?
Another way
$sa = new-object -c shell.application
$pn = $sa.namespace($env:windir).parsename('notepad.exe')
$pn.invokeverb('startpin')
Or unpin
$pn.invokeverb('startunpin')
Use the code below
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace('C:\Windows')
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Start Men&u'}
if ($verb) {$verb.DoIt()}
Note: the change is in the fourth line.
The main problem with most of the solution is that they enumerate the verbs on a file, search for the string to perform the action (“Pin to Startmenu” etc.) and then execute it. This does not work if you need to support 30+ languages in your company, except you use external function to search for the localized command (see answer from shtako-verflow).
The answer from Steven Penny is the first that is language neutral and does not need any external code. It uses the verbs stored in the registry HKEY_CLASSES_ROOT\CLSID\{90AA3A4E-1CBA-4233-B8BB-535773D48449} and HKEY_CLASSES_ROOT\CLSID\{a2a9545d-a0c2-42b4-9708-a0b2badd77c8}
Based on this, here’s the code we are now using:
function PinToTaskbar {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "taskbarpin"
}
function UnpinFromTaskbar {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "taskbarunpin"
}
function PinToStartmenu {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "startpin"
}
function UnpinFromStartmenu {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "startunpin"
}
function ExecuteVerb {
param(
[Parameter(Mandatory=$true)][string]$File,
[Parameter(Mandatory=$true)][string]$Verb
)
$path = [System.Environment]::ExpandEnvironmentVariables($File)
$basePath = split-path $path -parent #retrieve only the path File=C:\Windows\notepad.exe -> C:\Windows
$targetFile = split-path $path -leaf #retrieve only the file File=C:\Windows\notepad.exe -> notepad.exe
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace($basePath)
if ($folder)
{
$item = $folder.Parsename($targetFile)
if ($item)
{
$item.invokeverb($Verb)
# "This method does not return a value." (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787816%28v=vs.85%29.aspx)
# Therefore we have no chance to know if this was successful...
write-host "Method [$Verb] executed for [$path]"
}
else
{
write-host "Target file [$targetFile] not found, aborting"
}
}
else
{
write-host "Folder [$basePath] not found, aborting"
}
}
#PinToTaskbar "%WINDIR%\notepad.exe"
#UnpinFromTaskbar "%WINDIR%\notepad.exe"
PinToStartmenu "%WINDIR%\notepad.exe"
#UnpinFromStartmenu "%WINDIR%\notepad.exe"
See the script (international) here : http://gallery.technet.microsoft.com/scriptcenter/b66434f1-4b3f-4a94-8dc3-e406eb30b750
If you want to add an action like Pin to Modern UI interface (Windows 8), at $verbs, add 51201
Steven Penny's second answer above worked well for me. Here are a couple more tidbits.
It's doing COM through PowerShell, so you can do the same thing with pretty much any COM client. For example, here's an AutoHotkey version.
Shell := ComObjCreate("Shell.Application")
Target := Shell.Namespace(EnvGet("WinDir")).ParseName("Notepad.exe")
Target.InvokeVerb("startpin")
VBScript or InnoSetup would look almost the same except for the function used to create the object.
I also found that I have one program that pinned OK, but didn't have the right icon and/or description because of limitations in the compiler. I just made a little 1-line WinForms app that starts the target with Process.Start, and then added the appropriate icon, and the name I wanted in the Start Menu in the Title property in AppInfo.cs.