I recently created a PowerShell script to gather disk size, usage and free space, then export them into a CSV. Now I need to create a new CSV file with the "free space" column of each created file. I need to have each column grabbed, dropped into a new column. I've been tinkering with a script and digging into articles all day without luck. Below is the closest I've gotten.
$sort = gci | select name | Where-Object {$_.name -like "diskspace_*"}
$count = 0
foreach ($item in $sort) {
$count = ($count +=1)
$free = Import-Csv $item.name | Select-Object 'Free'
$share = Import-Csv $item.name |
Select-Object 'Share',#{Name="something"; Expression={$free.free}} |
Export-Csv free_report.csv -NoTypeInformation
}
So I have a script that runs at logon to search for PST's on a users machine, then copies them to a holding area waiting for migration.
When the search/copy is complete it outputs to a CSV that looks something like this:
Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied
COMP1,user1,\\comp1\c$\Test PST.pst,20.58752,08/12/2015,08/12/2015,Client copied
COMP1,user1,\\comp1\c$\outlook\outlook.pst,100,08/12/2015,15,12,2015,In Use
The same logon script has an IF to import the CSV if the copied status is in use and makes further attempts at copying the PST into the holding area. If it's successful it exports the results to the CSV file.
My question is, is there anyway of getting it to either amend the existing CSV changing the copy status? I can get it to add the new line to the end, but not update.
This is my 'try again' script:
# imports line of csv where PST file is found to be in use
$PST_IN_USE = Import-CSV "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" | where { $_.copied -eq "In Use" }
ForEach ( $PST_USE in $PST_IN_USE )
{ $NAME = Get-ItemProperty $PST_IN_USE.Path | select -ExpandProperty Name
$NEW_NAME = $USER + "_" + $PST_IN_USE.Size_in_MB + "_" + $NAME
# attempts to copy the file to the pst staging area then rename it.
TRY { Copy-Item $PST_IN_USE.Path "\\comp4\TEMPPST\PST\$USER" -ErrorAction SilentlyContinue
Rename-Item "\\comp4\TEMPPST\PST\$USER\$NAME" -NewName $NEW_NAME
# edits the existing csv file replacing "In Use" with "Client Copied"
$PST_IN_USE.Copied -replace "In Use","Client Copied"
} # CLOSES TRY
# silences any errors.
CATCH { }
$PST_IN_USE | Export-Csv "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" -NoClobber -NoTypeInformation -Append
} # CLOSES ForEach ( $PST_USE in $PST_IN_USE )
This is the resulting CSV
Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied
COMP1,user1,\\comp1\c$\Test PST.pst,20.58752,08/12/2015,08/12/2015,Client copied
COMP1,user1,\\comp1\c$\outlook\outlook.pst,100,08/12/2015,15,12,2015,In Use
COMP1,user1,\\comp1\c$\outlook\outlook.pst,100,08/12/2015,15,12,2015,Client copied
It's almost certainly something really simple, but if it is, it's something I've yet to come across in my scripting. I'm mostly working in IF / ELSE land at the moment!
If you want to change the CSV file, you have to write it completely again, not just appending new lines. In your case this means:
# Get the data
$data = Import-Csv ...
# Get the 'In Use' entries
$inUse = $data | where Copied -eq 'In Use'
foreach ($x in $inUse) {
...
$x.Copied = 'Client Copied'
}
# Write the file again
$data | Export-Csv ...
The point here is, you grab all the lines from the CSV, modify those that you process and then write the complete collection back to the file again.
I've cracked it. It's almost certainly a long winded way of doing it, but it works and is relatively clean too.
#imports line of csv where PST file is found to be in use
$PST_IN_USE = Import-CSV "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" | where { $_.copied -eq "In Use" }
$PST_IN_USE | select -ExpandProperty path | foreach {
# name of pst
$NAME = Get-ItemProperty $_ | select -ExpandProperty Name
# size of pst in MB without decimals
$SIZE = Get-ItemProperty $_ | select -ExpandProperty length | foreach { $_ / 1000000 }
# path of pst
$PATH = $_
# new name of pst when copied to the destination
$NEW_NAME = $USER + "_" + $SIZE + "_" + $NAME
TRY { Copy-Item $_ "\\comp4\TEMPPST\PST\$USER" -ErrorAction SilentlyContinue
TRY { Rename-Item "\\comp4\TEMPPST\PST\$USER\$NAME" -NewName $NEW_NAME -ErrorAction SilentlyContinue | Out-Null }
CATCH { $NEW_NAME = "Duplicate exists" }
$COPIED = "Client copied" }
CATCH { $COPIED = "In use" ; $NEW_NAME = " " }
$NEW_FILE = Test-Path "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 4.csv"
IF ( $NEW_FILE -eq $FALSE )
{ "Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied,New_Name" |
Set-Content "\\lccfp1\TEMPPST\PST\$HOSTNAME - $USER 4.csv" }
"$HOSTNAME,$USER,$PATH,$SIZE,$CREATION,$LASTACCESS,$COPIED,$NEW_NAME" |
Add-Content "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 4.csv"
} # CLOSES FOREACH #
$a = Import-CSV "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" | where { $_.copied -ne "in use" }
$b = Import-Csv "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 4.csv"
$a + $b | export-csv "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 8.csv" -NoClobber -NoTypeInformation
Thanks for the help. Sometimes it takes a moments break and a large cup of coffee to see things a different way.
I'm trying to take input from a CSV file, which has a list of group names (canonical names) and get the Distinguished Name from it, then output to another CSV file. The code:
#get input file if passed
Param($InputFile)
#Set global variable to null
$WasError = $null
#Prompt for file name if not already provided
If ($InputFile -eq $NULL) {
$InputFile = Read-Host "Enter the name of the input CSV file (file must have header of 'Group')"
}
#Import Active Directory module
Import-Module -Name ActiveDirectory -ErrorAction SilentlyContinue
$DistinguishedNames = Import-Csv -Path $InputFile -Header Group | foreach-Object {
$GN = $_.Group
$DN = Get-ADGroup -Identity $GN | Select DistinguishedName
}
$FileName = "RESULT_Get-DistinguishedNames" + ".csv"
#Export list to CSV
$DNarray | Export-Csv -Path $FileName -NoTypeInformation
I've tried multiple solutions, and none have seemed to work. Currently, it throws an error because
Cannot validate argument on parameter 'Identity'. The argument is null. Supply a non-null argument and try the command again.
I tried using -Filter also, and in a previous attempt I used this code:
Param($InputFile)
#Set global variable to null
$WasError = $null
#Prompt for file name if not already provided
If ($InputFile -eq $NULL) {
$InputFile = Read-Host "Enter the name of the input CSV file(file must have header of 'GroupName')"
}
#Import Active Directory module
Import-Module -Name ActiveDirectory -ErrorAction SilentlyContinue
$DistinguishedNames = Import-Csv -Path $InputFile | foreach {
$strFilter = "*"
$Root = [ADSI]"GC://$($objDomain.Name)"
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher($root)
$objSearcher.Filter = $strFilter
$objSearcher.PageSize = 1000
$objsearcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
$objcolresults = $objsearcher.FindAll()
$objitem = $objcolresults.Properties
[string]$objDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
[string]$DN = $objitem.distinguishedname
[string]$GN = $objitem.groupname
#Get group info and add mgr ID and Display Name
$props = #{'Group Name'= $GN;'Domain' = $objDomain;'Distinguished Name' = $DN;}
$DNS = New-Object psobject -Property $props
}
$FileName = "RESULT_Get-DistinguishedNames" + ".csv"
#Export list to CSV
$DistinguishedNames | Sort Name | Export-Csv $FileName -NoTypeInformation
The filter isn't the same one I was using here, I can't find the one I was using, the I currently have is a broken attempt.
Anyway, the main issue I was having is that it will get the group name, but search for it in the wrong domain (it wouldn't include Organizational Units) which caused none of them to be found. When I search for a group in PowerShell though (using Get-ADGroup ADMIN) they show up with the correct DN and everything. Any hints or code samples are appreciated.
You seemingly miss the point of $variable = cmdlet|foreach {script-block} assignment. The objects to assign to $variable should be returned (passed through the script block) in order to end up in $variable. Both your main loops contain the structure of the line $somevar=expectedOutput where expectedOutput is either a New-Object psobject or Get-ADGroup call. The assignment to $someVar suppresses the output, so that the script block does not have anything to return, and $variable remains null. To fix, do not prepend the call that should return an object into outside variable with an assignment.
$DistinguishedNames = Import-Csv -Path $InputFile -Header Group | foreach-Object {
$GN = $_.Group
Get-ADGroup -Identity $GN | Select DistinguishedName # drop '$DN=`
}
$DistinguishedNames | Export-CSV -Path $FileName -NoTypeInformation
The same issue with the second script.
We have this PowerShell script that we use to take out users from the AD. We recently moved to Windows Server 2012R2 from 2008R2 and noticed that the script no longer works. After a few tweaks and turns I have managed to get almost everything to work except this loop:
$mail += $nameofgroup | ForEach-Object {$mail += $_.Name+"<br>"}
This is to be sent via email later therefore we have the $mail variable.
Here is a code example:
Get info from AD:
$alla = Get-ADUser -filter 'name -like "*"' `
-Properties extensionattribute2, extensionattribute14, extensionattribute15 | `
Select-Object Name, Extensionattribute2, `
Extensionattribute14, Extensionattribute15
Sort the data:
$nameofgroup = $alla | where { `
$.Extensionattribute14 -like "nameofgroup" -and `
$.Extensionattribute15 -like "FULL"} | `
Select-Object Name | Sort-Object Name
Post total amount of users:
$mail += "nameofgroup: " + ($nameofgroup).count + "<br>"
and then my line from before, I want this to list the users by "name"
$mail += $nameofgroup | ForEach-Object {$mail += $_.Name+"<br>"}
Can anyone spot a fault in this last line?
Update:
I just tried to Write-Host $nameofgroup to see if contains data and it does, so the problem is more or less why it won't print it to $mail.
You append to $mail both inside and outside the loop. Decide on one or the other:
$mail += $nameofgroup | ForEach-Object { $_.Name+"<br>" }
or
$nameofgroup | ForEach-Object { $mail += $_.Name+"<br>" }
I have this script that will only list a user's groups on the ISE screen where the data can be copied and pasted elsewhere, but I'm trying to get the group membership names written into the Telephone Notes tab (or Info field). I'm thinking next that these probably need to be turned into string values since I'm getting errors about multi properties not allowed. Here is what I've been trying, but I keep getting errors. Thanks
Import-Module ActiveDirectory
$Users= Import-csv "C:\Scripts\UsersSAM-DisplayName.csv"
ForEach ($User in $Users) {
$SamAccountName=$User.SamAccountName
$DisplayName=$User.DisplayName
$TableFormat= #{E={$_.Name};L="$($DisplayName) - $($SamAccountName)"}
Get-ADUser -Identity $SamAccountName -Properties MemberOf | % {$_.MemberOf } | % {Get-ADGroup -Identity $_ } | % { Set-ADUser -Identity $SamAccountName -add #{info="$_.name"}} | Select Name |
Format-Table $TableFormat }
I figured this out. What they wanted was to first write out a terminated user's groups, then remove those. I did it like this and this code includes the semi-colon so if the user comes back, all you need to do to add them back to all the groups is copy and paste those from the output stored in the Telephones Tab, Notes field. I've also used a trimmed down version of this to export a user's groups to speed up duplicating a user's groups so they match with others on the same team. Hope this helps someone.
Import-csv "$Terms" | % {
$user = Get-ADUser -LDAPFilter ("(sAMAccountName=" + $_.samaccountname + ")") -Properties samaccountname,enabled,name,memberof,distinguishedname,info
#Grab all user group names
$user | ForEach-Object {
$grps = $_.MemberOf | Get-ADGroup | ForEach-Object {$_.Name} | Sort-Object
$arec = $_.Name,$_.SamAccountName
$aline = ($grps -join ";")
#Add info to Notes field Telephone Tab
Get-ADPrincipalGroupMembership -Identity $user | %{
If ($_.SamAccountName -ne "Domain Users") {
$Userinfo=$user.info
Set-ADUser $User -replace #{info= "$Userinfo | $a | Terminated via automated process | $aline"}
#Remove User Groups Process in Telephones Tab Notes Field.
Remove-ADPrincipalGroupMembership -Identity $user -MemberOf $_.SamAccountName -Confirm:$false
(" "+ $a +" [" + $User.samaccountname + "], Removed from group [" + $_.samaccountname + "]. ") | Out-File -FilePath $ErrorLog -Append
}
}}}