Format string inplace in PowerShell - powershell

I've notice I'm not manage to format string in-place when calling a function in PowerShell. I need to format it because I want to output a number as hex and not decimal.
This didn't work like so:
WriteLog "Running Step | Retry=$RetryCount | EnabledDevices={0:X}" -f $EnabledDevices
It only works if I store the result in variable and then use it like so:
$Log = "Running Step | Retry=$RetryCount | EnabledDevices={0:X}" -f $EnabledDevices
WriteLog $Log
If there a way to do it in one statement instead of two?

Just put it in parentheses:
WriteLog ("Running Step | Retry=$RetryCount | EnabledDevices={0:X}" -f $EnabledDevices)

Related

Using subexpression with & in powershell

I am completely new to powershell.
I have a requirement to have a set of commands as a subexpression $() because I want the output of the command to be sent to Out-Host and without $() the if loops create an issue.
Now there might also be a possibility that the command has filenames with spaces and to handle that we append & before the file name in command.
Bacially, $(& file_name) | Out-Host fails saying & here is invalid.
How to go about using $() with &
Works ok for me. You'll need to supply a counterexample. In this case you couldn't pipe from "if" without $() or &{}.
$( If (1 -eq 1) { & echo hi } ) | out-host > file
hi
# no output until it's finished
$( If (1 -eq 1) { & 'c:\program files\internet explorer\iediagcmd' } ) |
out-host > file

clip and display result in same time

How can I use clip and display output at the same time?
Every time if I put | clip at the of the end line, the output is copied to clipboard, but not displayed in the console window.
Get-Date | clip
Use common parameter -ov (-OutVariable) to also capture Get-Date's output in a variable, then output that variable:
Get-Date -ov output | clip; $output
If the command you're invoking is not a cmdlet or advanced function/script and therefore doesn't support -OutVariable, you can use this technique instead:
($output = Get-Date) | clip; $output
This relies on the fact that enclosing a variable assignment in (...) passes the assigned value through.
You can package this functionality with the help of a custom function:
Function Write-OutputAndClip { $Input | Write-Output -ov output | clip; $output }
If you also define an alias for it, say clipecho ...
Set-Alias clipecho Write-OutputAndClip
... you can invoke it succinctly as:
Get-Date | clipecho # copies output to the clipboard *and* echoes it.
After looking into this a bit I think the only way to do what you're asking is to do it in two separate lines.
$value = Get-Date
Write-host $value
$value | clip
One line would look like this $value = Get-Date;$value;$value|clip
Powershell really wants to redirect anything from write-host to the console. And clip doesn't want to pass anything further down the pipeline...

using powershell like awk to get the console user

I basically want to use powershell and get the console user like
"query session | findstr console | awk '{print $2}'"
but not using awk, but I can't get it to work.
$out = query session | findstr console # good
$consoleuser = $out.split('\s+')[1] # doesn't work
$out looks something like:
>console joe 2 Active
$consoleuser ends up being:
ole joe 2 Active
As others have suggested try the following
$out = query session | findstr console
$consoleuser = $($out -split('\s+'))[1]
Or you could try
$consoleuser = $ENV:username
.Split() is a .Net string method, it doesn't use regexes. -split is the PowerShell operator and uses regexes.
And calling out to findstr is usable, but there's no need to leave PS to use it. e.g.
$out = query session | Where {$_ -match 'console'}
$consoleuser = ($out -split '\s+')[1]
((query session) -match 'console' -split '\s+')[1]
To complement TessellatingHeckler's helpful answer with a further optimization (but note that armorall171's helpful recommendation to simply use $env:USERNAME may be all you need):
(-split ((query session) -match '^>console'))[1]
Output from external command query session is returned as an array of strings by PowerShell, and the -match operator filters that array down to only the matching elements (just 1 line in this case).
The -split operator has a unary form whose behavior is similar to awk's default field-parsing behavior:
It splits the input into array elements by runs of whitespace, ignoring leading and trailing whitespace.
Example:
> -split " ab `t `t cde `n `n efgh "
ab
cde
efgh
Try
($out -Split '\s+')[1]
More useful stuff here

Powershell key=value output

I searched for answer to this before posting, so I apologise in advance if it's here and I can't find it!
I'm using Powershell to pull a heap of data from my Exchange server and it is put into a hashtable.
I have no problem formatting this hashtable to suit my own reporting needs, but now I want to put this data into Splunk (I know about the Splunk Exchange App, this is for different needs).
So Splunk can pull the data in without any pre-processing work I need it to look like the below.
timestamp key=value,key=value,key=value,key=value
timestamp key=value,key=value,key=value,key=value
timestamp key=value,key=value,key=value,key=value
timestamp key=value,key=value,key=value,key=value
timestamp key=value,key=value,key=value,key=value
Try this:
$ht = #{one=1; two=2; three=3}
$KeysAndValues = $ht.GetEnumerator() | Foreach-Object { '{0}={1}' -f $_.Key,$_.Value }
'{0:MM/dd/yyyy} {1}' -f (Get-Date),($KeysAndValues -join ',')
Let's build output the output string with a StringBuilder.
$sb=new-object Text.StringBuilder
# Append timestamp, here from system time
[void]$sb.Append("{0} " -f [datetime]::now.tostring("u"))
# Populate sample hashtable with some data
$ht = #{"foo"="oof"; "bar"="rab"; "baz"="zab"; "qux"="xug" }
# Enumerate the hashtable by sorted names just for fun
$ht.GetEnumerator() | sort name | % {
# Append keys and values to the stringbuilder
[void]$sb.Append($("{0}={1}," -f $_.Name, $_.Value))
}
# Get rid of the tailing comma
[void]$sb.Remove($sb.Length-1, 1)
# Print output
$sb.ToString()

replace variables with value in batch file

I am having a batch file where it has set variable. I would like replace each variable with value.
For ex: My batch file looks like follows
Set Sourcefolder=..\..\Release
Set Variable2=/y /R
Set DestFolder=..\..\Output
XCopy %SourceFolder%\Comp1 %DestFolder%\Comp1 %Variable2%
...
...
..
Likewise it has many lines. I would like to replace the variables with value. For example
instead of %SourceFolder% it should replace with value ( ....\release)
How to achieve this ? batch file or Powershell script are preferrale
This is how I would do it:
$script:variables=#{}
gc .\script.bat | %{ if($_ -match "^Set (.+?)=(.+)"){ $script:variables["$($matches[1])"] = $matches[2]}}
$evaluator ={
$group1 = $args[0].groups[1]
$script:variables["$group1"]
}
gc .\script.bat | %{ [Regex]::Replace($_,"%(.+?)%",$evaluator,[Text.RegularExpressions.RegexOptions]::none) } |
out-file .\script2.bat
Try this:
$bat = switch -regex -file c:\test.bat
{
'^set Sourcefolder=.+$' {'set Sourcefolder=....\release'}
'^set Variable2=.+$' {'set Sourcefolder=/y /R'}
'^set DestFolder=.+$' {'set Sourcefolder=..\..\Output'}
'%SourceFolder%' {'....\release'}
default {$_}
}
$bat | Out-File c:\test.bat