How to add a text in a file with an argument in Powershell - powershell

I am trying to add the text passed as an argument in powershell to config file. Below is the sample of the code. What I am expecting that below command will read the config file & search for parameter1 & when it find the parameter it will add the value (passed as an argument) after "="
(gc config.params) -replace "Parameter1 =", "$&` $1" | sc inifile.params
So the output supposed to be like:
Parameter1 = hostname
when the following command will be executed:
powershell.exe Untitled1.ps1 hostname
Please suggest.

$1 is not how arguments are passed to PowerShell scripts; they get an array $args or you specify parameter names. And the array does not have the script path as the first element.
So, for your code:
(gc config.params) -replace "Parameter1 =", "$&` $($args[0])" | sc inifile.params
or
param($text)
(gc config.params) -replace "Parameter1 =", "$&` $text" | sc inifile.params

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

powershell : pipe get-content to ps1 file with parameters

I'm trying to write a script which uses the powershell cmdlet get-content tail and inserts the new lines into the sql server table. i can't get the syntax to pipe the tail to the sqlinsert.ps1 file that handles the table insert.
i'm looking for help on how to pipe "get-content tail" to a sqlinsert.ps1 file to do a sql database insert statement using the following :
$startTime = get-date
Write-Host "\\iisserver\logs\Logs-$("{0:yyyyMMdd}" -f (get-date)).txt"
get-content "\\iisserver\logs\Logs-$("{0:yyyyMMdd}" -f (get-date)).txt" -tail 1 -wait | & "sqlinsert.ps1" -stmp $("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date)) -method "Error" -msg $_
# % { "$_ read at $(Get-Date -Format "hh:mm:ss")" }
in the sqlinsert.ps1 :
param ([string]$stmp, [string]$method, [string]$msg )
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$serverName';database='$databaseName';User ID = $uid; Password = $pwd;"
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$sql = "insert into [tbl_iiserrors] (errstamp, method, msg) values (#stmp , #method, #msg) "
.
.
.
error i get:
& : The term 'sqlinsert.ps1' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is
correct and try again. At C:\Temp\ob\iislog\tst_tail.ps1:3 char:95
... Mdd}" -f (get-date)).txt" -tail 1 -wait | & "sqlinsert.ps1" -stmp $ ...
~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (sqlinsert.ps1:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
Suggestion [3,General]: The command sqlinsert.ps1 was not found, but
does exist in the current location. Windows PowerShell does not load
commands from the current location by default. If you trust this
command, instead type: ".\sqlinsert.ps1". See "get-help
about_Command_Precedence" for more details.
The sqlinsert.ps1 works when i run it from powershell command :
PS c:\temp> .\sqlinsert -stmp 2020-11-20 00:00:00 -method 'eek' -msg 'uh hello'
In order to bind pipeline input to a parameter, you need to decorate it with a [Parameter] attribute and specify that it accepts pipeline input, like this:
param (
[string]$stmp,
[string]$method,
[Parameter(ValueFromPipeline = $true)]
[string]$msg
)
See the about_Functions_Advanced_Parameters help file for more details about how to modify the behavior of parameters
By design, for security reasons, PowerShell requires you to signal the intent to execute a script located in the current directory explicitly, using a path - .\sqlinsert.ps1 - rather than a mere file name - sqlinsert.ps1; that is what the suggestion following the error message is trying to tell you.
Note that you only need &, the call operator, if the script path is quoted and/or contains variable references - and .\sqlinsert.ps1 doesn't require quoting.
You can only use the automatic $_ variable, which represents the current input object from the pipeline inside a script block ({ ... }), such as one passed to the ForEach-Object cmdlet, which invokes that block for each object received via the pipeline.
Re the content of your script: Inside expandable strings ("..."), you cannot use # to refer to variables to be expanded (interpolated); use regular, $-prefixed variable references or $(...), the subexpression operator to embed expressions; also, it looks like you're inserting string values into the SQL table, so you'll have to enclose the expanded variable values in embedded '...'
$startTime = get-date
Get-Content "\\iisserver\logs\Logs-$("{0:yyyyMMdd}" -f (get-date)).txt" -Tail 1 -Wait |
ForEach-Object {
.\sqlinsert.ps1 -stmp ("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date)) -method "Error" -msg $_
}
The alternative to using a ForEach-Object call is to modify your script to directly receive its -msg argument from the pipeline, as shown in Mathias' answer, in which case you must omit the -msg $_ argument from your script call:
Get-Content ... |
.\sqlinsert.ps1 -stmp ("{0:yyyy-MM-dd hh:mm:ss.fff}" -f (get-date)) -method "Error"

Invoke-Expression cannot execute multi-line functions

I was trying to run a PowerShell script saved in a text document by using the following:
cat myScript.txt | Invoke-Expression
It works when each command is on its own line but throws an error saying I am missing syntax:
Invoke-Expression: At line:1 char:14
+ function foo {
+ ~
Missing closing '}' in statement block or type definition.
The code in myScript.txt is as follows:
function foo {
param([int]$a, [int]$b)
echo "$a + $b"
}
foo 1 2
Is there a way to run this script without changing the text file to merge all functions to one line?
You can also use out-string to convert output into string.
cat myScript.txt | out-string | Invoke-Expression

How to read value of parameter defined in text file

I am using the below command to read the value of parameter defined in txt file.
$asid = Get-Content -Path config.cfg | Select-String -Pattern 'NW_GetSid' | ForEach-Object { $_.line.split('= ') }
The parameter is defined as below in file:
Hostname = hostname
NW_GetSid = ABC
The command gives the output with blank line first & then outputs:
Blank line
ABC
How can I avoid the blank line in my result as in output I just need ABC to get stored in asid variable?
I would use a regex to retrieve the value of your desired property
$asid = [regex]::Match((get-content config.cfg -Raw), 'NW_GetSid\s*=\s*(\w+)').Groups[1].Value

Piping from a variable instead of file in Powershell

Is ther any way in Powershell to pipe in from an virable instead of a file?
There are commands that I need to pipe into another command, right now that is done by first creating a file with the additional commands, and then piping that file into the original command. Code looks somehting like this now:
$val = "*some command*" + "`r`n" + "*some command*" + "`r`n" + "*some command*"
New-Item -name Commands.txt -type "file" -value $val
$command = #'
db2cmd.exe /C '*custom db2 command* < \Commands.txt > \Output.xml'
'#
Invoke-Expression -Command:$command
So instead of creating that file, can I somehow just pipe in $val insatead of Commands.txt?
Try this
$val = #("*some command*1","*some command2*","*some command3*")
$val | % { db2cmd.exe /C $_ > \Output.xml }
You should be able to pipe in from $val provided you use Write-Output or its shorthand echo, but it may also be worth trying passing the commands directly on the command line. Try this (and if it doesn't work I can delete the answer):
PS C:\> filter db2cmd() { $_ | db2cmd.exe ($args -replace '(\\*)"','$1$1\"') }
PS C:\> $val = #"
>> *custom db2 command*
>> *some command*
>> *some command*
>> *some command*
>> "#
>>
PS C:\> db2cmd /C $val > \Output.xml
What happens here is that Windows executables receive their command line from a single string. If you run them from cmd.exe you cannot pass newlines in the argument string, but Powershell doesn't have that restriction so with many programs you can actually pass multiple lines as a single argument. I don't know db2cmd.exe so it might not work here.
The strange bit of string replacement is to handle any double quotes in the arguments: Powershell doesn't quote them and the quoting rules expected by most exe files are a bit bizarre.
The only limitation here would be that $val must not exceed about 32,600 characters and cannot contain nulls. Any other restrictions (such as whether non-ascii unicode characters work) would depend on the application.
Failing that:
echo $val | db2cmd.exe /C '*custom db2 command*' > \Output.xml
may work, or you can use it in combination with the filter I defined at the top:
echo $val | db2cmd /C '*custom db2 command*' > \Output.xml