Powershell - How can I test the result of my command? - powershell

Sorry for this stupid question but I don't know how to simply test the result of my command (it returns an object)!
Here is my command:
$command = Get-ADUser -Server "MyServer" -Filter 'Name -eq "test"' -SearchBase "DC=MyDomain,DC=COM" -Properties badpwdcount,lockedout | Select-Object LockedOut
I just want to test the result like this :
if($command -eq $true){
write-host "OK"
}
When I try this command to see the result :
write-host $command
I get "#{LockedOut=True}". So, I have tried to change also my condition like :
if($command -eq "#{LockedOut=True}"){
write-host "OK"
}
But it's not working...

When Write-Host $command outputs #{LockedOut=True}, it's because Select-Object LockedOut produces a new object with a LockedOut property.
Either change your Select-Object statement to use the -ExpandProperty parameter:
$command = Get-ADUser -Server "MyServer" -Filter 'Name -eq "test"' -SearchBase "DC=MyDomain,DC=COM" -Properties badpwdcount,lockedout | Select-Object -ExpandProperty LockedOut
if($command){
# "test" user is locked out
}
or inspect the LockedOut property:
if($command.LockedOut){
# "test" user is locked out
}
As you can see, the -eq $true comparison inside an if statement is redundant
Be aware that you may get unexpected results if you have multiple users with the name test in your directory. If you're locating users by username, you should filter on the SAMAccountName property (which is guaranteed to be unique per-domain):
$command = Get-ADUser -Server "MyServer" -Filter 'SAMAccountName -eq "test"' -SearchBase "DC=MyDomain,DC=COM" -Properties badpwdcount,lockedout | Select-Object -ExpandProperty LockedOut
if($command){
# "test" user is locked out
}

Related

get deactivated computers in ad from csv list

i'm tryin to figure out which computers are deactivated. for that i provide the computer names in a csv list. i just want to output the computers which are deactivated. this is what i have. unfortunately i get all deactivated computers. but i only want that names provided in the csv
Import-CSV -Path "C:\pc_names" | Select -expand Name | Get-ADComputer -searchbase 'XXX' -Filter {(Enabled -eq $False)} -Properties Name, OperatingSystem | Export-CSV “C:\Temp\DisabledComps.CSV” -NoTypeInformation
The problem is likely in the Get-ADComputer command, you specify a SearchBase (assumedly an OU), and a filter for all disabled computers - but never actually include the name of the PC that you piped in from the CSV, so it just returns every disabled PC under that search base.
Try something like this instead;
Import-CSV -Path "C:\pc_names" | Select -Expand Name | Get-ADComputer -SearchBase 'XXX' -Filter {(Enabled -eq $False) -and ($_.Name)} -Properties Name, OperatingSystem | Export-CSV "C:\Temp\DisabledComps.CSV" -NoTypeInformation
Note the $_.Name in the filter.
I've probably got that filter syntax wrong - but that should be the cause.
There is no way you can test if the computername is to be found in an array of names using the -Filter parameter..
You need to first collect computer objects within your SearchBase OU and filter the disabled ones only.
Following that, you filter out the ones that can be found in the $pcNames array using a Where-Object clause:
$pcNames = (Import-Csv -Path "C:\pc_names.csv").Name
Get-ADComputer -SearchBase 'XXX' -Filter "Enabled -eq 'False'" -Properties OperatingSystem |
Where-Object { $pcNames -contains $_.Name } | # or: Where-Object { $_.Name -in $pcNames }
Export-Csv -Path "C:\Temp\DisabledComps.csv" -NoTypeInformation
Note: Get-ADComputer by default already returns these properties: DistinguishedName, DNSHostName, Enabled, Name, ObjectClass, ObjectGUID, SamAccountName, SID, UserPrincipalName. That means you only have to ask for the extra property OperatingSystem in this case
It's pretty obvious that something like this ignores what's piped in and returns many computers.
'comp001' | get-adcomputer -filter 'Enabled -eq $False'
If you wait until the end, there is an error message:
get-adcomputer : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
At line:1 char:13
+ 'comp001' | get-adcomputer -filter 'Enabled -eq $false'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (comp001:String) [Get-ADComputer], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
You can do get-adcomputer inside a foreach loop and test Name as well:
$list = echo comp001 comp002 comp003
$list | % { get-adcomputer -filter 'Enabled -eq $False -and Name -eq $_' }

Retrieving Bitlocker Recovery Keys from AD

Fairly new to Powershell, I managed to get the following code to retrieve the Bitlocker key for computers in the domain, however, I have an issue with it:
Clear-Host
$TestOU = "OU=ABC,DC=XYZ,DC=com"
$PCs = Get-ADComputer -Filter * -SearchBase $TestOU
$Results = ForEach ($Computer in $PCs)
{
New-Object PSObject -Property #{
ComputerName = $Computer.Name
RecoveryPassword = Get-ADObject -Filter 'objectclass -eq "msFVE-
RecoveryInformation"' -SearchBase $computer.DistinguishedName -Properties
msFVE-RecoveryPassword,whencreated | sort whencreated -Descending | select
msfve-recoverypassword
}
}
$Results
My output for each password begins with {a{msfve-recoverypassword= and I'm not sure how to remove this.
The following code gives useful output for human consumption in the shell, but may also be used in a script:
$computer = Get-ADComputer $computerName
Get-ADObject -Filter 'objectClass -eq "msFVE-RecoveryInformation"' -SearchBase $computer.DistinguishedName -Properties whenCreated, msFVE-RecoveryPassword | `
Sort whenCreated -Descending | Select whenCreated, msFVE-RecoveryPassword

Combine powershell output

I'm trying to combine the output of two functions with the output of the default Get-ADUser-cmdlet. I'm interested in when an account was created, if it's locked and what it's name is. I also want to know when the user logged on for the last time (using multiple DC's) and if the account is being used as a shared mailbox.
I've written two custom functions Get-ADUserLastLogon and isSharedMailbox, both functions use the Write-Output function to output their output. In case of Get-ADUserLastLogon this will be Lastlogon: time and in case of isSharedMailbox this will be shared: yes/no. I'm also using a standard Get-ADUser call in a foreach loop
Now, the default output of Get-ADUser is:
SAMAccountName LockedOut Created
-------------- --------- -------
ACC False 23-10-2015 8:20:20
Output of the custom functions is as following:
Lastlogon : 1-1-1601 1:00:00
Shared: yes
What I would like is to combine the LastLogon and Shared 'headers' to be combined into the Get-ADUser. So the output would become:
SAMAccountName LockedOut Created LastLogon Shared
Code of current code, where the accounts get imported from an Excel sheet:
foreach($username in $usernameWithTld){
if ($username -eq $NULL){
break
}
$usernameWithoutTld = $username.split('\')
Get-ADUser $usernameWithoutTld[1] -Properties LockedOut, SamAccountName,
Created -ErrorAction Stop | Select-Object SAMAccountName, LockedOut,
Created
Get-ADUserLastLogon -UserName $usernameWithoutTld[1]
# Shared mailbox?
isSharedMailbox -mailboxname $usernameWithoutTld[1]
}
Function code:
function isSharedMailbox([string]$mailboxname){
$isObject = Get-ADUser -Filter {name -eq $mailboxname} -SearchBase "..." | Select-Object DistinguishedName,Name
if ($isObject -match "DistinguishedName"){
$output = "Shared: no"
Write-Output $output
} else {
$output = "Shared: No"
Write-Output $output
}
}
function Get-ADUserLastLogon([string]$userName){
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs)
{
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time)
{
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
Write-Output "LastLogon : $dt"
}
I'm sure there are lots of improvements that can be made, I'm still learning how to write (proper) PowerShell. I hope someone can answer my question.
You could use a Calculated Property in your Select-Object. Have a look at example 4 for the MSDN page.
In your case this would be:
Get-ADUser $usernameWithoutTld[1] -Properties LockedOut, SamAccountName, Created -ErrorAction Stop | `
Select-Object SAMAccountName, LockedOut, Created, #{Name='LastLogon';Expression={Get-ADUserLastLogon -UserName $usernameWithoutTld[1]}}, #{Name='IsSharedMailbox';Expression={isSharedMailbox -mailboxname $usernameWithoutTld[1]}}
Or even better, you can use the object(s) that Get-ADUser puts in the pipeline to in turn call your functions for that specific object, and can be useful in case your query returns multiple results:
Get-ADUser $usernameWithoutTld[1] -Properties LockedOut, SamAccountName, Created -ErrorAction Stop | `
Select-Object SAMAccountName, LockedOut, Created, #{Name='LastLogon';Expression={Get-ADUserLastLogon -UserName $_.sAMAccountName}}, #{Name='IsSharedMailbox';Expression={isSharedMailbox -mailboxname $_.sAMAccountName}}
One way to do this is to get your functions to return the values you are interested in, store them in variables, and combine everything together afterwards into a PSObject containing the properties you are interested.
The benefits of storing as an object are many. For example, you can use Select-Object, Sort-Object etc in the pipeline, or Export-CSV and other Cmdlets that expect InputObject
foreach($username in $usernameWithTld){
if ($username -eq $NULL){
break
}
$usernameWithoutTld = $username.split('\')
$adDetails = Get-ADUser $usernameWithoutTld[1] -Properties LockedOut, SamAccountName,
Created -ErrorAction Stop | Select-Object SAMAccountName, LockedOut,
Created
$lastlogin = Get-ADUserLastLogon -UserName $usernameWithoutTld[1]
# Shared mailbox?
$isshared = isSharedMailbox -mailboxname $usernameWithoutTld[1]
# putting together the PSobject
[array]$myResults += New-Object psobject -Property #{
SAMAccountName = $adDetails.SAMAccountName
LockedOut = $adDetails.LockedOut
Created = $adDetails.Created
LastLogon = $lastlogin
Shared = $shared # true/false or yes/no, depending on function
#Shared = if($shared){"yes"}else{"no"} # yes/no, based on true/false from function
}
}
Functions:
function isSharedMailbox([string]$mailboxname){
$isObject = Get-ADUser -Filter {name -eq $mailboxname} -SearchBase "..." | Select-Object DistinguishedName,Name
return ($isObject -match "DistinguishedName") # returns true/false
<# if you prefer to keep yes/no
if ($isObject -match "DistinguishedName"){
return "Yes" # no in original code
} else {
return "No"
}
#>
}
function Get-ADUserLastLogon([string]$userName){
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs)
{
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time)
{
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
return $dt
#Write-Output "LastLogon : $dt"
}
You can store the result of the functions in global variables and finally concatenate them is one way.
Else you can use return the output from the function and use the value later or like : $value= functionname then $value will hold the return value of the function and later you can combine the results.
function isSharedMailbox([string]$mailboxname){
$isObject = Get-ADUser -Filter {name -eq $mailboxname} -SearchBase "..." | Select-Object DistinguishedName,Name
if ($isObject -match "DistinguishedName"){
$output = "Shared: no"
$Global:result1= $output
} else {
$output = "Shared: No"
$Global:result1= $output
}
}
function Get-ADUserLastLogon([string]$userName){
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs)
{
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time)
{
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
$Global:result2= "LastLogon : $dt"
}
## Calling the function . Change the placeholders accordingly
Get-ADUserLastLogon -UserName $usernameWithoutTld[1]
isSharedMailbox -mailboxname $usernameWithoutTld[1]
$FinalResult = "result1" + "result2"
$FinalResult
Hope it helps you better understanding.

powershell get samaccountuser with no formatting

I write a powershell command to return the samaccountname, and I kind of get what I want but not exactly.
PS C:\> (get-aduser -Server -f {(GivenName -eq "Nota") -and (Surname -eq "Realuser")} -Properties SamAccountName | select SamAccountName)
This is what I get:
SamAccountName
--------------
NRealuser
This is what I want:
NRealuser
So I want the samaccountname without the header.
You should try the ExpandProperty parameter that Select-Object offers.
(Get-ADUser -Server -f {(GivenName -eq "Nota") -and (Surname -eq "Realuser")} -Properties SamAccountName |
Select-Object -ExpandProperty SamAccountName)
You could also have skipped the Select-Object part and just retrieved the value of the property in the "normal way" like this:
(Get-ADUser -Server -f {(GivenName -eq "Nota") -and (Surname -eq "Realuser")} -Properties SamAccountName).SamAccountName

Powershell - printing out during a loop

I have to go through an OU and remove all the memberOf groups for all users. The script I have works, but I cannot get it to print out when each user is processed. So when I run the script, it working, but nothing happens until its complete. For piece of mind, I want to SEE the current login name that is being processed, but I can't, for the life of me, get the write-host command to write to my screen.
Here is my code:
$users = get-aduser -filter * -searchbase "ou=disabled,dc=corp,dc=test,dc=org" | Sort-Object -Property Name
Function removeMemberShips {
Param( [string] $SAMAccountName)
$user = get-aduser $SAMAccountName -properties memberof
$userGroups = $user.memberof
$userGroups | %{get-adgroup $_ | Remove-ADGroupMember -confirm:$false -member $SAMAccountName}
$userGroups = $null
}
$users | %{removeMemberShips $_.SAMAccountName}
The most obvious way seems to be:
$users | %{
removeMemberShips $_.SAMAccountName
Write-Host $_.SAMAccountName
}