Conversion function not working correctly - powershell

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

Related

Is there any way to avoid the line break when using Read-Host?

I am working on a Powershell script for our support guys, to help them in their day to day tasks.
I have some experience with Powershell, but by far not a hardcore programmer.
I believe my question is fairly basic, even though I have not been able to find the exact answer yet.
function f_LOCAL_CheckADUser($strInitials)
{
try
{
$TestVariable = Get-ADUser -Identity $strInitials -Properties *
Write-Host " - approved" -ForegroundColor Green
}
catch
{
Write-Host " - does not exist" -ForegroundColor Red
}
}
$Internal_Initials = Read-Host " Enter initials"; f_LOCAL_CheckADUser $Internal_Initials
What is happening: The user enters someone’s initials (SamAccountName), the entry is then checked against our AD to see if the user exists, this is working just fine, but the “approve” / “does not exist” line is being printed on the line below what the user entered.
This is what it looks like now:
My question is then, is there any way to avoid the line break, and have the “approve” / “does not exist” be printed on the same line as where the user entered the input?
Would like it to be displayed like this:
I have been searching far and wide, and actually found some inspiration on how to blank out a line and replace it with a new one, but that seems a little overkill. So I am hoping a simple solution may exist.
Inspiration: PowerShell - Overwriting line written with Write-Host credit to Boluwade Kujero for posting the reply.
Starting in PowerShell 5.1, virtual terminal (VT) escape sequences are now supported. One form of escape sequence can move the cursor position, so long as the host supports it. For example:
$esc = [char]27
$setCursorTop = "$esc[0;0H"
function f_LOCAL_CheckADUser($strInitials)
{
$setCursorRight = "$esc[0;$(18 + $strInitials.length)H"
try
{
$TestVariable = Get-ADUser -Identity $strInitials -Properties *
Write-Host "${setCursorRight} - approved" -ForegroundColor Green
}
catch
{
Write-Host "${setCursorRight} - does not exist" -ForegroundColor Red
}
}
Clear-Host
$Internal_Initials = Read-Host "${setCursorTop} Enter initials"
f_LOCAL_CheckADUser $Internal_Initials
...might give you the results you're looking for.
Other escape sequences may be more useful, if you wish to preserve screen information. For more details on other supported VT escape sequences, visit: https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
Hope this helps.

How to make write-host recognizable on TFS?

write-verbose prints out whatever output from powershell onto the TFS logging screen, but write-host doesnt.
what i like about write-host is the -foreground color option it has.
so i would like to retain the colors and hence i ask:
Ive tried write-host but nothing gets printed out on the TFS logging
how can i configure TFS logging to accept/recognize write-host just like it recognizes write-verbose?
There is a solution for the narrower requirements in the comments: Make TFS show Write-Host output without colors, continue having colors on local, and don't change all the Write-Host calls in code to something else.
The solution is to redefine Write-Host only for the TFS environment, such that calls to Write-Host end up using some supported Write- command (like Write-Verbose or Write-Output).
So you can add this to the start of your powershell script:
if($Env:BUILD_BUILDNUMBER) {
function Write-Host($object) {
Write-Output $object
}
}
Note there is an important limitation in this approach: If any function uses Write-Host and then returns some value, it's return value will include whatever was sent to Write-Host. For example, compare the value of $x before redefining Write-Host and after:
function test() {
Write-Host "hi"
return "bye"
}
$x = test
To avoid this, you can also use Write-Verbose or any other Write- instead of Write-Output, but they don't work well for non-primitive types. They will either error out or just show the type name. You can do $object.ToString() inside the Write-Host redefinition to prevent errors, but often that may just show the object's type name.
More info on TFS env variables: https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/powershell?view=azure-devops

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)

Powershell Write-host outputting parameters in variable as string

$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.