Remove old/redundant activesync partnerships - powershell

I have used a script to get all users that have activesync enabled and list all of the connections. Many users have multiple entries where they have used a phone and upgraded, or re-enabled after a wipe.
I am looking to get rid of any entry above 30 days, only for users in a specific OU, or text file full of users.
I believe this code will work universally across the domain:
$DevicesToRemove = Get-ActiveSyncDevice -result unlimited | Get-ActiveSyncDeviceStatistics | where {$_.LastSuccessSync -le (Get-Date).AddDays("-30")}
$DevicesToRemove | foreach-object {Remove-ActiveSyncDevice ([string]$_.Guid) -confirm:$false}
but I only want to do it for either an OU, or txt list.
I can create a .txt list of either the UPN, or the username, which may be easier than looking for all users in an OU. How would I modify that code (or altogether better code?) to remove 30 day+ activesync connections for that txt list?
Text file option would be preferred for a better target.

I think I self answered, so posting for others.
“==============================================================”
“Start Mailbox Retrieve”
“==============================================================”
$mbx = get-casmailbox -resultsize unlimited | where {$_.activesyncenabled -eq $true} ;
“==============================================================”
“End Mailbox Retrieve”
“==============================================================”
$mbx | foreach {
“Processing: “+$_.name
$name = $_.name;
$device = get-activesyncdevicestatistics -mailbox $_.identity | where {$_.LastSuccessSync -le (Get-Date).AddDays(“-30”)};
if($device){
{
”
Device: “+$dev.DeviceType
$csvRows += $dev
}
}
}
“==============================================================”
“Start CSV Write”
“==============================================================”
$csvRows | Export-Csv “c:\ps\staledevices.csv” -NoType
“==============================================================”
“End CSV Write”
“==============================================================”
From http://techtalklive.org/ttlblog/removing-stale-activesync-devices/
Then to remove:
Import-Csv c:\ps\staledevices.csv |foreach {remove-activesyncdevice -identity $_.guid -confirm:$false}
From http://techtalklive.org/ttlblog/removing-stale-activesync-devices/

Related

output all mailboxes with inbox rules

I am trying to get a list of all Exchange mailboxes that have inbox rules. I am able to get a list of all mailboxes and a count of how many rules each mailbox has. I am trying to skip or have no output for mailboxes with zero rules.
$mailboxes = get-mailbox
foreach ($mailbox in $mailboxes) {
Write-Output $mailbox.id,((Get-InboxRule -Mailbox $mailbox.id)| Measure-Object | select count)
}
Current code outputs:
User1
0
User2
11
User3
0
User4
1
User5
0
etc....
I am looking to only output user's who have inbox rules.
Thanks-
#!/usr/bin/env powershell
get-mailbox -resultsize unlimited |
ForEach-Object {
Write-Output -Message ('Checking {0}...' -f $_.alias) -Verbose
$inboxrule = get-inboxrule -Mailbox $_.alias
if ($inboxrule) {
foreach($rule in $inboxrule){
New-Object -TypeName PSObject -Property #{
Mailbox = $_.alias
## you could uncomment this if you wanted more information
##Rulename = $rule.name
##Rulepriority = $rule.priority
##Ruledescription = $rule.description
}
}
}
} |
Export-csv -Path "$env:userprofile/desktop/export.csv" -NoTypeInformation
This should give you a list of just the users who have rules.
Not exactly sure what your expected is but to answer how to exclude those mailboxes with no inbox rules:
foreach($mailbox in Get-Mailbox) {
$ibxrules = #(Get-InboxRule $mailbox.Id).Count
if($ibxrules -eq 0) {
continue
}
[pscustomobject]#{
MailboxId = $mailbox.Id
InboxRules = $ibxrules
}
}
To explain the use of #(...) around Get-InboxRule, this is to ensure the output is always an array, and this also ensures we can always get a .Count out of it.

Get the Last Logon Time for Each User Profile

I need to get the last logon time for each user profile on a remote computer (not the local accounts). I've tried something similar to the following using Win32_UserProfile & LastLogonTime, however this is not giving accurate results. For example, one this computer, only 1 account has been used in the past year, however LastUpdateTime is showing very recent dates. Some accounts have not even been logged into and should say "N/A", but it doesn't.
$RemoteSB_UserADID = Get-WmiObject win32_userprofile -Property * | Where-Object {$_.LocalPath -like "*users*"} | Sort-Object $_.LastUseTime | ForEach-Object{
$Parts = $_.LocalPath.Split("\")
$ADID = $Parts[$Parts.Length - 1]
if ($ADID -ne "SPECIALPURPOSEACCOUNT1" -and $ADID -ne "SPECIALPURPOSEACCOUNT2"){
$Time = $null
try{
$Time = $_.ConvertToDateTime($_.LastUseTime)
}catch{
$Time = "N/A"
}
"[$ADID | $Time]"
}
}
Example Output
[Acct1 | 03/13/2022 07:18:19]
[Acct2 | 03/15/202214:59:16]
[Acct3 | 03/13/2022 07:18:19]
[Acct4 | 03/16/2022 11:53:17] <--- only "active" account
How can I go about retrieving accurate (or decently accurate) login times for each user profile? Thanks!
It would help to know for what reason you need that, so that I know how to find a (better) solution for you.
If you need to cleanup your profiles not used for a long time at the target system, then take the last changed date of "ntuser.dat". That is the last logon if you define logon like logging on to a new session. If the user was logged on and simply locked the computer or used standby and then relogs then this date won't change.
Use this to get this date from all users you have access to but possibly not getting real user names
Get-ChildItem \\REMOTECOMPUTERNAMEHERE\Users\*\ntuser.dat -Attributes Hidden,Archive | Select #{Name="NameByFolder";Expression={($_.DirectoryName -split "\\")[-1]}},LastWriteTime
Or this a bit more complex version
Invoke-Command -ComputerName REMOTECOMPUTERNAMEHERE -ScriptBlock {$UsersWithProfilePath = #{}
dir "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" |
where {$_.name -like "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-*"} |
foreach {$UsersWithProfilePath[([System.Security.Principal.SecurityIdentifier]$_.name.split("\")[-1]).Translate( [System.Security.Principal.NTAccount]).Value] = $_.GetValue("ProfileImagePath")}
foreach ($Name in $UsersWithProfilePath.Keys) {#{$Name =(dir (join-path $UsersWithProfilePath.$Name ntuser.dat) -Attributes Hidden,Archive,System).LastWriteTime}}}
Depending on what you need you need to change it a bit.
Sorry for the long codelines... it is late here.

how to get exact user name from get-mobiledevicestatistics in powershell

I have a small script to get all user mobile devices info from exchange 2013 server.
Get-Mailbox -ResultSize Unlimited |
ForEach {Get-MobileDeviceStatistics -Mailbox:$_.Identity} |
Select-Object #{label="User" ; expression={$_.Identity}},DeviceOS, lastsuccesssync
I just want to get an exact user name instead of a path in AD. How can I do it in expression={?}
Here is another script to do it, it gives me the user name, but all devices belongs to user are not in separated lines, they all in one line...
$EASMailboxes = Get-CASMailbox -Filter {HasActiveSyncDevicePartnership -eq $True -and DisplayName -notlike "CAS_{*"} | Get-Mailbox
$EASMailboxes | Select-Object DisplayName, PrimarySMTPAddress, #{Name="Mobile Devices";Expression={(Get-MobileDeviceStatistics -Mailbox $_.Identity).DeviceOS}} |
Out-GridView
I don't have the environment to test this but is this not what you are looking for ?
Get-Mailbox -ResultSize Unlimited | ForEach {
$user = $_.SamAccountName
Get-MobileDeviceStatistics -Mailbox:$_.Identity |
Select-Object #{label="User" ; expression={$user}},DeviceOS, lastsuccesssync
}
That should output the user for every device they own on its own line. You could then easily export this to Export-CSV or some such thing that way.
We save the $user so it is available later in the pipe. Could also have used Add-Member but the result would have been the same.
If you have the identity field, which looks like this
domain.com/Users/OU/UserName/ExchangeActiveSyncDevices/iPhone
Then to split on the / and get the third result, you simply request:
$_.Identity.Split("/")[3]
>UserName
PowerShell begins indexing with number zero, so to request the fourth entry in the list, we request index number 3.
Update
OP mentioned that the OU level might vary, meaning that he couldn't count on a fixed position to request the Index. In order to accomodte that scenario, try this method, which will look for the index of ExchangeActiveSyncDevices and then pick the index position before that.
$_.Identity.Split('/')[($_.Identity.Split('/').Indexof('ExchangeActiveSyncDevices')-1)]
Get-Mailbox -resultsize unlimited|foreach {Get-MobileDeviceStatistics -Mailbox:$_.identity} |Select-Object #{l="user";e={$_.Identity.parent.parent.name}}, lastsuccesssync
on e2k13

Verify Domain Admins against List via AD Module for PowerShell

I have an issue of certain administrators temporarily elevating users to Domain Admins for troubleshooting. Instead of removing said administrators from the picture, I have been asked to create a script to check the Domain Admins group nightly, and remove any users that do not belong there.
I need it to verify the Domain Admins group against a givin list in txt or csv. I could delete everone from the group nightly, then readd the desired users back, but this could create issues if someone is logging in or logging off when that happens.
Can anyone help with this? So far I have managed to export a list of users within the group by piping get-adgroup and export-csv. But I'm failing in my attempt to get the list of users and compare to an already existing list.
Here's a little script I just wrote for you. First you need to make a default text file with the default members. I named my file PreviousMembers.txt
Import-Module ActiveDirectory
Get-AdGroupMember "Domain Admins" | Select Name | Out-File C:\Scripts\PreviousMembers.txt
Now, save the following lines in ADGroupMembersDiff.ps1 and run it any time to get a current list of members. You'll need to make sure the files are in the same location that you specify below and the file names need to be the same, too.
Import-Module ActiveDirectory
$pattern = ".*"
Get-AdGroupMember "Administrators" | Select Name | Out-File C:\Scripts\CurrentMembers.txt
(Get-Content C:\Scripts\CurrentMembers.txt) | ? {$_.trim() -ne "Name" -and $_.trim() -ne "----" -and $_.trim() -ne "" } | Set-Content C:\Scripts\CurrentMembers.txt
(Get-Content C:\Scripts\PreviousMembers.txt) | ? {$_.trim() -ne "Name" -and $_.trim() -ne "----" -and $_.trim() -ne "" } | Set-Content C:\Scripts\PreviousMembers.txt
$comparedLines = Compare-Object (Get-Content C:\Scripts\PreviousMembers.txt) (Get-Content C:\Scripts\CurrentMembers.txt) -IncludeEqual | Sort-Object { $_.InputObject.ReadCount }
$lineNumber = 0
$comparedLines | foreach {
if($_.SideIndicator -eq "==" -or $_.SideIndicator -eq "=>")
{
$lineNumber = $_.InputObject.ReadCount
}
if($_.InputObject -match $pattern)
{
if($_.SideIndicator -eq "==")
{
$lineOperation = "No Change"
}
ElseIf($_.SideIndicator -eq "=>")
{
$lineOperation = "New User"
}
Elseif($_.SideIndicator -eq "<=")
{
$lineOperation = "Default User"
}
$HashChanges = #{
Line = $lineNumber
Operation = $lineOperation
Users = $_.InputObject
}
New-Object psobject -Property $HashChanges | select Users, Operation
}
}
Here's what the output will look like.
Users Operation
_____ ______
John Hancock New User
Thomas Edison Default User
George Washington New User
Thomas Jefferson No Change
Good Luck,
T|CK
MJOLINOR had the perfect suggestion. Here are some details about Restricted Groups...
By creating a Restricted Group GPO and linking it to the Domain Controllers OU, I have been able to add my desired group to the newly created GPO, tell that GPO which users belong in the desired group, and now, every 16 hours my desired group (Domain Admins) will be verified against the new GPO. So if users are members that are not part of the new GPO, they will be removed, and if users have been removed that are part of the new GPO, they will be added.
Thank you! And I hope this helps someone else.
I have only ever used Restricted groups to modify the memberships of local groups on client computers. I have never used it to modify the memberships of domain groups. In fact, Microsoft states that the intention of Restricted Group is not for Domain groups.
...Restricted Groups is a client configuration means and cannot be used with Domain Groups...

Exchange 2010 TotalItemSize.Value.ToBytes() always empty

I'm trying to create simple reports on Exchange 2010 mailbox size.
While this works:
Get-MailboxStatistics -server <serverfqdn> |ft displayname, TotalItemSize
this doesn't (second column stays empty):
Get-MailboxStatistics -server <serverfqdn> |ft displayname, {$_.TotalItemSize.Value.ToBytes()}
The problem is that I need the size as an integer, so the first line of code doesn't serve my purpose.
According to several websites the second line of code should work but unfortunately doesn't on my machine.
I know I could parse the value after using the first line but that would be unnecessarily inefficient, wouldn't it? :-)
Hope anyone can help.
Regards,
Kevin
If performing from a imported PS session the methods .ToMB() is lost as the type becomes a custom object.
The $variable.TotalItemSize.Value becomes a two element array [0] in KB,MB or GB and [1] always in bytes.
So to use this we can play with strings to achieve what we want.. in long hand for clarity
$mailboxes = Get-Mailbox -Filter{(RecipientType -eq "UserMailbox") -and (CustomAttribute12 -eq "whatever")}
foreach ($mailbox in $mailboxes)
{
$size1 = Get-MailboxStatistics $mailbox.id
[string]$bob = $size1.TotalItemSize.Value
[int]$bill = $bob.TrimEnd(" bytes)").Split("(")[1] # The bytes part of the array.
$bill = $bill/1mb # Convert into MB's
if ($bill -le 1500) {do something} Else {"Too Big " + $bill} # note -le 1500 NOT 1500MB
}
I hope this helps
this worked for me
$a = get-mailbox -id user | Get-MailboxStatistics
$a.TotalItemSize.Value.ToMB()
$a.TotalItemSize.Value.ToKB()
I have the same issue. I'm not sure if you resolved this.
I have this, which is quite ugly - but works:
$a = get-mailbox USER | get-mailboxstatistics
$intTotalItemSize = [int]$a.TotalItemSize.SubString($a.TotalItemSize.indexof("(")+1, $a.TotalItemSize.indexof(" b")-$a.TotalItemSize.indexof("("))
Try this for your size expression:
#{expression={$_.TotalItemSize.Value.ToMB()};label="Mailbox Size(MB)"}
I believe there is also a ToKB() method.
MVP Shay Levy has delved into this on his blog (http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2011/08/22/get-full-control-over-your-exchange-remote-powershell-session.aspx).
Basically, you have to modify a setting in the PowerShell virtual directory on the server that you are remoting to.
This is great news for those who are remoting to Exchange servers that they have this kind of control over, but is not helpful for those of us who use hosted Exchange solutions and cannot change these settings. I suppose we will just have to abandon some of the uber-coolness of PowerShell and go back to parsing the string to get the bytes and convert from there.
--EDIT--
This is how I tackled outputting a file of all of my users' mailbox sizes. It could be compressed a bit further, but is a little more readable this way.
$allMailboxes = Get-Mailbox -ResultSize Unlimited
ForEach ( $mailbox in $allMailboxes ) {
$itemSizeString = ( Get-MailboxStatistics $mailbox.Identity ).TotalItemSize.Value.ToString()
$posOpenParen = $itemSizeString.IndexOf("(") + 1
$numCharsInSize = $itemSizeString.IndexOf(" bytes") - $posOpenParen
$mailboxSizeInBytes = $itemSizeString.SubString($posOpenParen,$numCharsInSize).Replace(",","")
Write-Output "$($mailbox.alias),$($mailboxSizeInBytes)"
}
Please, see this article: http://blogs.technet.com/b/gary/archive/2010/02/20/the-get-mailboxstatistics-cmdlet-the-totalitemsize-property-and-that-pesky-little-b.aspx
Get-Mailbox | Get-MailboxStatistics | Add-Member -MemberType ScriptProperty -Name TotalItemSizeinMB -Value {$this.totalitemsize.value.ToMB()} -PassThru | Format-Table DisplayName,TotalItem*
I needed to have this work outside of a remoting session, so I simplified the answer from Greybear to this:
$a = get-mailbox USER | get-mailboxstatistics
$intTotalItemSize = [int64]($a.TotalItemSize -split '[\( ]')[3]
Or in the format of the original question::
Get-MailboxStatistics -Server <serverfqdn> | Select-Object -Property DisplayName,#{label="TotalItemSize";expression={[int64]($_.TotalItemSize -split '[\( ]')[3]}} | ft
Realized that [int] would fail for mailboxes over 4GB, so changed to [int64]. Alternately, display the mailboxes in MB:
Get-MailboxStatistics -Server <serverfqdn> | Select-Object -Property DisplayName,#{label="TotalItemSize";expression={[int64](([int64]($_.TotalItemSize -split '[\( ]')[3])/1048576)}} | ft
The name needs to go before the expression. This will work.
Get-MailboxStatistics -Identity [name] | select #{label=”User”;expression={$_.DisplayName}},lastlogontime,#{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}
This works for me
#{Name="TotalSize (MB)"; Expression={((($_.TotalItemSize) -split " ")[0])}}
You might try:
get-mailbox -resultsize unlimited | Get-MailboxStatistics | ft displayname,#{label="Total Size (MB)";expression={$_.TotalItemSize.Value.ToMB()}}