I have a powershell script which looks to make sure someone is running the script as an admin.
The variable $currentPrincipal returns true or false.
Here is the code:
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
If ($currentPrincipal -eq $true) {
Write-host "yay"
}
Else {
Write-Host "boo"
}
But when running as an admin AND currentPrincipal is true, it still falls through to the else... here is the CLI which shows that:
PS C:\WINDOWS\system32> C:\Users\dogzilla\Desktop\SetSQLServerToManual.ps1
True
boo
My question is, what is the proper way to evaluate a boolean in powershell?
Your currently just calling WindowsPrincipal.IsInRole, which will output the Boolean result. Additionally, $currentPrincipal is of type System.Security.Principal.WindowsPrincipal, which is not a Boolean. I would ammend your code to store the result of IsInRole() as a variable and checking that instead.
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
$checkRole = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
If ($checkRole -eq $true) {
Write-host "yay"
}
Else {
Write-Host "boo"
}
This is the way to test it:
if ( ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) -eq $true )
Related
So I have an SSM association that would run a AWS-RunRemoteScript document to call a Powershell script that would run commands for domain join.
Its successfully doing the domain join but after I try to do a exit 3010, which return a 255 exit status and my script fails.
My AWS-RunRemoteScript document accepts some params. Below is the snippet in my powershell script.
try {
$ansible_token = (Get-SECSecretValue -SecretId $ansibletoken_secretname -Select SecretString | ConvertFrom-Json | Select -ExpandProperty token)
$instanceid = Invoke-RestMethod -Uri "http://169.254.169.254/latest/meta-data/instance-id"
$limit = $instanceid + ",127.0.0.1"
If((gwmi win32_computersystem).partofdomain -ne $True) {
Write-Host "Instance not joined to domain. Running domain join ansible template.."
$domain_join_success = Run-AnsibleJob $domain_join_template $extra_vars_param_domain_join $limit $ansible_token $tower_url
if ($domain_join_success -eq $True)
{
Write-Host "Shutting Down Instance $($instanceid).." --> This is printed and then I get a 255.
exit 3010
}
}
If((gwmi win32_computersystem).partofdomain -eq $True)
{
Write-Output "The instance is domain joined, running node setup ansible template.."
$node_initialize_success = Run-AnsibleJob $initialize_node_template $extra_vars_param_initialize_node $limit $ansible_token $tower_url
If($node_initialize_success -eq $True)
{
exit 0
}
}
}
catch {
Write-Host "--------------Error Occured----------------"
Write-Host $_
}
exit 1
Run-AnsibleJob is a function which calls an ansible job and returns tru if it is successful, and false if it fails.
What am doing wrong?
I am trying to get info about an iSCSI-Targets Connectionstate.
Ideally I want to have a variable with a value that is True or False for connected or not connected, so that i can run commands to connect or disconnect as needed.
If i set the Variable directly it's working fine. Setting the Variable with the output of a cmdlet seems to work but comparing the Values False or True with IF is always resulting in True. For me the question is: where is the difference between setting the Variable directly to True and using the output of the cmdlet...?
Sample one:
$IsConnected=true
if($IsConnected -eq 'true') {
echo IsConnected!
} else {
echo IsNotConnected
}
Results, as expected, in: IsConnected
Sample two:
$IsConnected=False
if($IsConnected -eq 'true') {
echo IsConnected!
} else {
echo IsNotConnected
}
Results, as expected, in: IsNotConnected
So now my knowledge ends...:
Sample three:
PS ~> $IsConnected=get-iscsitarget | select -ExpandProperty IsConnected
PS ~> echo $IsConnected
True
PS ~> if($IsConnected -eq 'True') {Echo "IsConnected"}else{echo "IsNotConnected"}
IsConnected
PS ~> if($IsConnected -eq 'False') {Echo "IsConnected"}else{echo "IsNotConnected"}
IsConnected
PS ~> if($IsConnected -eq '17beerarenotenaugh') {Echo "IsConnected"}else{echo "IsNotConnected"}
IsConnected
PowerShell's comparison operators are overloaded, meaning they might have different behaviors based on the type of operand you provide.
The behavior depends entirely on the type of the left-hand side (lhs) operand you provide, and PowerShell will try to convert the right-hand side (rhs) to the same.
In your example, the value of the $IsConnected variable is a [bool] - and PowerShell therefore attempts to convert the rhs operand to a [bool] to.
The conversion logic for [string] to [bool] is:
Empty strings = $false
Non-empty strings = $true
Since 'True', 'False' and '17beerarenotenaugh' are all non-empty, the if conditions are basically interpreted as:
if($IsConnected -eq $true) { ... }
if($IsConnected -eq $true) { ... }
if($IsConnected -eq $true) { ... }
Use the automatic variables $true and $false to avoid this:
PS ~> if($IsConnected -eq $false) {Echo "IsConnected"}else{echo "IsNotConnected"}
IsNotConnected
alternatively, use the -not operator:
PS ~> if(-not $IsConnected) {Echo "IsConnected"}else{echo "IsNotConnected"}
IsNotConnected
thanks for helping!. Our NAS disconnects sometimes or just don't connect after Reboot so maybe some others find this usefull...:
$IsConnected = Get-IscsiTarget | Select-Object -ExpandProperty IsConnected
If($IsConnected -eq $false)
{
Get-IscsiTarget | Where-Object -Property NodeAddress -Like "iqn.2000-01.com.synology:nas01.Target-myiqnnumber" |
Connect-IscsiTarget -AuthenticationType ONEWAYCHAP -ChapUsername mychapuser -ChapSecret mychapuserssecret
}
else
{
echo "IsConnected=$Isconnected iSCSI-Drive:OK"
}
I'm trying to make a loop for joining a Windows domain in PowerShell with usage of $?, which should return false/true if last command returned error or not.
This is what I got:
Add-Computer -DomainName "domainname.local" -Credential "admin"
$MaxAttempts = 0
do {
if ($? -like "false" -and $MaxAttempts -lt 5) {
$MaxAttempts += 1
Write-Host "Attempt" $MaxAttempts "out of 5"
Add-Computer -DomainName "domainname.local" -Credential "admin"
} else {
Write-Host "test"
}
Problem is when I have first command outside of that do/until loop it's returning true even when I get an error.
But when I add this command to do/until loop it returns false as expected but that way im running that command twice and that's not I want.
Can someone explain me this sorcery?
The automatic variable $? contains true or false depending on whether or not the previous PowerShell statement completed successfully. The last PowerShell statement before you check the value of $? inside the loop is $MaxAttempts = 0, which changes the value of $? to true (because the assignment operation succeeded), even if the Add-Computer statement before that failed.
I'd recommend adjusting your loop to something like this:
$MaxAttempts = 0
do {
Add-Computer -DomainName "domainname.local" -Credential "admin"
$success = $?
if (-not $success) {
$MaxAttempts++
}
} until ($success -or $MaxAttempts -ge 5) {
I have the following code in my powershell script to validate user input (The first positional argument in the script):
function validatePath {
Param
(
[Parameter(Mandatory=$true)]
[ValidateScript({
If ($_ -match "^([a-z]:\\(?:[-\\w\\.\\d])*)") {
$True
} Else {
Write-Host "Please enter a valid path,$_ is not a valid path."
Write-debug $_.Exception
Break
}
})]
[string]$filePath
)
Process
{
Write-Host "The path is "$filePath
}
}
validatePath -filePath $args[0]
My problem is, currently when the validation fails, and the code goes in the Else block and hits Break, instead of stopping the entire script from continue running, it goes to the next block and everything continues and more errors come out.
Question is, how can I modify my code so that When the validation fails to match the regex, it will throw an appropriate error message and stops the entire script from running?
Set the $ErrorActionPreference variable inside the script to Stop:
$ErrorActionPreference = 'Stop'
function validatePath {
Param
(
[Parameter(Mandatory=$true)]
[ValidateScript({
If ($_ -match "^([a-z]:\\(?:[-\\w\\.\\d])*)") {
$True
} Else {
Write-Host "Please enter a valid path,$_ is not a valid path."
Write-debug $_.Exception
Break
}
})]
[string]$filePath
)
Process
{
Write-Host "The path is "$filePath
}
}
validatePath -filePath $args[0]
Do-MoreStuff # this won't execute if parameter validation fails in the previous call
See the about_Preference_Variables help file for more information
use "exit" to stop the entire script. Put any message before the "exit".
I am trying to test if two PC's are connected by using the following script
$array ='PC1','PC2'
for ($i=0; $i -lt $array.length; $i++) {
Start-Job –Name TestConnection$i –Scriptblock {
if(test-connection $array[$i] -count 1 -quiet){
write-host Success
}
else { write-host No connection
}
}
}
When I try to do Receive-Job for either one I get "Cannot index into a null array".
What am I doing wrong?
You need to pass in the PC name as an argument, as the array does not exist in the context of the script block, like this:
$array ='PC1','PC2'
for ($i=0; $i -lt $array.Length; $i++) {
Start-Job –Name TestConnection –Scriptblock {
param($pcName)
if(Test-Connection $pcName -Count 1 -Quiet) {
Write-Host Success
} else {
Write-Host No connection
}
} -ArgumentList $array[$i]
}
You have to pass $i (and any other variables) via -ArgumentList through the Start-Job Cmdlet since your script block is running in an entirely different powershell host and doesn't have access to anything inside the shell that started the job.
Even though your script block exists inside the original code, Powershell does not expand any variables in it until it's executing the code in the other host. You can define param() at the beginning of your script block to use the variable you pass via -ArgumentList