Out-File won't display what powershell ISE shows - powershell

Ok, so I'm a beginner in Powershell.
I'm at work so I wanted to auto some things. My work with this script is to select those specific users and their password expiration date, format the date to be human readable and then save all that in a txt file to be analized.
My current code is this:
$List = Get-Content D:\Users\c05896\Desktop\VIPS.txt
$Users = #()
foreach ($Item in $List){
$Users += Get-ADUser -Filter * -Properties "msDSUserPasswordExpiryTimeComputed"| where {$_.Name -like "*$Item*"}}
$Users | Sort-Object | Select-Object Name, #{Name="Password expires";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed" )}}
Out-File -filepath D:\Users\c05896\Desktop\VIPLista.txt -InputObject $Users
So, the script above is what I wrote.
The output WITHIN the Powershell ISE is at follows:
Name Password expires
---- ---------------
User 1 10/11/2010 01:39:53 p.m.
User 2 21/10/2018 10:21:43 a.m.
User 3 21/10/2018 08:38:23 a.m.
. .
. .
. .
That's what I want to output in the txt file, but instead I got this format:
DistinguishedName : CN=USER LASTNAME
OU=VIPs,OU=Users
Enabled : False
GivenName : USER LASTNAME
msDS-UserPasswordExpiryTimeComputed : 129192702049912335
Name : USER
ObjectClass : user
ObjectGUID : bb033273-6117-470b-9f07-aee2885a45bc
SamAccountName : B00057
SID : S-1-5-21-808411757-1154953693-317593308-27012
Surname : USER
UserPrincipalName : XXXXX
I erased all names and lastnames just for privacy.
So, the question is what can I do to get the Out-File to display the information as it shows on Powershell ISE?
Thank you very much for your answers

# --> $Users = $Users | ...
$Users = $Users | Sort-Object | Select-Object Name, #{Name="Password expires";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed" )}}
Out-File -filepath D:\Users\c05896\Desktop\VIPLista.txt -InputObject $Users
# or
# combine ISE output with file output in one command using Tee-Object
$Users | Sort-Object |
Select-Object Name, #{Name="Password expires";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed" )}} |
Tee-Object -FilePath D:\Users\c05896\Desktop\VIPLista.txt

Nas has a good answer for you regarding how to meet your objective. I'm going to try to answer the why.
When you used Get-ADUser to retrieve your user objects a number of properties are returned by default. You were aware of that and used Select-Object to select which attributes to return and you even added a new custom attribute.
The Select-Object output is what displayed in the ISE (and would have displayed in a console if you weren't using the ISE as well).
What you did not do is actually modify the objects that were stored in the $Users array so when you sent those objects to Out-File it received all the attributes of the objects.
Both of the options that Nas gives you above modify the objects in $Users while they are in the pipeline so that when they are sent to Out-File only the attributes you wanted to output to the file are remaining. His first example actually replaces the original $Users array with a new $Users array so that if you subsequently examine it, only your specified attributes will remain. In his second example, using Tee-Object, $Users still remains unmodified and if you examined the objects you would see that they still retain DistinguishedName, Enabled, GivenName, etc.

Related

Powershell script : read and insert value from txt file (on 30+ entry)

Sorry, i'm noob for powershell, but want to automate the following:
Got a powershell script:
import-module ActiveDirectory
$username = Read-Host 'Please enter Username!'
Get-ADPrincipalGroupMembership $username | Get-ADGroup -Properties * | select name, description
When run script i enter the username and it give me a list which group the user is member of.
I had a big 50-100 list user list which obtained with Get-aduser -filter * -properties Name | select-object Name | out-file -filepath .\userlist.txt command and saved to a text file.
Is there any way to read every user 1 by 1 and auto fill the username field, then save the output to a text file? when finished with the 1st, script rerun and read the next value.
Is that possible?
Thank you
Here's a few snippets to help you put together what you need.
Get all users from a file containing only usernames
[string[]]$allUsers = Get-Content -Path '.\FileWithUsernames.txt'
Get all active users from AD
[string[]]$allUsers = Get-AdUser -Filter "enabled -eq 'True'" | Select-Object -ExpandProperty 'SAMAccountName'
Loop through users getting the users' group info / doing something with it
foreach ($user in $allUsers) {
Get-AdUser -Identity $user -Properties 'memberof' |
Select-Object -ExpandProperty 'memberof' |
ForEach-Object {
([PSCustomObject]#{ Username=$user; GroupDN = $_})
} |
Export-Csv -Path '.\AllActiveUsersGroups.csv' -Append -Delimiter ',' -Encoding 'Utf8' #-NoTypeInformation #only include the -notypeinfomrmation parameter if using PS rather than PWSH)
}

Allocating values to specific csv columns in Powershell

I'd like to ask if anybody can please advise a way how to allocate a value in variable to a column in csv.
For example:
TriggeredBy | TriggeredTime | Firstname | Lastname | Username | ....
Throughout my script I'm modifying input data and on the go I'd like it to fill in the row to the relevant column.
Then another script from a different server has to take over, read the calculated values and add its calculated results into its dedicated columns.
The output would be a row where I can see that all the results.
In the end it's supposed to serve as a sort of database.
Sample of script here would be:
$aduser = Get-ADUser -Filter {sAMAccountName -like $username} -Properties *
$Firstname = $aduser.GivenName
$Firstname | Export-CSV -Path $filepath | Select-Object "First Name"
$Lastname = $aduser.Surname
$Lastname | Export-CSV -Path $filepath | Select-Object "Last Name"
$TriggeredBy = $env:UserName
$TriggeredBy | Export-CSV - Path $filepath | Select-Object "TriggeredBy"
...
Throughout the process all saved in one relevant row. Next process does the same for the following row etc...
The "Export-CSV ...." part is obviously wrong, I would need some alternative
Many thanks!
Use Select-Object with calculated properties:
Get-ADUser -Properties * -Filter "sAMAccountName -eq `"$username`"" | #`
Select-Object #{ n='FirstName'; e='GivenName' },
#{ n='Last Name'; e='Surname' },
#{ n='TriggeredBy'; e={ $env:UserName } } |
Export-Csv -NoTypeInformation -Literalpath $filePath
Note that I've used a string as the -Filter argument, because that's what it ultimately becomes anyway. Using script-block literal syntax { ... } is tempting, but ultimately causes more problems than it solves - see this answer.
Note that in Windows PowerShell Export-Csv creates ASCII(!)-encoded files by default, which can result in loss of information; use the -Encoding parameter to change that.
PowerShell [Core] v6+, by contrast, commendably defaults to (BOM-less) UTF-8; also, the
-NoTypeInformation switch is no longer necessary there.
If you want to append to an existing CSV file (which needs to have the same column structure), use the -Append switch.

Passing results to a -like filter in PowerShell

I am trying to create a script to take care of a repetitive task I have. Basically I need to get the person's ID that manages a particular folder.
My first script tells me the various security groups assigned to a specified folder. The second script takes a specified AD group and tells me who manages it. Ideally I want to just run the script, input my folder name and have it tell me who manages the various AD groups assigned. I can then go and do the rest. But I am having an issue with the output of the first script. I have it so it displays in the console correctly, but I cannot figure out how to get those results into the filter in the second script.
Script one:
$FN = Read-Host -Prompt "Please enter Folder name"
$ADG = (Get-Acl $FN).Access |
Select IdentityReference |
Where-Object IdentityReference -like '*SL*'
foreach ($ACL in $ADG) {
$Group.Fullname + ($ACL.IdentityReference.Value.Split('\'))[1] | Out-String
}
Script two:
Get-ADGroup -Filter {Name -like "use output here"} -Properties managedby |
Select managedby
I would be most appreciative of any assistance. ESPECIALLY if I am barking up the wrong PowerShell command! My first foray into using multiple queries in a script.
It's not quite clear to me what the $Group.Fullname + (...)[1] | Out-String is supposed to do, but assuming that you want to run the second command for each identity reference from your first command you could do something like this:
Get-Acl $FN |
Select-Object -Expand Access |
Select-Object -Expand IdentityReference |
Where-Object { $_.Value -like '*SL*' } |
ForEach-Object {
$name = $_.Value.Split('\', 2)[-1]
Get-ADGroup -Filter "Name -like '*${name}*'" -Property ManagedBy
} |
Select-Object -Expand ManagedBy |
Get-ADUser

How do I get Powershell to output Get-ADUser -Filter * as comma delimited?

I have a simple Powershell script that I want to use to grab all the users in AD and show specific properties. Here is the heart of my script:
$id = "*"
Get-ADUser -Filter {SAMAccountName -like $id} -Properties * | Select-Object -Property SAMAccountName,Name,PasswordNeverExpires,LockedOut,PasswordLastSet,LastLogOnDate,CanonicalName
The full script has an input parameter to set $id so that it can be a single ID, a list of IDs (such as "bsmith, jdoe, gmanning"), or * to get all accounts.
Here's my problem: When using, *, I need this to output as comma delimited.
Here's the catch: The output cannot be to a CSV file--or any other type of file.
The reason being is that I'm writing this script to be used on N-Enable's N-Central monitoring suite of software. You don't need to know N-Central to help with my problem, just understand that N-Central uses its own software to run Powershell scripts on clients and returns the results into a txt file that cannot be changed to a csv file (or formatted in any other way than what it has hard-coded).
What this means is that my results have to either be what would show up on the screen or in a variable (such as $results=Get-ADUser -Filter * ....). I cannot output to any type of file, which leaves out Export-CSV as an option.
I've tried other types of formatting to no avail (such as with -f). The issue seems to be with the way Powershell grabs all AD Users using the * wildcard. It seems to grab them all as one big object, so I am unable to get my output to have a comma between all the properties so that I get a comma-delimited output. Thus, when I get the results back from N-Central as a .txt file, all the data is there, but there are no commas in between the properties for me to then open the .txt file as comma-delimited in Excel (or tab-delimited for that matter).
Does anyone have a solution that will allow me to format Get-ADUser -filter * so that it is comma-delimited without using export to file?
UPDATE: Ok, I thought I was keeping things easy by not posting my full script but it seems I've done the opposite. So, below is my full script. Anyone should be able to run this to see the results:
function Get-ADUserInfo
{
[CmdletBinding()]
param(
#[Parameter(Mandatory=$True)]
[string[]]$Users= '*'
)
Begin {
$maxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.Days
$Headers="ID, Name, Password Never Expires?, Locked Out, Password Last Set, Expiry Date, Last Logon Date, OU Path"
}
Process {
foreach ($id in $Users)
{
$results=Get-ADUser -Filter {SAMAccountName -like $id} -Properties * | select -property SAMAccountName,Name, PasswordNeverExpires,LockedOut,PasswordLastSet,(#{Expression={$_.PasswordLastSet.AddDays($maxPasswordAge)}}), LastLogOnDate,CanonicalName | `
ConvertTo-CSV -NoTypeInformation
}
}
End {
$Headers
$results
}
}
Get-ADUserInfo -Users
Some notes:
When calling Get-AdUserInfo -Users, the script needs to work by entering a single ID, *, or multiple IDs separated by a comma when using the -Users parameter.
Using ConvertTo-CSV solved my biggest problem, comma separated output,thanks all.
I'd like to get rid of the headers that are auto-created as well ("SAMAccountName","Name","PasswordNeverExpires","LockedOut","PasswordLastSet","$_.PasswordLastSet.AddDays($maxPasswordAge)","LastLogOnDate","CanonicalName"). How can I do that? I've tried -skip 1 but that doesn't work with * and removes everything (including the data) if used with a single ID or IDs separated with commas. I can't get -ExpandProperty to work either. Adding format-table -hidetableheaders at the end doesn't do anything as well
So you could use something like this then
$props = "SAMAccountName","Name","PasswordNeverExpires","LockedOut","PasswordLastSet","LastLogOnDate","CanonicalName"
$results = Get-ADUser -Filter * -Properties $props | Select $props | ConvertTo-Csv -NoTypeInformation
This uses the $props array to make the actual query readable and enforce property order. Most of those properties are returned by default, like samaccountname, so it is not required to specify them but no harm done.
$results would contain a quoted comma delimited output. If the quotes bother you they should be removed with a simple -replace
$results = $results -replace '"'
Aside
As others have mentioned you are wasting time using -Properties * you should only return the properties that you need. Which is, again, why I used $props.
Update from comments
If you want to remove the header column you just need to -Skip that from the output. At the end of the code that populates results just add Select-Object
$results = Get-ADUser -Filter * -Properties $props | Select $props | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1
Also to cover your calculated property the easiest way that I have found so far is to add another Select-Object. Not the way I would want to but for now it works.
$results = Get-ADUser -Filter * -Properties $props |
Select $props | Select-Object *,#{L="pWD";Expression={$_.PasswordLastSet.AddDays($masPasswordAge)}} |
ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1
Game Changer
So you made some pretty big changes to your example by including your function. Try this on for size now.
function Get-ADUserInfo
{
[CmdletBinding()]
param(
#[Parameter(Mandatory=$True)]
[string[]]$Users= '*'
)
Begin{
$results = #()
$maxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.Days
$Headers= #{Label="ID";Expression={$_.SAMAccountName}},
#{Label="Name";Expression={$_.Name}},
#{Label="Password Never Expires?";Expression={$_.PasswordNeverExpires}},
#{Label="Locked Out";Expression={$_.LockedOut}},
#{Label="Password Last Set";Expression={$_.PasswordLastSet}},
#{Label="Expiry Date";Expression={$_.PasswordLastSet.AddDays($maxPasswordAge)}},
#{Label="Last Logon Date";Expression={$_.LastLogOnDate}},
#{Label="OU Path";Expression={$_.CanonicalName}}
}
Process{
foreach ($id in $Users){
$results += Get-ADUser -Filter {SAMAccountName -like $id} -Properties PasswordNeverExpires,LockedOut,PasswordLastSet,LastLogOnDate,CanonicalName | select $Headers
}
}
End{
$results | ConvertTo-CSV -NoTypeInformation
}
}
Get-ADUserInfo -Users
$Headers= contains a collection of calculate properties most of which are there the change the header. It does not need to be done this was and you could have just manually added a header line before the output of contents. This solution however is more in line with what PowerShell is capable of.
We collect all of the users in the array $results and in the End block convert that to CSV output which would not contain your custom headers.
$id = "*"
$userlist = Get-ADUser -Filter {SAMAccountName -like $id} -Properties SAMAccountName,Name,PasswordNeverExpires,LockedOut,PasswordLastSet,LastLogOnDate,CanonicalName | ConvertTo-CSV -NoTypeInformation
$userlist will be an array of users stored in CSV formatted lines
Edit: Combined -Properties * | Select [propertylist] and get rid of the pull of all properties.
Edit: included -NoTypeInformation so that the output is pure CSV.
Note: Something should be done about the filter.

Create Shortcut based on an AD HomeDirectory

I'm Trying to create a script to create shortcuts for students based on their AD HomeDirectory and naming the Link as there AD display name. Homedirectory is a UNC path.
However when i get to the $shortcut.targetpath area it complains about invalid parameter. I think it's not liking the data in the $homedir variable. My code is noobish. But i'm still learning. Any help would be great.
###Read a Sisweb Extract
$data=Get-Content C:\studentfile.txt
###For each row in the file execute all of this
foreach ($line in $data)
{
###Parse the row and retrieve SSID
$columns = $line -split '\t'
$studentid = $columns[3]
###If a SSID is found execute the following code.
if($studentid -match "[0-9]")
{
###Retrieve DisplayName of the SSID.
$displayname=Get-aduser $studentid -property displayname |ft displayname -hidetableheaders |out-string
###Retrieve Home Directory of the SSID
$homedir=Get-aduser $studentid -property homedirectory |ft homedirectory -hidetableheaders |out-string
###Parse the homedirectory data and retrieve the servername.
$pathdata="$homedir" -split '\\'
$server=$pathdata[2]
###Create Shortcut
$WshShell=New-Object -comObject WScript.Shell
$Shortcut=$WshShell.CreateShortcut("C:\temp\$displayname.lnk")
$Shortcut.TargetPath="$homedir"
$Shortcut.Save()
}
}
I am going to build an answer since i see a couple of things that should be addressed. Ultimately I think your issue lies with your assignment of $homedir.
if($studentid -match "[0-9]") This code will check to see if $studentid contains a single numerical digit. Was this on purpose? Currently you would get a hit if an ID was sdfhgkjhg3kjg since that contains one digit. A simple addition would be to change it to if($studentid -match "^[0-9]{6}$") for example. Means that it will match a single line that contained exactly 6 digits.
$displayname=Get-aduser $studentid -property displayname |ft displayname -hidetableheaders |out-string I see this twice. I would update this since the Format-Table doesnt really serve a purpose and you can use Select-Object to accomplish your goal.
Get-aduser $studentid -property displayname | select -first 1 -ExpandProperty displayname
Get-aduser $studentid -property homedirectory | select -first 1 -ExpandProperty homedirectory
OR
Instead of call get-aduser twice you could combine both your variable assignments.
$singleStudent = Get-aduser $studentid -property homedirectory,displayname
$displayname = $singleStudent.DisplayName
$homedir = $singleStudent.HomeDirectory