Powershell Write-host outputting parameters in variable as string - powershell

$mycolorparams = "-foregroundcolor red -backgroundcolor black"
write-host "I want this foreground in Red and background in black" $mycolorparams
Hi All,
This is driving me nuts. When I use write-host the cmdlet returns everything as string:
"I want this foreground in Red and background in black -foregroundcolor red -backgroundcolor black".
Not the actual string with red text and a black background.
The worst part is this was working for me until I changed the var name in my code. I have no idea what has been altered since. I suspect it has something to do with the quotes as single quotes spit out the string and double quotes read the var. But after trying heaps of variations with single and double on both the text and var the results are the same just a string output.
I have been trawling the web for the past hour with no luck, plenty of examples but nothing I can find with the specific problem. Any help appreciated, thanks.

Use argument splatting (though I think it wasn't in old versions so you might need to upgrade to Powershell version 3 or later).
PS C:\> $opts = #{ForegroundColor="red"; BackgroundColor="black"; object="Hello world"}
PS C:\> write-host #opts
Hello world
or:
PS C:\> $opts = #{ForegroundColor="red"; BackgroundColor="black"}
PS C:\> write-host #opts -object "Hello world"
Hello world
You'll need to convert your options string into either a hashtable or an array. In fact if you run help about_Splatting you'll find one of the examples exactly covers your question:
This example shows how to re-use splatted values in different
commands.
The commands in this example use the Write-Host cmdlet to write messages
to the host program console. It uses splatting to specify the foreground
and background colors.
To change the colors of all commands, just change the value of the $Colors
variable.
The first command creates a hash table of parameter names and values and
stores the hash table in the $Colors variable.
$Colors = #{ForegroundColor = "black"
BackgroundColor = "white"}
The second and third commands use the $Colors variable for splatting in a
Write-Host command. To use the $Colors variable, replace the dollar sign
($Colors) with an At symbol (#Colors).
# Write a message with the colors in $Colors
Write-Host "This is a test." #Colors
# Write second message with same colors.
# The position of splatted hash table does not matter.
Write-Host #Colors "This is another test."

Hmm.. I have a little workaround for you in shape of a wrapper function:
$mycolorparams = " -foregroundcolor red -backgroundcolor black"
function redBlack($text){
invoke-expression ("write-host " + $text + $mycolorparams)
}
Then execute
redBlack "I want this foreground in Red and background in black"
which will yield a correctly coloured result.

Related

Contain Write-host in a variable

I am after storing write-host as a variable for multiple lines
So I want to encompass the write-host section below so it is essentially copied and pasted to the beginning of the loop, updating certain parameters.
the script is to check a file and see how many lines are in the file, this then carries out a function on each line, I want to update the user on the progress, however during the loop I cls and want to update the progress. Simple progress bar.
However I am unable to do so, so I created a variable that stores this information and updates accordingly.~
The varible only contains the information I want to update, see code.
I have tried the following;
Surrounding in parenthese,
using , to change to a new line,
Encasing the statement in ().
$56 = (Write-Host "This is a test" -foregroundcolor green),
(Write-host "Same Test only bigger"-foregroundcolor red) ,
"No!",
"I am King" $King ++
#$56
Output is
This is a test
Same Test only bigger
I want it to only display if I use the variable $56 as you can see it pulls the write-host without the variable.
Write-Host doesn't return its output as an object; it bypasses the pipeline to go directly to the console, effectively "returning" a null string. As such, you can't save the result of a Write-Host in a variable.
You can, however, save a script block in a variable, and execution of any statement in the script block variable will be deferred until the variable is invoked with the & expression, e.g.,
$fifty-six = { Write-Host "This is a test" -foregroundcolor green }
& $fifty-six
You should, however, consider carefully what your goal is, and whether there might not be a better way to do things. If you are interested in tracking the progress of a function, and you are using PowerShell 3.0 or later, you may want to look into Write-Progress instead.
I still think a function can do this:
function Output {
param([int]$lineNumber)
switch ($lineNumber) {
1 {Write-Host "This is a test" -foregroundcolor green}
2 {Write-host "Same Test only bigger"-foregroundcolor red}
3 {"No!"}
4 {"I am King"}
}
}
PS H:\> Output 1
This is a test
PS H:\> Output 4
I am King
I don't know what King is here, but if you want to use that as an increment, then you can just do this:
PS H:\> $King = 1
PS H:\> Output $King
This is a test
PS H:\> $King++
PS H:\> output $King
Same Test only bigger

Powershell remove space from after command

I have this command
Write-Host "Background " -NoNewline; [System.Windows.Forms.SystemInformation]
::PrimaryMonitorSize.Width; Write-Host "x" -NoNewline;
[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height
I want it to come out Background 1920x1080
I cant seem to find a way to stop the command
[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width
from making a new line.
Its coming out
Background 1920
x1080
It's less complicated to simply use string formatting or in-line expand into a single string.
"Background {0}x{1}" -f [System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width,[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height
or
Write-Host "Background $([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width)x$([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height)"
An article on various formatting options: https://blogs.technet.microsoft.com/heyscriptingguy/2013/03/12/use-powershell-to-format-strings-with-composite-formatting/
The reason you're getting the extra newline is that your code sample omitted a Write-Host on the Width portion. The first items went to Write-Host, then an item on the output stream that didn't have a way to omit the newline. Simply correcting that flaw gives you the output you desired, but the approach is overly complicated.
Fixed original sample:
Write-Host "Background " -NoNewline;
Write-Host ([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width) -NoNewLine;
Write-Host "x" -NoNewline;
Write-Host ([System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height)
You are getting multiple lines because you are not calling Write-Host -NoNewLine on the command to output the width. Your code is running the following four commands
Write-Host "Background " -NoNewline
[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width
Write-Host "x" -NoNewline
[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height
The second and fourth commands insert a newline, because you didn't use Write-Host to tell them not to.
Write-Host is not usually the best way to output text. A better option would be to build the output string in one statement using PowerShell's -f formatting operator.
$width = [System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width
$height = [System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height
"Background {0}x{1}" -f ($width, $height)

Displaying block of text

I've done a bit of Googling and can't seem to find an effective method of displaying an entire block of text to the console. I would rather not use the Write-Host command on every line if I need to display a block of code. I'm trying to make an interactive script that's somewhat aesthetic. Is there an example that someone could give me?
PowerShell supports multiline strings, either as here-strings:
Write-Host #"
Some text you
want to span
multiple lines.
"#
or regular strings:
Write-Host "Some text you
want to span
multiple lines."
In addition to Ansgar's examples, Write-Host accepts an array too.
'one','two','three' | Write-Host
So whether your multi-line string is a single string, or an array of lines, it will still work as expected with a single Write-Host call:
Get-Content mycode.txt | Write-Host
Get-Content mycode.txt -Raw | Write-Host

Conversion function not working correctly

So I'm taking a powershell class and am trying to create a script that converts feet into meters. this is what I have so far but it's not working correctly. I've been tinkering with it for about an hour but can't quite get it to operate properly.
Write-Host Hey there. This is an easy script that will convert Feet to Meters - ForegroundColor Cyan -BackgroundColor Magenta
PAUSE;
Function script:converttometers($feet)
{
"$feet feet equals $($feet*.31) Meters"
} #end Converttometers
Converttometers -feet $feet(Read-Host)
I'm having trouble getting it to take the input from read-host. Doesn't want to use it for some reason =/
Try calling your function like this:
ConvertToMeters -feet (Read-Host -prompt "Enter feet")
Also be aware that when you write a message to the console using Write-Host and you don't quote the string, PowerShell will remove extra spaces and commas. And if you have to be careful with - because Powershell might try to interpret the following text as a parameter. Subsequently I recommend just using quotes:
Write-Host 'Hey there. This is an easy script that will convert Feet to Meters' -ForegroundColor Cyan -BackgroundColor Magenta
BTW that's a horrible color combination. :-)
The other problem you are running into is due to $feet being a string rather than a number. Try it like this:
Write-Host 'Hey there. This is an easy script that will convert Feet to Meters' -Fore Cyan -Back Magenta
PAUSE
Function ConverTo-Meters($feet) {
"$feet equals $(.31*$feet) meters"
}
ConvertTo-Meters -feet (Read-host -prompt "Enter Feet")
Another way you could solve this is to specify the type of $feet e.g.:
Function Converttometers([double]$feet) { ... }
The way you have it now, PowerShell is using a feature where you can take a string and repeat it e.g.:
"a" * 4 # outputs aaaa
Since you specified .31 which is less than one, you get an empty string as result e.g.:
("10" * .31).length # outputs 0

How to expand member-variables in Write-Host or double quotes?

I have written a PS script and for diagnostic purpose am echoing messages to screen using Write-Host. This is fine as long as I have to expand normal variable like
Write-Host "Hello World, $name"
Problem starts when i try to echo some member variable as below
Write-Host "Hello World, $Person.Name"
This does not expand as expected. The work around that am following is, to use temp variable
as below
$personName = $Person.Name
Write-Host "Hello World, $personName"
Is there an elegant way of doing this with out the use of temp variable?
If you want to use property access within double-quoted strings, you need a subexpression:
"Foo $($bar.Property)"
Try this:
$dir = ls
Write-Host "Dir elements:" $dir.Length