Not able to Pass Switch Parameter from Command Shell Prompt - sql

I have a PowerShell script which has couple of parameters including a switch parameter.
The below command executed within PowerShell works as expected:
\\localhost\Test\Code\DataPullResults.ps1 -TestName 'Test survey' -QUser 'sdasch#gmail.com' -SqlServerInstanceName localhost -SqlDatabaseName MyDatabase -Load:$True -ErrorAction Continue;
But when I ran the same command from command prompt I get an error:
\\localhost\Test\Code\DataPullResults.ps1 : Cannot process
argument transformation on parameter 'FullLoad'. Cannot convert value
"System.String" to type "System.Management.Automation.SwitchParameter".
Boolean parameters accept only Boolean values and numbers, such as $True,
$False, 1 or 0.
Below is the command which I have used to execute from the command prompt:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe powershell.exe -ExecutionPolicy ByPass -File \\localhost\Test\Code\DataPullResults.ps1 -TestName 'Test survey' -QUser 'sdasch#gmail.com' -SqlServerInstanceName localhost -SqlDatabaseName MyDatabase -Load:$True -ErrorAction Continue;
Here Load is a Switch Parameter.

powershell.exe does not fully evaluate script arguments when the -File parameter is used (source). So you should use -command instead:
powershell.exe -Command \\localhost\Test\Code\DataPullResults.ps1 -TestName 'Test survey' -QUser 'sdasch#gmail.com' -SqlServerInstanceName localhost -SqlDatabaseName MyDatabase -Load:$True -ErrorAction Continue;
But beside that, note that you don't have to pass a boolean to a switch value. That means, if you omit -Load, $load will be set to $false. And if you pass -Load (without $true), it will get set to $true.
Aslo, did you noticed, that you are calling powershell.exe twice?
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe powershell.exe

Related

Powershell script as a step in sql job giving error

I am trying to create a sql job which syncs users from a csv file to ad group.
My powershell script is one of the steps of this job. Issue is that my script is supposed to run on another server which has Active Directory but i keep on getting error when i run this step.
My script is following:
invoke-Command -Session Server-Name
Import-Module activedirectory
$ADUsers = Import-csv \\Server-Name\folder\file.csv
foreach ($User in $ADUsers)
{
$Username = $User.sAMAccountName
$group=$user.adgroup
if (Get-ADUser -F {SamAccountName -eq $Username})
{
foreach($group in $groups){Add-ADGroupMember -identity $group -Members $Username}
Write-Output "$username has beeen added to group $group"
}
}
Error i am getting is
Executed as user: Username. A job step received an error at line 2 in a PowerShell script. The corresponding line is 'Invoke-Command -Session Server-Name. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Cannot bind parameter 'Session'. Cannot convert the "Server-Name" value of type "System.String" to type "System.Management.Automation.Runspaces.PSSession". '. Process Exit Code -1. The step failed.
server name has '-' in between so need to know if that is causing the issue
or i am using wrong way to run this script on a different server from a sql job
Any help would be appreciated!
Jaspreet I am not expert on powershell but seems like you are passing the wrong parameters.Just referring to Microsoft docs seems like you need to pass the computer name rather than -Session
Try with this line of code at starting
invoke-Command -ComputerName Server-Name.
For more please refer Microsoft docs
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/invoke-command?view=powershell-6#examples

Remote Netstat to STDOUT with WMIC?

I would like to use WMIC to retrieve the output of a "netstat" command on a remote computer. The actual execution of the following command executes without error and I see the output popup briefly within a new window:
wmic /node:server1 process call create "netstat.exe -ano"
With that being said, I need to pipe the output of the process window to STDOUT, and have tried:
wmic /node:server1 process call create "netstat.exe -ano > C:\temp\test.txt"
However, that does not work. I have also tried the /output:STDOUT option, however, that only reports the execution of the command:
Executing (Win32_Process)->Create() Method execution successful. Out Parameters: instance of __PARAMETERS {
ProcessId = 5044;
ReturnValue = 0; };
Does anyone know how I can go about using WMIC to retrieve the actual output from the new window that was opened in order to process the data?
Thanks in advance!
The > symbol behaves as operator of redirection in cmd.exe, not in netstat.exe.
In fact, wmic process call create "netstat.exe -ano > C:\temp\test.txt" is about to run the same as netstat.exe -ano ^> files\nstat.txt (try it from command line).
Next command works (unfortunately, I can't try it with /node:"server1" against a remote computer at the moment):
wmic process call create "cmd /C > C:\temp\test.txt 2>&1 netstat.exe -ano"

Powershell parameter to variables into a command

I tried to find a way to join or use variable into a command.
I'm trying to create a command that accept parameters:
The command: aduser.ps1 John
aduser.ps1 script:
Param($User)
Get-AdUser -filter 'Name -like "*$user*"'
I had error and not sure what operator to use to join in the $user variables, i tried + or & and not working for me.
Variables will not expand inside single quote strings, replace them with double quotes:
Get-AdUser -filter "Name -like '*$user*'"

Equivalent to bash "expect" in powershell

I'm using powershell to run another powershell script, at some point the other script asks for some input, I would like to be able to read the output from the other script and based on that supply input to it. Similar to what you can do with expect on bash.
Any ideas?
Thanks
Just posting my solution so that it can help someone. I faced the same problem while running some other script that will ask for answers. First create a file "inputFileLocation.txt" with answers to each question in each line in sequence. Then run the script in below syntax. And it will do the work.
`cmd.exe /c "script.bat < inputFileLocation.txt"`
You just use Expect program in your powershell. It works. Powershell is a shell too, you can run code wrote by powershell, which call bash code, which call powershell again.
Bellow is a test, it passed.
It "can work with tcl expect" {
$bs = #'
echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
case $yn in
Yes ) echo "install"; break;;
No ) exit;;
esac
done
'#
$bsf = New-TemporaryFile
$bs | Set-Content -Path $bsf
$tcls = #'
#!/bin/sh
# exp.tcl \
exec tclsh "$0" ${1+"$#"}
package require Expect
set timeout 100000
spawn {spawn-command}
expect {
"Enter password: $" {
exp_send "$password\r"
exp_continue
}
"#\? $" {
exp_send "1"
}
eof {}
timeout {}
}
'#
$tclf = New-TemporaryFile
$tcls -replace "{spawn-command}",("bash",$bsf -join " ") | Set-Content -Path $tclf
"bash", $tclf -join " " | Invoke-Expression
Remove-Item $bsf
Remove-Item $tclf
}
Let me explain the test.
create a bash file which expect an input.
create a tcl file which call bash created in step one.
invoke tcl program from powershell, it works, will not waiting for input.
Sample to solve part of the problem
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
Start-Process -FilePath C:\myexecbatchfile.bat
# Wait the application start for 2 sec
Start-Sleep -m 2000
# Send keys
[System.Windows.Forms.SendKeys]::SendWait("input1")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
Start-Sleep -m 3000
[System.Windows.Forms.SendKeys]::SendWait("input2")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
I am not aware of any native capability to duplicate exact. This question has an answer that claims to be able to pass content to/from a process, so it might work with what you want.
How to run interactive commands in another application window from powershell
Good Luck!
Lee Holmes put out an "Expect for Powershell" in 2014 on the Powershell Gallery called Await. Turns out emulating expect is a lot more complicated than you'd imagine, involving the Win32 calls.
Package
https://www.powershellgallery.com/packages/Await/0.8
Demo
https://www.youtube.com/watch?v=tKyAVm7bXcQ

How to pass boolean values to a PowerShell script from a command prompt

I have to invoke a PowerShell script from a batch file. One of the arguments to the script is a boolean value:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify $false
The command fails with the following error:
Cannot process argument transformation on parameter 'Unify'. Cannot convert value "System.String" to type "System.Boolean", parameters of this type only accept booleans or numbers, use $true, $false, 1 or 0 instead.
At line:0 char:1
+ <<<< <br/>
+ CategoryInfo : InvalidData: (:) [RunScript.ps1], ParentContainsErrorRecordException <br/>
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,RunScript.ps1
As of now I am using a string to boolean conversion inside my script. But how can I pass boolean arguments to PowerShell?
A more clear usage might be to use switch parameters instead. Then, just the existence of the Unify parameter would mean it was set.
Like so:
param (
[int] $Turn,
[switch] $Unify
)
It appears that powershell.exe does not fully evaluate script arguments when the -File parameter is used. In particular, the $false argument is being treated as a string value, in a similar way to the example below:
PS> function f( [bool]$b ) { $b }; f -b '$false'
f : Cannot process argument transformation on parameter 'b'. Cannot convert value
"System.String" to type "System.Boolean", parameters of this type only accept
booleans or numbers, use $true, $false, 1 or 0 instead.
At line:1 char:36
+ function f( [bool]$b ) { $b }; f -b <<<< '$false'
+ CategoryInfo : InvalidData: (:) [f], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,f
Instead of using -File you could try -Command, which will evaluate the call as script:
CMD> powershell.exe -NoProfile -Command .\RunScript.ps1 -Turn 1 -Unify $false
Turn: 1
Unify: False
As David suggests, using a switch argument would also be more idiomatic, simplifying the call by removing the need to pass a boolean value explicitly:
CMD> powershell.exe -NoProfile -File .\RunScript.ps1 -Turn 1 -Unify
Turn: 1
Unify: True
Try setting the type of your parameter to [bool]:
param
(
[int]$Turn = 0
[bool]$Unity = $false
)
switch ($Unity)
{
$true { "That was true."; break }
default { "Whatever it was, it wasn't true."; break }
}
This example defaults $Unity to $false if no input is provided.
Usage
.\RunScript.ps1 -Turn 1 -Unity $false
This is an older question, but there is actually an answer to this in the PowerShell documentation. I had the same problem, and for once RTFM actually solved it. Almost.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
Documentation for the -File parameter states that
"In rare cases, you might need to provide a Boolean value for a switch parameter. To provide a Boolean value for a switch parameter in the value of the File parameter, enclose the parameter name and value in curly braces, such as the following: -File .\Get-Script.ps1 {-All:$False}"
I had to write it like this:
PowerShell.Exe -File MyFile.ps1 {-SomeBoolParameter:False}
So no '$' before the true/false statement, and that worked for me, on PowerShell 4.0
I think, best way to use/set boolean value as parameter is to use in your PS script it like this:
Param(
[Parameter(Mandatory=$false)][ValidateSet("true", "false")][string]$deployApp="false"
)
$deployAppBool = $false
switch($deployPmCmParse.ToLower()) {
"true" { $deployAppBool = $true }
default { $deployAppBool = $false }
}
So now you can use it like this:
.\myApp.ps1 -deployAppBool True
.\myApp.ps1 -deployAppBool TRUE
.\myApp.ps1 -deployAppBool true
.\myApp.ps1 -deployAppBool "true"
.\myApp.ps1 -deployAppBool false
#and etc...
So in arguments from cmd you can pass boolean value as simple string :).
Running powershell scripts on linux from bash gives the same problem. Solved it almost the same as LarsWA's answer:
Working:
pwsh -f ./test.ps1 -bool:true
Not working:
pwsh -f ./test.ps1 -bool=1
pwsh -f ./test.ps1 -bool=true
pwsh -f ./test.ps1 -bool true
pwsh -f ./test.ps1 {-bool=true}
pwsh -f ./test.ps1 -bool=$true
pwsh -f ./test.ps1 -bool=\$true
pwsh -f ./test.ps1 -bool 1
pwsh -f ./test.ps1 -bool:1
To summarize and complement the existing answers, as of Windows PowerShell v5.1 / PowerShell Core 7.0.0-preview.4:
David Mohundro's answer rightfully points that instead of [bool] parameters you should use [switch] parameters in PowerShell, where the presence vs. absence of the switch name (-Unify specified vs. not specified) implies its value, which makes the original problem go away.
However, on occasion you may still need to pass the switch value explicitly, particularly if you're constructing a command line programmatically:
In PowerShell Core, the original problem (described in Emperor XLII's answer) has been fixed.
That is, to pass $true explicitly to a [switch] parameter named -Unify you can now write:
pwsh -File .\RunScript.ps1 -Unify:$true # !! ":" separates name and value, no space
The following values can be used: $false, false, $true, true, but note that passing 0 or 1 does not work.
Note how the switch name is separated from the value with : and there must be no whitespace between the two.
Note: If you declare a [bool] parameter instead of a [switch] (which you generally shouldn't), you must use the same syntax; even though -Unify $false should work, it currently doesn't - see this GitHub issue.
In Windows PowerShell, the original problem persists, and - given that Windows PowerShell is no longer actively developed - is unlikely to get fixed.
The workaround suggested in LarsWA's answer - even though it is based on the official help topic as of this writing - does not work in v5.1
This GitHub issue asks for the documentation to be corrected and also provides a test command that shows the ineffectiveness of the workaround.
Using -Command instead of -File is the only effective workaround:
:: # From cmd.exe
powershell -Command "& .\RunScript.ps1 -Unify:$true"
With -Command you're effectively passing a piece of PowerShell code, which is then evaluated as usual - and inside PowerShell passing $true and $false works (but not true and false, as now also accepted with -File).
Caveats:
Using -Command can result in additional interpretation of your arguments, such as if they contain $ chars. (with -File, arguments are literals).
Using -Command can result in a different exit code.
For details, see this answer and this answer.
In PowerShell, boolean parameters can be declared by mentioning their type before their variable.
function GetWeb() {
param([bool] $includeTags)
........
........
}
You can assign value by passing $true | $false
GetWeb -includeTags $true
I had something similar when passing a script to a function with invoke-command. I ran the command in single quotes instead of double quotes, because it then becomes a string literal. 'Set-Mailbox $sourceUser -LitigationHoldEnabled $false -ElcProcessingDisabled $true';
Based on my test, a default value specification does not work for a parameter that is expected to be a boolean in the Function.
You can use the [switch] type or if you really want to use boolean, you should specify default value at the start of the function like below:
Function nullRules {
Param
(
[Parameter(Mandatory=$false)] $boolWins
)
if ([DBNull]::Value.Equals($boolWins)) {$boolWins=$false}
....
....
}
You can also use 0 for False or 1 for True. It actually suggests that in the error message:
Cannot process argument transformation on parameter 'Unify'. Cannot convert value "System.String" to type "System.Boolean", parameters of this type only accept booleans or numbers, use $true, $false, 1 or 0 instead.
For more info, check out this MSDN article on Boolean Values and Operators.