Removing samaccountname from group after N time - powershell - powershell

I am looking to find a way to remove a user from a group after a specific amount of time.
Via the below link I found that you can find users that were added with 10 days or more:
https://gallery.technet.microsoft.com/scriptcenter/Find-the-time-a-user-was-a0bfc0cf#content
As an output I get the example below:
ModifiedCount : 2
DomainController : DC3
LastModified : 5/4/2013 6:48:06 PM
Username : joesmith
State : ABSENT
Group : CN=Domain Admins,CN=Users,DC=Domain,DC=Com
I would like to return SamAccountName instead of Username.
I was trying to look at code and I know this is something to do with the variable $pattern But I am not that good in powershell to know at first sight.

Looking at that code, the Username property IS the SamAccountName.
However, if you want to change that label, you can either simply change it on line 106 from
Username = [regex]::Matches($rep.context.postcontext,"CN=(?<Username>.*?),.*") | ForEach {$_.Groups['Username'].Value}
into:
SamAccountName = [regex]::Matches($rep.context.postcontext,"CN=(?<Username>.*?),.*") | ForEach {$_.Groups['Username'].Value}
Or change the label in the objects returned afterwards with a calculated property:
$returnedObjects | Select-Object #{Name = 'SamAccountName'; Expression = {$_.Username}}, * -ExcludeProperty Username

Related

Concatenate string with object in Powershell

Currently I want to get a list of active user on Windows 10 using Powershell.
After some searching I found this helps:
Get-LocalUser | Where-Object -Property Enabled -eq True
And here is the output:
Name Enabled Description
---- ------- -----------
User_1 True
User_2 True
I just want to concatenate strings to a list of values of Name column from above, which will be like below:
Active user(s): User_1, User_2
Do you have any idea how I can do that? I'm just a non-tech guy trying to learn some useful command so forgive me if this is a basic to you.
You can do the following:
# Retrieve the name values
$Users = Get-LocalUser |
Where-Object Enabled -eq True | Select-Object -Expand Name
# Create the output string
"Active user(s): {0}" -f ($Users -join ', ')
Using -Expand (or -ExpandProperty) from Select-Object, the target property's value is returned rather than the object that contains the property.
-f is the string format operator. It uses substitution for the {position} syntax. The -join operator creates a string from a list with , as the delimiter.

Powershell export Active Directory User data not complete

I have to export the user data of accounts before we delete them. The problem is, that not all group memberships are written in the .txt file (example below).
This is the code:
Get-ADUser -Properties * -Filter "cn -eq '$name'" |
format-list -property #{Label = "Name";Expression = {$_.sAMAccountName}},
#{Label = "Initials";Expression = {$_.initials}},
#{Label = "Email";Expression = {$_.Mail}},
#{Label = "Groups";Expression = {%{(Get-ADPrincipalGroupMembership $name | select -expandproperty name)}}},
#{Label = "Creation";Expression = {$_.whenCreated}},
#{Label = "Deletion";Expression = {%{(Get-Date)}}},
#{Label = "Last change";Expression = {$_.whenChanged}} |
#write data into txt file
Out-File -append "C:\temp\deleted.txt" -Encoding utf8
And this is the output:
Name : John Doe
Initials : Jdo
Email : John.Doe#acme.com
Groups : {Domain-User, Remotedesktopuser, Administrator, Share-User...}
Creation : 23.03.2018 13:36:44
Deletion : 17.12.2018 08:46:30
Last Change : 16.12.2018 10:42:21
It's really not the Format-List causing this, the same thing would happen with a select, though using Format-* like this is not really a thing. This will be a list by default, so, no real reason to use it for what you are after.
You don't even need that expand.
The issue is the fact that you cannot use that loop and expect that to work, the auto formatters won't allow it. You have to directly handle the collection, something like this...
Get-ADUser -Properties * -Filter * |
Select-Object -property #{Label = "Name";Expression = {$_.sAMAccountName}},
#{Label = "Initials";Expression = {$_.initials}},
#{Label = "Email";Expression = {$_.Mail}},
#{Label = "Creation";Expression = {$_.whenCreated}},
#{Label = "Deletion";Expression = {%{(Get-Date)}}},
#{Label = "Last change";Expression = {$_.whenChanged}},
#{Label = "Groups";Expression = {%{(Get-ADPrincipalGroupMembership $_.SamAccountName).Name -join ','}}} |
Out-File -append "C:\temp\deleted.txt" -Encoding utf8
Get-Content -Path "C:\temp\deleted.txt"
# Results
Name : Administrator
Initials :
Email : Administrator#contoso.com
Creation : 3/31/2017 8:02:15 PM
Deletion : 12/17/2018 4:07:52 AM
Last change : 12/9/2018 7:23:22 PM
Groups : Domain Users,Administrators,Schema Admins,Enterprise Admins,Domain Admins,Group Policy Creator Owners,Organization Management,Recipient
Management,ADSyncAdmins,ADRMSSuperUsers
…
Update as per the OP comment / question
No worries, glad it worked for you.
As for ...
Would you mind to explain me what the difference between that two AD
Group commands are?
If you mean ...
Get-ADPrincipalGroupMembership Administrator | select -expandproperty
name
... vs ...
(Get-ADPrincipalGroupMembership Administrator).Name
... they are ostensibly the same thing, each producing and array list of group names.
# use the expand switch to show the group name list
Get-ADPrincipalGroupMembership Administrator | select -expandproperty name
Domain Users
Administrators
Schema Admins
Enterprise Admins
Domain Admins
Group Policy Creator Owners
Organization Management
Recipient Management
ADSyncAdmins
ADRMSSuperUsers
# Use the property to view the group name list
(Get-ADPrincipalGroupMembership Administrator).Name
Domain Users
Administrators
Schema Admins
Enterprise Admins
Domain Admins
Group Policy Creator Owners
Organization Management
Recipient Management
ADSyncAdmins
ADRMSSuperUsers
However, the formatters, when the data is being serialized, will try to put this all on one line. Yet, they will truncate this to fit the screen / page width.
So, if you want a different layout, then either you need to go in and muck with the default formatter files, or handle it is code. Personally, I never try to mess with them, and just work to handle it in code. So, this...
(Get-ADPrincipalGroupMembership Administrator).Name -join ','
... just says, I know this collection is an array list. I know that this will get truncated per screen/page width, so, concatenate this list of strings as one string and autowrap.
You could have done the same thing with your original expand the same way ...
(Get-ADPrincipalGroupMembership Administrator | select -expandproperty name) -join ','
I stuck the groups list at the end for aesthetic reasons as well as the shorter form, as I prefer not writing unnecessary code or using unneeded options as much as possible. Everyone has their preferences.

adding variable to format list output

I have a question about adding a variable to the output of format-list. When I run the command:
get-CsAdUser | Format-List DisplayName, Enabled
I get the output
DisplayName : user01
Enabled : True
DisplayName : user02
Enabled : False
I have a variable $var1 = "folder one" that I need to add to the output so it looks like :
DisplayName : user01
Enabled : True
folder one
DisplayName : user02
Enabled : False
folder one
Anyone have an idea on how to do this? Thanks
On a meta note:
PetSerAl, as he often does, has provided an effective answer in a comment.
However, it is preferable to have an actual answer post that can be marked as accepted so as to signal to future readers what solution truly solved the OP's problem.
As PetSerAl notes:
get-CsAdUser | Format-List DisplayName, Enabled, #{Label = 'Folder'; Expression = {$var1}}
adds a third property to each input object's output that prints the value of variable $var1 as an ad-hoc, calculated property named Folder, following the preexisting DisplayName and Enabled properties.
The #{ Label = ...; Expression = ... } part of the command is a PowerShell hashtable literal that is an instance of a calculated property, which you can use with Select-Object, Format-Table, and Format-List, as described in this answer of mine.

Removing PowerCLI list truncation

I have the following snippet
Get-VM | select name, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }} | Format-List
This outputs a fantastic list of servers and IP addresses however i notice some iPV6 addresses are truncated.
Name : eg.example.com
IP Addresses : {192.168.100.18, 2a03:2658:1068:0:250:56ff:feaf:593f, fe80::2504:56ff:feaf:593f, 192.168.100.1...}
How can I expand this to output all address space? I have tried using -ExpandProperty but this seems to fail.
Join the elements of the list to a string:
... | select name, #{n='IP Addresses';e={$_.Guest.IPAddress -join ', '}} | ...
The data is there but PowerShell has truncated it on screen by only showing you the first 4 elements in the IP Addresses property array. If you want to leave the property as an array you could change the preference variable for $FormatEnumerationLimit. By default it is 4.
$FormatEnumerationLimit = -1
That will force it to display the entire array on screen. It would be a good idea to save the value before you change it in case you need to reverse.
$savedValue = $FormatEnumerationLimit

Powershell - keep specific word in a string

I'm doing AD extract and I sort the field "distinguishedname" and I want to keep only a specific part of the value that represent the "parent OU" of the user itself.
I'm running this command to do an add extract of all users:
import-module activedirectory
get-aduser -filter * -properties *| Select-Object -Property SamAccountName,CN,co,ExtensionAttribute10,extensionAttribute11,extensionAttribute12,EmailAddress,whenCreated,Enabled,LastLogonDate,accountexpirationdate,distinguishedname |Sort-Object -Property Name | Export-Csv -Delimiter ";" -path "u:\theOutFile_NOFILTER_July.txt"
The column "distinguishedname" look like this:
distinguishedname
CN=familly\, user,OU=Remote Users,OU=New York,OU=My,DC=Company,DC=Local
CN=nameless\, cat,OU=Remote Users,OU=Ottawa,OU=My,DC=Company,DC=Local
CN=Cameron\, James,OU=Regular Users,OU=Hollywood,OU=My,DC=Company,DC=Local
CN=Bon\, Jean,OU=regular Users,OU=Springfield,OU=My,DC=Company,DC=Local
Note July 10
some time I will hit those line:
CN=Dog\, Cesar,OU=Special Accounts,OU=Regular Users,OU=Alma,OU=My,DC=Company,DC=Local
CN=keys\, Alicia,OU=Special Accounts,OU=Regular Users,OU=Paris,OU=My,DC=Company,DC=Local
CN=Clansy\, Door,OU=Map Drives,OU=Remote Users,OU=Rome,OU=My,DC=Company,DC=Local
In those case I am getting result such Remote Users an Regular Users instead of the City. I've tried some modification in your command you gave but in vain.
But I would like the first command to return this result instead:
distinguishedname
New York
Ottawa
Hollywood
Springfield
I can't effort to find how.
thanks in advance
Select-Object has a very versatile feature to create calculated properties using a hash in the place of a property name, where the key "Name" is set to the name of the calculated property (effectively, the column heading), and "Expression" is set to a code block that determines the value of the property, for each object in the pipeline. This will do what you want:
Get-Aduser -Filter * -Properties * | Select-Object -Property SamAccountName,CN,co,ExtensionAttribute10,extensionAttribute11,extensionAttribute12,EmailAddress,whenCreated,Enabled,LastLogonDate,accountexpirationdate,#{Name='distinguishedname'; Expression={[regex]::match($_.distinguishedname,'OU=.+?OU=(.+?),(OU|DC)=').Groups[1].Value}} | Sort-Object -Property Name | Export-Csv -Delimiter ";" -Path "u:\theOutFile_NOFILTER_July.txt"
Here's a breakdown what's going on:
Name='distinguishedname' tells it to create a new column called 'distinguishedname'. I used that name to match your example of the output you're looking for, but it doesn't have to be the name of an existing property. It would probably make more sense to change the name to something more descriptive of the values you're calculating, e.g. Name="parentOU".
[regex]::match is used to extract the desired portion from $_.distinguishedname using the regular expression OU=.+?OU=(.+?),(OU|DC)=, which isolates the name of the second OU in the list using a match group.
.Groups[1].Value returns the value of the first match group (the part matched by the contents of the first set of parentheses). .Value on its own without .Groups[1] would return the entire matched string, from the first OU= to the = following name of the parent OU. The following would work just as well, using zero-width assertions instead of a match group: [regex]::match($_.distinguishedname,'(?<=OU=.+?OU=).+?(?=,(OU|DC)=)').Value