How to get the inactive user in active directory using Powershell? - windows

How to get the inactive user in Active Directory with time stamp using Powershell for Windows 2012 server?

Here is an example to get you started (not tested but should work in 2012):
$DaysInactive = 30
$time = (Get-Date).Adddays(-($DaysInactive))
Get-ADUser -Filter {LastLogonTimeStamp -lt $time -and enabled -eq $true} -Properties LastLogonTimeStamp |
select Name, #{l='LastLogonTimestamp'; E={[DateTime]::FromFileTime($_.LastLogonTimestamp)}} | sort name
This script will get all accounts that have not had the lastlogontimestamp attribute updated in 30 days.

Related

Fastest way to count ad users in PowerShell?

I've been looking for the fastest way to count the number of ad users in powershell, aswell as the number of enabled and disabled users, but the queries are very long (~100k users, 1-2 min per query) and my powershell ISE usually crashes after one or two requests (it's for a reporting job)
So my question is how can I optimize these queries :
$CountADUsers = (get-aduser –filter * -server $myserver).count.Count
$CountADUsersEnabled = (get-aduser -filter * -server $myserver | where {$_.enabled -eq "True"}).count
$CountADUsersNotEnabled = $CountADUsers - $CountADUsersEnabled
Thanks in advance guys
You don't need to run Get-AdUser twice. You can save it to variable and just filter it:
$allUsers = get-aduser –filter * -server $myserver
$CountADUsers = $allUsers.count
$CountADUsersEnabled = ($allUsers | where {$_.enabled -eq "True"}).count
Also, it won't be helpful in that case, but please remember that using -Filter * and then Where-Object is not very effective as you can just use:
Get-ADUser -Filter {enabled -eq "True"}
Another hint: ISE shouldn't be used for running scripts as it sometimes behave in strange ways (especially when you run out of memory on your machine). You should use powershell.exe instead.
Edit: to improve even more you could try to choose only the attributes you need using
$t = $allusers |select userprincipalname,enabled
And then use Where-Object to filter. For comparison:
Measure-command {($allusers | where {$_.enabled -eq "True"}).count}
took two minutes when
Measure-command {($t | where {$_.enabled -eq "True"}).count}
took two seconds (but selecting takes about 2 mins so the overall time is more or less the same). However, this strongly depends on the scenario. I'll leave it to you so you can find the best solution for your case. Remember, Measure-Command is your very good friend for this!

Powershell giving wrong output after scheduling with window's task scheduler

I have a PowerShell script to check the password expiry date of the a system user and send a mail if it is going to expire within 10 days. Script works fine when we run it stand alone. But it show abnormal behaviour after scheduling it with windows task scheduler. Sometimes it works perfectly fine and sometimes it's not.
Output: Password will Expire in -736235 Days.
Expected output: Password will Expire in Days.
It always give -736235 days when if runs incorrectly.
Here is the configuration,
1.General tab
- Run whether user logged in or not
- Run with highest Privilege
- Configure for : Windows server 2012 R2
Action Tab
Program/script: PowerShell
-Add Argument: .\ps.ps1
Start in: D:
Setting Tab(Following Options are checked)
-Allow task to run on demand
Stop task if it running from: 3 days
-if the running task doesn't stop when requested, force stop
If the task is already running then following rule will apply: Stop the existing instance.
Please let me know if you need any other details,
Thanks,
Navdeep
Script is,
$user = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and Name -eq "<user_name>" } –Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Displayname",#{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
$DayCount = $user.ExpiryDate - (GET-DATE)
$DayAbsCount = $DayCount.Days
$message.body = "Password will Expire in $DayAbsCount Days.Please reset."
if ( $DayAbsCount -lt 10)
{
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)
}
,
and the script is running from the same account whose pwd expiration date we needed.

PowerShell - WMI returns incorrect profile last use time

I use Get-WMIObject with the Win32_UserProfile class and LastUseTime property to filter a Win7/Server2008R2 profile deletion script, and recently noticed that the date returned is not matching any of the applicable fields in Windows (Date Accessed, Date Modified, or Date Last Saved).
For example when checking a profile that was last accessed on 5/1/2015 at 1:54 PM per Windows, PowerShell returns the following:
Get-WmiObject -Class Win32_UserProfile -ComputerName TESTCOMPUTER |
Where{$_.LocalPath -Like "*TESTUSER*"} |
ForEach-Object{
Write-Host $_.LastUseTime
Write-Host $_.ConvertToDateTime($_.LastUseTime)}
20150502112839.854000+000
5/2/2015 4:28:39 AM
What am I missing? I though it might have something to do with time zone, but the minute difference throws that off for me. I've spent considerable time searching through Google, but haven't had any luck. Any insight you can provide would be greatly appreciated!
If you run a program under the credentials of TESTUSER but without loading the environment this can happen. Both DateTimes aren't very accurate.
What do you mean with "last accessed? Logon, Logoff, ...?

Exchange 2010 - All maiboxes with auditing enabled

I am trying to return a list of all mailboxes that have auditing enabled. I have tried the below, but it is returning all the users and not just those that have auditing enabled on their mailboxes. Can someone please help. Thanks
Get-Mailbox | select Name | where-object {$_.AuditEnabled -eq $true}
You might want check your pipeline and move the where-object before the select eg
get-mailbox | Where-Object {$_.AuditEnabled -eq $true} | select Name
Cheers
Glen

Is there a way to check AD group membership for a computer?

I am trying to check computer group membership through Powershell. I want to be able to specify a certain computer name and find which groups that computer is in but from a Powershell script. I am planning on running the script on a computer, grabbing the hostname, and then printing out what AD groups that computer is in. Is there an easy way to do this?
EDIT:
So the plan here is to have a computer check to see what groups it is in, then assign a printer based on which group it is in. We have many printers that only 3 to 4 people use but due to the spread out nature of the users cannot downsize the amount of printers. I was looking at group policy but did not want to create 20 different GPOs. I wanted to do this with a logon/startup script. I'm not sure if this is doable or feasible.
Edit #2:
This edit it really late to the party but I figured if anyone found this it could help. We ended up using item level targeting on User>Preferences>Control Panel>Printers objects. We made an account in AD for each group of users needing access to the printers. This worked although it did create a long logon process for the first logon of the computer. We also enabled Point-to-Print restrictions so the drivers were loaded from the servers quietly.
This will give you the group membership (group names) of the local computer (requires powershell 2.0):
([adsisearcher]"(&(objectCategory=computer)(cn=$env:COMPUTERNAME))").FindOne().Properties.memberof -replace '^CN=([^,]+).+$','$1'
Apologies if I'm a bit late to the party on this but I needed to find a computer's group membership as well. After a lot of trial and error, this worked for me.
Get-ADComputer "mycomp" -Properties MemberOf | %{if ($_.MemberOf -like "*group name*") {Write-Host "found"} }
I noticed that if the string comparison is on a separate line, I needed to do the following
$g=Get-ADGroupMember -Identity "CN=myADgroup,OU=myOU,DC=corp,DC=com" -server corp.com
foreach($mbr in $g) {if($name.MemberOf -like "*mycomp*" -eq $true) {Write-Host "found"}}
Not sure but I imagine that testing the computer might be faster and easier than testing the group depending on the number of members.
the gpresult method seems to be the only way I can find that is accurate. Querying AD is not accurate since the computer may have been added to groups but not rebooted. I am sure someone could condense this but it worked well enough for what I needed to see.
# Get all active domain servers
$staledate = (Get-Date).AddDays(-90)
$computers = Get-ADComputer -Filter {(OperatingSystem -Like "*Server*") -and (Enabled -eq $True) -and (LastLogonDate -ge $staledate) -and (Modified -ge $staledate) -and (PasswordLastSet -ge $staledate) -and (whenChanged -ge $staledate) -and (Name -notlike "PHXVSSA101A")} | Select name -expandproperty name
$computers = $computers | Where {(Resolve-DNSName $_.name -ea 0) -and (Test-Connection -ComputerName $_.Name -Count 1 -ea 0)} | Sort
# Loop through all active domain servers
Foreach ($computer in $computers)
{
# Pull the gpresult for the current server
$Lines = gpresult /s $computer /v /SCOPE COMPUTER
# Initialize arrays
$cgroups = #()
$dgroups = #()
# Out equals false by default
$Out = $False
# Define start and end lines for the section we want
$start = "The computer is a part of the following security groups"
$end = "Resultant Set Of Policies for Computer"
# Loop through the gpresult output looking for the computer security group section
ForEach ($Line In $Lines)
{
If ($Line -match $start) {$Out = $True}
If ($Out -eq $True) {$cgroups += $Line}
If ($Line -match $end) {Break}
}
# Loop through all the gathered groups and check for Active Directory groups
ForEach ($group in $cgroups)
{
Try {
$check = Get-ADgroup $group -ErrorAction Stop
If ($check) {
$dgroups += $group
}
}
Catch {}
}
# Output server name and any Active Directory groups it is in
$computer
$dgroups
# End of computers loop
}
try running gpresult /V and check under "security GROUPS"
You can also try gpresult /scope computer /v under a command prompt (elevated to admin) for more specific results
Heres an LDAP query to find if a computer is in a group recursively:
(((objectClass=computer)(sAMAccountName=COMPUTERNAME$))(memberof:1.2.840.113556.1.4.1941:=DistinguishedNameOfGroup))
More info: http://justanotheritblog.co.uk/2016/01/27/recursively-check-if-a-usercomputer-is-a-member-of-an-ad-group-with-powershell-2-0/
To check the computer's own view of group membership, you can run:
(New-Object System.Security.Principal.WindowsPrincipal("$env:computername$")).IsInRole('Example Group')
True
Taking the computer out of Example Group doesn't affect the output of the above until the computer is rebooted.
Try this DOS Command, this will return all the local groups this computer belong to :
net localgroup

Resources