Output filename weirdly - powershell

I've written a script to extract a list of all AD groups name, that then feeds it into the next section which exports a number of CSV files based on the name of the group:
import-module active directory
New-Item -Path "c:\" -Name "ADlist" -ItemType "directory"
get-adgroup -filter * | sort name | select Name | export-csv -Path c:\ADlist\adlist.csv
$ADlist = Import-Csv -Path "c:\ADlist\adlist.csv"
foreach ($ADgroup in $ADlist)
{
$export = get-ADGroupMember -identity $ADgroup.name | select name |Export-Csv "$ADgroup.csv" -notypeinformation
}
this works, however, the csv names are outputting weirdly and looks similar to:
#{Name=$ADgroup}
instead of simply
$ADgroup
is there a way to correct this to output as such?

Your last Export-Csv "$ADgroup.csv" is stringifying your $ADGroup object. Since that object has a property called Name and an associated value, you are seeing the result in that format. You should change that to the following:
$export = Get-ADGroupMember -Identity $ADgroup.name |
Select-Object Name |
Export-Csv "$($ADgroup.Name).csv" -NoTypeInformation
You can see this behavior by just surrounding a custom object in quotes or using Write-Host.
"$ADgroup"
Write-Host $ADgroup

Related

Excluding folders using Get-ChildItem -Exclude

I require to exclude user profiles from \\Computer\c$\Users folder when using Get-ChildItem.
I potentially need to exclude 100 profiles from various machines so have created a variable that contains all user profiles from an AD security group that I want excluding but when I run the below command it doesn't work but if I list the profiles in plain text it does work.
Get-ChildItem "\\$computer\c$\Users" -Exclude $ListOfUsers
But works if I run Get-ChildItem "\\$computer\c$\Users" -Exclude Bob1,Bob2,Bob3,Bob4,Bob5
My code to obtain the users from AD security groups are below and the format it outputs to is like the above with commas.
## collects users from groups and adds to exlusion list.
$1stline = Get-ADGroupMember GG_1st_Line_Team | Select SamAccountName
$2ndline = Get-ADGroupMember GG_2nd_Line_Team | Select SamAccountName
$3rdline = Get-ADGroupMember GG_3rd_Line_Team | Select SamAccountName
$FieldTech = Get-ADGroupMember "Field tech" | select SamAccountname
$Excluded = $1stline + $2ndline + $3rdline + $Fieldtech | Out-File "C:\temp\Members.txt"
(get-content c:\temp\Members.txt) -join "," | out-file C:\temp\Format.txt
$format = get-content c:\temp\format.txt; $format = $format -replace '\s',''; $format = $format -replace ',SamAccountName,--------------,',''; $format = $format.trimend(",,") | Out-File "C:\temp\newFormat.txt"
$excluded = Get-Content C:\Temp\newFormat.txt
This will create a text file with 100 names with no spaces, only commas to seperate the users. If I Write-Host the variable $newformat the commas are White along with the text but if I put the Profile names in plain text then the commas are grey...
The excessive use of Out-File is unnecessary and will cause you issues as it changes objects into strings. You then have to use commands like Split and Join to turn the strings back into the object (arrays here) you require.
Out-File should only be used when you actually need the output as a file.
With a few simple changes to your script it'll do what you want, and be a lot simpler too!
You can use ExpandProperty to only return the value of SamAccountName itself as a string rather than an object.
You can then simply create an array of those strings and use this to exclude those accounts/folders from Get-ChildItem,
$1stline = Get-ADGroupMember GG_1st_Line_Team | Select-Object -ExpandProperty SamAccountName
$2ndline = Get-ADGroupMember GG_2nd_Line_Team | Select-Object -ExpandProperty SamAccountName
$3rdline = Get-ADGroupMember GG_3rd_Line_Team | Select-Object -ExpandProperty SamAccountName
$FieldTech = Get-ADGroupMember "Field tech" | Select-Object -ExpandProperty SamAccountname
$excluded = $1stline,$2ndline,$3rdline,$Fieldtech
Get-ChildItem "\\$computer\c$\Users" -Exclude $excluded
You could then look into using a foreach loop with Get-ADGroupMember to cut down on the duplicated Get-ADGroupMember code.
The problem here seems to be that you're using a [string] variable with a value of Tom,Dick,Harry.
I bet you've got no folders like this, have you?
Whilst you can pass a [string] in to the -Exclude parameter; that will be a singleton (a single, scalar value); and the best you'll get is a single exclusion.
What you really want to pass in is a string array: [string[]]!
[string]$excludedString = "Tom,Dick,Harry"
[string[]]$excludedArray = $excludedString -split ","
Get-ChildItem -Path "C:\users" -Exclude $excludedArray

User Directory Identification

I need to create a script to iterate through a list of user samaccountnames and identify network directories matching their samaccountname on the network. It doesn't seem to work though. Users home folders on the network use their samaccountname in the path. Here is what I have so far:
$userList = "C:\Users\sfp01\My
Documents\Data_Deletion_Testing\User_SamAccountName.csv"
$userDirectory = foreach ($user in $userList)
{
Get-ChildItem -Path "\\ceoii\" -Directory -Recurse | ? {}
}
Export-Csv -Path "C:\Users\sfp01\My
Documents\Data_Deletion_Testing\User_Directory.csv"
First, you need to import the csv as your first line just saves the location of the file in the variable rather than the contents of the file.
Second, you didn't provide the column name of the csv file that contains the user's saMAccountName. You'll need to set up your Where-Object to filter using that information. I am using -match on saMAccountName, but edit this to reflect your requirements.
And I don't think that \\servername\ isn't a valid share name, it should be a share like \\servername\share\ If you want to get all the shares from a server you could enumerate them with something like this invoke-command -ComputerName ceoii -ScriptBlock {Get-SmbShare}
You also probably want to only pull the list of folders once and then filter for each user.
Lastly, you save the information in $userDirectory so you'll want to pipe that information into your export-csv.
$userList = Import-CSV 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_SamAccountName.csv'
$folders = Get-ChildItem -Path "\\ceoii\sharename" -Directory -Recurse
$userDirectory = foreach ($user in $userList) {
$folders | Where-Object {$_.name -match $user.saMAcountName}
}
$userDirectory | Export-Csv -Path 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_Directory.csv'
More efficient than that would be to use -in or -contains if you know that the folder names exactly match.
$folders = Get-ChildItem -Path "\\ceoii\sharename" -Directory -Recurse
$userList = Import-CSV 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_SamAccountName.csv' |
Select-Object -ExpandProperty saMAccountName
$folders |
Where-Object {$_.name -in $userList} |
Export-Csv -Path 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_Directory.csv'

Check AD Computer Names against CSV file

I'm trying to write a Powershell script that will import a list of computer names from a CSV file and compare it against all computer names in AD. I need it to output a list of names from the CSV file that do not exist in AD.
I have been playing around with these commands but they don't do exactly what I want.
$import = Import-Csv -Path C:\Users\username\Desktop\test.csv
$AD-Names = Get-ADComputer -filter * | Select -Expand Name
Compare-Object $import $AD-Names
This seems to give me a list of everything different from both variables which is an extremely long list. I really just need to know which computer names in the CSV file are not in AD.
Simply compare the names from your CSV against the list of names from AD (I'm going to assume that the column title of the CSV is Name):
$ADNames = Get-ADComputer -Filter * | Select-Object -Expand Name
Import-Csv 'C:\path\to\input.csv' |
Where-Object { $ADNames -notcontains $_.Name } |
Export-Csv 'C:\path\to\not_in_AD.csv' -NoType
Side note: $AD-Names is not a valid variable name. Change the hyphen to an underscore or remove it entirely, or put the variable name in curly brackets (${AD-Names}).
First, why do you need a csv file if there are only computer names ?
CSV files are usually used to store a table in a simple text file.
If your CSV only contains the computer names, and you only want to check for computer names, this could work for you :
$OutputComputers = #();
$InputComputers = Import-Csv input.csv -Header ComputerName;
$AdComputers = Get-ADComputer -Filter 'Name -like "*"';
$InputComputers | ForEach-Object {$i = 0} {
if ($_.ComputerName -notin $AdComputers.Name) {
$OutputComputers += New-Object PsObject -property #{
'ComputerName' = $_.ComputerName
}
}
}
$OutputComputers | Export-Csv output.csv -Delimiter ";" -Encoding UTF8 -Force -NoTypeInformation
Hope it helps.

How to use Select-Object property to expand all the fields in the power shell command

Get-ChildItem -Path E:\Server_Data\data\2015 -Recurse –File -include "*.txt","*.csv" | Where-Object {$_.Name -like "*transaction*"} | Select-Object -ExpandProperty FullName,LastWriteTime
I'm trying to list all files in a folder using Get-ChildItem and Select-Object property. When I try to use FullName variable to list the fully qualified file name, the file name is getting truncated. Tried to use -ExpandProperty to get fully qualified file name. It works for one field but if I try to list both FullName and LastWriteTime, it's not working.
The output from the power shell command will be used in MS SQL Server to load the file names into a specific table.
Please suggest proper syntax for my purpose. Appreciate your help!
Depending on your use case and input, one way to accomplish this is by having two Select-Object cmdlets in your pipeline, one to define an array of properties, and one to expand them:
PS C:\> $Name,$DisplayName,$Status = Get-Service
| Select-Object -First 1 -Property #{
Name = "MyProperties"
Expression = { $_.Name,$_.DisplayName,$_.DisplayName }
} | Select-Object -ExpandProperty MyProperties
Get-ChildItem -Path E:\Server_Data\main.sweetbeam.net\data\2015 -Recurse –File -include "*.txt","*.csv" | Where-Object {$_.Name -like "*transaction*"} | Select-Object #{Name="test";Expression={$_.FullName + "`t" + $_.LastWriteTime}} | Select-Object -ExpandProperty test
Merged the two fields and used the derived field for my purpose.
If you are only going to do this to display on the console, then you can look at using Format-Table with the -Wrap parameter to display all of the text on the console without truncating the output.
Get-ChildItem -Path E:\Server_Data\data\2015 -Recurse –File -include "*.txt","*.csv" |Where-Object {
$_.Name -like "*transaction*"
} | Format-Table FullName,LastWriteTime -Wrap
If you are planning on doing anything else with our output, then you will need to avoid the use of Format-* cmdlets as they add custom formatting to the object and render it effectively useless in the pipeline.
If you're using the output in another program, you should be converting to CSV, JSON, or XML rather than copying the formatted output. It may also be possible to insert directly into SQL using PowerShell commands.
Get-ChildItem -Path E:\Server_Data\data\2015 -Recurse –File -include "*.txt","*.csv" |
Where-Object {$_.Name -like "*transaction*"} |
Select-Object FullName,LastWriteTime |
ConvertTo-Csv -NoTypeInformation
Other options for the last command are:
JSON with ConvertTo-Json
XML with ConvertTo-xml -As String -NoTypeInformation
Late answer, but this has existed since PowerShell 3.0, so should have been an option.
get-eventlog Security `
-EntryType SuccessAudit `
-Newest 50 `
-InstanceId 4624,4634 `
-ComputerName $env:COMPUTERNAME |
Select-Object -Property *
OR (not all fields)
get-eventlog Security `
-EntryType SuccessAudit `
-Newest 50 `
-InstanceId 4624,4634 `
-ComputerName $env:COMPUTERNAME |
Select-Object -Property TimeGenerated,EventID,Message -PipelineVariable myEvent |
Foreach-Object -Process {
convertTo-Json -InputObject #{
TimeGenerated = (Get-Date $myEvent.TimeGenerated)
EventID = $myEvent.EventID
Message = $myEvent.Message.Substring(0, $myEvent.Message.IndexOf("`r"))
} -Depth 1
}
Hope I'm not late for the game. This one example works for me (Get-Service, more than 1 properties having embedded 'collections' of data)
Get-Service |
Select-Object
Name,
Status,
...
and then in the next lines in your script, the next object(s) that you want expanded should be like this
#{Name="CustomCol01";Expression={$_.ServicesDependedOn} },
#{Name="CustomCol02";Expression={$_.DependentService} }
In the example, the 2 offending objects that I need expanded are ServicesDependedOn and DependentService
So yeah by custom making new columns it expands whatever Objects for you
Tested works even when redirecting the final output to a csv like this
... > myfile.csv

PowerShell foreach loop export to new column in CSV format

I am currently working with a CSV file that has a manager's employee number, but not their SAMAccountName. I want to utilize Get-ADUser to grab the manager's SAMAccountName from their EmployeeNumber attribute and place that inside a new column in the same CSV file.
CSV sample:
"Full Name","Username","Manager","Manager User Sys ID"
"User 1","u1","1, Manager","123456"
"User 2","u2","2, Manager","234567"
"User 3","u3","3, Manager","345678"
I would like:
"Full Name","Username","Manager","Manager User Sys ID","Manager SamAccountName"
"User 1","u1","1, Manager","123456","m1"
"User 2","u2","2, Manager","234567","m2"
"User 3","u3","3, Manager","345678","m3"
I have spent some time putting together the following code. I can get a new column added and can further grab the SAMAccountName, but it only exports a single line in the new CSV file like this:
"SAMAccountName","managerUsername"
"m1","#{SAMAccountName=m1}"
Here is the code:
$managers = Import-Csv -Path .\test.csv
$usermananger = #()
foreach ($manager in $managers)
{
$getmanagersam = Get-ADUser -Filter "employeeNumber -eq $($manager."Manager User Sys ID")" -Properties SAMAccountName |
Select-Object SAMAccountName
$exportstring = $testmanager |
Select-Object *,#{Name='managerUsername';Expression={"$getmanagersam"}}
$exportstring | Export-Csv -Path .\simpletest.csv -NoTypeInformation
}
As #MathiasR.Jessen mentioned in the comments: you need to expand the SamAccountName property to get just the value. Also, you're overwriting your output CSV with every iteration. Either append to the file, or move the Export-Csv cmdlet outside the loop. The former requires PowerShell v3 or newer, the latter requires that you change the loop to a ForEach-Object loop (or run the foreach loop in a subexpression).
Personally I'd prefer using a pipeline, so I'd pick the latter:
Import-Csv -Path .\test.csv | ForEach-Object {
$acct = Get-ADUser -Filter "employeeNumber -eq $($_.'Manager User Sys ID')" |
select -Expand SamAccountName
$_ | select *,#{Name='managerUsername';Expression={$acct}}
} | Export-Csv -Path .\simpletest.csv -NoTypeInformation
The short answer is to add the -Append option to your export-csv statement to stop it overwriting each time round the loop.
Alternatively move the export outside the loop as follows:
$managers = Import-Csv -Path .\test.csv
$managers|foreach-object{
$getmanagersam = Get-ADUser -Filter "employeeNumber -eq $($_.'Manager User Sys ID')" | select -ExpandProperty SAMAccountName
$_|Select *,#{Name='managerUsername';Expression=$getmanagersam}
} | Export-Csv -Path .\simpletest.csv -NoTypeInformation
Note: looks like #AnsgarWiechers beat me to it :-)
I'm late to the party it looks like, but that rarely stops me... I'm not a huge fan of adding properties via the Select cmdlet, so I'm going to offer an alternative where you pipe the CSV to a ForEach-Object loop (just like the other answers), but inside that you use Add-Member with the -PassThru argument, and then pipe it off to the output file. I will add a new line and indent after the pipes, just to make it easier to read.
Import-Csv -Path ".\test.csv" |
ForEach-Object {Add-Member -InputObject $_ -NotePropertyName 'managerUserName' -NotePropertyValue (Get-ADUser -Filter "employeeNumber -eq $($_.'Manager User Sys ID')").samaccountname -PassThru} |
Export-Csv -Path ".\simpletest.csv" -NoTypeInformation
This should essentially do the exact same thing as the other two answers, it just adds the property differently, because variety is the spice of life! (I saw that on the internet somewhere, so it must be true.)