PowerShell export to csv. Only quote 1 set in each row - powershell

When I'm building a CSV Export it puts quotes around every set of parameters. However, I only want 1 set to have the quotes.
$UserInfo = New-Object System.Object
foreach ($user in $MailBoxList)
{
$UserInfo | Add-Member -Type NoteProperty -Name LegacyExchangeDN -Value $user.LegacyExchangeDN
$UserInfo | Add-Member -Type NoteProperty -Name CloudEmailAddress -Value $CloudEmailAddress
$UserInfo | Add-Member -Type NoteProperty -Name OnPremiseEmailAddress -Value $user.PrimarySMTPAddress.ToString()
$UserInfo | Add-Member -Type NoteProperty -Name MailboxGUID -Value $user.ExchangeGUID
$Users += $UserInfo
}
$Users | Export-CSV -Delimiter "," -Path ".\cloud.csv" -NoTypeInformation
This code results in this exported CSV:
"LegacyExchangeDN","CloudEmailAddress","OnPremiseEmailAddress","MailboxGUID"
"/o=MyUnit/ou=This Admin Group (BRBIDOMF87SRQLT)/cn=Recipients/cn=a0dd27c5djd864108cfa61dj37dj56c6-MyLastName, M","mMyLastName#WhereverImFrom.Bob.com","mMyLastName#AnotherDomain.com","687efe5e-4690-110e-86a5-69fr4cdecf7e"
What I'd like is just the first column of data to have double quotes and the rest without:
"/o=MyUnit/ou=This Admin Group (BRBIDOMF87SRQLT)/cn=Recipients/cn=a0dd27c5djd864108cfa61dj37dj56c6-MyLastName, M",mMyLastName#WhereverImFrom.Bob.com,mMyLastName#AnotherDomain.com,687efe5e-4690-110e-86a5-69fr4cdecf7e
Any thoughts?

You can "roll your own" csv file:
$Outfile = ".\cloud.csv"
'LegacyExchangeDN,CloudEmailAddress,OnPremiseEmailAddress' | Set-Content $Outfile
foreach($user in $MailBoxList)
{
$Data = #(
$user.LegacyExchangeDN,
$CloudEmailAddress,
$user.PrimarySMTPAddress.ToString()
)
'"{0}",{1},{2}' -f $Data | Add-Content $Outfile
}

Here's one solution. What it does is convert the objects to csv-strings and then modify them before saving the csv to a file.
foreach($user in $MailBoxList)
{
$UserInfo = New-Object System.Object
$UserInfo | Add-Member -Type NoteProperty -Name LegacyExchangeDN -Value $user.LegacyExchangeDN
$UserInfo | Add-Member -Type NoteProperty -Name CloudEmailAddress -Value $CloudEmailAddress
$UserInfo | Add-Member -Type NoteProperty -Name OnPremiseEmailAddress -Value
$user.PrimarySMTPAddress.ToString()
$UserInfo | Add-Member -Type NoteProperty -Name MailboxGUID -Value $user.ExchangeGUID
$Users += $UserInfo
}
#Convert to csv-formatted-strings
$csv = $Users | ConvertTo-Csv -NoTypeInformation -Delimiter ","
#Get header
$out = #($csv[0])
#Remove quotes for all but first column
$out += $csv[1..($csv.Length-1)] | % {
[regex]::Match($_,'(^"[^"]*",)(.*)') | % { "{0}{1}" -f $_.Groups[1], $_.Groups[2].Value.Replace('"',"") }
}
$out | Set-Content -Path ".\cloud.csv"
Another apporach without regex:
#Remove quotes for all but first column
$out += $csv[1..($csv.Length-1)] | % {
$values = $_ -split '","'
$values[0] + '"' + $values[1..($values.Length-1)] -join ','
}

Related

How to find email adress of AzureAD user with ps1 script

here is the script i use to export the data from AzureAD to csv.
Connect-AzureAD
Connect-MsolService
$date = Get-Date -UFormat "%d%m%Y"
$dateInfo = Get-Date
$Results = #()
$Roles = Get-AzureADDirectoryRole
foreach ($Role in $Roles) {
$MemberRole = Get-AzureADDirectoryRoleMember -ObjectId $Role.ObjectId
foreach ($Membre in $MemberRole ) {
$InfosUsers = Get-MsolUser -ObjectId $Membre.ObjectId
$List = New-Object System.Object
$List | Add-Member -type NoteProperty -name Compte -Value $Membre.DisplayName
$List | Add-Member -type NoteProperty -name Active -Value $Membre.AccountEnabled
$List | Add-Member -type NoteProperty -name Role -Value $Role.DisplayName
$List | Add-Member -type NoteProperty -name NumeroTel -Value $InfosUsers.StrongAuthenticationUserDetails.PhoneNumber
$Results += $List
}
}
$Results | Export-Csv path/to/the/file/ -NoTypeInformation
Disconnect-AzureAD
The things is that i would like to get mail adresse from user and i dont know how to do ?
Happy to see you already got your answer, here is one alternative way you can approach to get the email address of Azure AD user.
I did Few changes in your code (ie I have removed Connect-MsolService and replace Get-MsolUser with Get-AzADUser.) and I am able to perform the operation you are trying to do .
Connect-AzureAD
$date = Get-Date -UFormat "%d%m%Y"
$dateInfo = Get-Date
$Results = #()
$Roles = Get-AzureADDirectoryRole
foreach ($Role in $Roles) {
$MemberRole = Get-AzureADDirectoryRoleMember -ObjectId $Role.ObjectId
foreach ($Membre in $MemberRole ) {
$InfosUsers = Get-AzADUser -ObjectId $Membre.ObjectId
$List = New-Object System.Object
$List | Add-Member -type NoteProperty -name Compte -Value $Membre.DisplayName
$List | Add-Member -type NoteProperty -name Active -Value $Membre.AccountEnabled
$List | Add-Member -type NoteProperty -name Role -Value $Role.DisplayName
$List | Add-Member -type NoteProperty -name NumeroTel -Value $InfosUsers.StrongAuthenticationUserDetails.PhoneNumber
$List | Add-Member -type NoteProperty -name Email -Value $Membre.Mail
$List | Add-Member -type NoteProperty -name UPName -Value $Membre.UserPrincipalName
$Results += $List
}
}
$Results | Export-Csv /RahulS -NoTypeInformation
Output---

Powershell custom append object to csv file

I'm trying to output a custom object to a csv formatted text file as I loop through a for each. One object per line.
But nothing is written to the file.
Is it something with types to be converted ?
$rechten = Get-ADGroupMember -Identity $v -Recursive -ERRORACTION silentlycontinue | Get-ADUser -Property DisplayName -ERRORACTION silentlycontinue | Select-Object Name
Write-Host -ForegroundColor Yellow "ADgroup $v wordt uitgevlooid."
foreach ($rechtenhouder in $rechten) {
$objResults = New-Object PSObject
$objResults | Add-Member -MemberType NoteProperty -Name DirectoryPath -Value $objPath
$objResults | Add-Member -MemberType NoteProperty -Name Identity -Value $rechtenhouder.name
$objResults | Add-Member -MemberType NoteProperty -Name Systemrights -Value $accessRight.FileSystemRights
$objResults | Add-Member -MemberType NoteProperty -Name systemrightstype -Value $accessRight.accesscontroltype
$objResults | Add-Member -MemberType NoteProperty -Name isinherited -Value $accessRight.isinherited
$objResults | Add-Member -MemberType NoteProperty -Name inheritanceflags -Value $accessRight.inheritanceflags
$objResults | Add-Member -MemberType NoteProperty -Name rulesprotected -Value $objACL.areaccessrulesprotected
$objResults | Add-Member -MemberType NoteProperty -Name Adtype -Value "User"
$arrResults += $objResults
Add-Content $exportpathtxtappend $objresults
}
For your specific use exporting all objects at once or in batches would be the most efficient, but there are times were it would make sense to export a record one at a time to a CSV file which is what led me to this question, so I want to post my solution.
Use Export-CSV -Append to continually add to the end of a csv file.
foreach ($rechtenhouder in $rechten) {
$objResults = New-Object PSObject -Property #{
DirectoryPath = $objPath;
Identity = $rechtenhouder.name;
Systemrights = $accessRight.FileSystemRights;
systemrightstype = $accessRight.accesscontroltype;
isinherited = $accessRight.isinherited;
inheritanceflags = $accessRight.inheritanceflags;
rulesprotected = $objACL.areaccessrulesprotected;
Adtype = "User";
}
$objResults | Export-CSV $csvPath -Append -NoTypeInformation
}
This is useful if you are continually polling at set time intervals, but less so if you are iterating over a collection of objects, just export them all at once. For example, I would use this method of exporting for a script like below:
while($true){
$procs = Get-Process | Select-Object Name,CPU
$procs | Add-Member -type NoteProperty -Name "Timestamp" -Value $(Get-Date)
$procs | Export-CSV $csvPath -Append -NoTypeInformation
sleep -Seconds 60
}
First, I suggest you to create your object in a decent smarter way:
foreach ($rechtenhouder in $rechten) {
$objResults = New-Object PSObject -Property #{
DirectoryPath = $objPath;
Identity = $rechtenhouder.name;
Systemrights = $accessRight.FileSystemRights;
systemrightstype = $accessRight.accesscontroltype;
isinherited = $accessRight.isinherited;
inheritanceflags = $accessRight.inheritanceflags;
rulesprotected = $objACL.areaccessrulesprotected;
Adtype = "User";
}
$arrResults += $objResults
}
With this done, your $arrResults now contains your objects. This can easily exported to CSV files with PowerShells builtin Export-CSV:
$arrResults | Export-Csv -Path "C:/temp/text.csv"
Using Add-Content on every loop iteration is IMHO ineffective regarding performance. If your script runs for a long time and you want to save your current state in intervals, you could e.g. start an asynchronous job - let's say every 10th iteration - exporting your current array:
$i = 0
foreach ($rechtenhouder in $rechten) {
$objResults = New-Object PSObject -Property #{
DirectoryPath = $objPath;
Identity = $rechtenhouder.name;
Systemrights = $accessRight.FileSystemRights;
systemrightstype = $accessRight.accesscontroltype;
isinherited = $accessRight.isinherited;
inheritanceflags = $accessRight.inheritanceflags;
rulesprotected = $objACL.areaccessrulesprotected;
Adtype = "User";
}
$arrResults += $objResults
if ($i % 10 -eq 0) {
Start-Job -ScriptBlock {
param($T, $Path)
$T | Export-Csv -Path $Path
} -ArgumentList #($arrTest, "Path/to/script")
}
$i++
}

powershell script to return all forwarding rules in org

I need to pull all forwarding rules for an exchange online environment, and output them to a csv. this sounds simple, but I have an additional caveat. there are 23,000 mailboxes in the org.
I was able to write the script I needed, it outputted the data, but it timed out.
then I was able to break out only certain mailboxes that were critical (11,000) but I was still timing out in powershell.
so finally, I found an article that detailed breaking up a script into blocks of 1,000, and running numerous sessions. and runs! it runs without timing out.
but it doesn't output to the csv anymore.
since my script has gone through several iterations, I'm pretty sure that my problem is the way I'm storing, or outputting the array, but for all my staring at this, I cant figure it out. short of asking the doc for a prescription of Adderall, I figured id ask here. below is the offending script.
the aliaslist.csv that it mentions is just a csv with a list of aliases for 11,000 mailboxes. if you would like to run your own tests, you can adjust $pagesize down and paste a few mailboxes into a csv called aliaslist, stored in c:\temp
Function New-O365ExchangeSession()
{
param(
[parameter(mandatory=$true)]
$365master)
#close any old remote session
Get-PSSession | Remove-PSSession -Confirm:$false
#start a new office 365 remote session
$365session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $365master -Authentication Basic -AllowRedirection
$office365 = Import-PSSession $365session
}
#set input variables
$path = "C:\temp"
$InputFile = aliaslist.csv"
$UserEmail = "admin#domain.com"
#set variables for csv usage
$Offset = 0;
$PageSize = 1000;
$MbxMax = (Import-Csv "$path/$InputFile").count
#Loop in the list and retrieve the device’s information
$file = “c:\temp\office365-$((get-date).tostring(“yyyy-MM-dd”)).csv”
$365master = get-credential $UserEmail
New-O365ExchangeSession $365master
# call the office365 remote connection function
do{
$mbxlist=#(import-csv "$path/$InputFile"|select-object -skip $Offset -First $PageSize)
"Process entry $($Offset) to $($Offset+$PageSize)"
#end csv input count reference
ForEach($mbx in $MbxList)
{
#Write to Host
"start Processing $($mbx.alias)"
#end Write to host,
#Check rules
$rules = Get-InboxRule -mailbox $_.alias | ? {$_.RedirectTo -ne $null -or $_.ForwardTo -ne $null -or $_.ForwardAsAttachmentTo -ne $null}
If ($rules -ne $null)
{
$rules | % {
#check for forwardAsAttachments
If ($_.ForwardAsAttachmentTo -ne $null)
{
$obj = New-Object system.object
$obj | Add-Member -name "NetID" -Value $_.alias -MemberType NoteProperty
$obj | Add-Member -name "ForwardType" -Value "Forward As Attachment Rule" -MemberType NoteProperty
$obj | Add-Member -name "ForwardAddress" -Value $_.forwardAsAttachmentTo -MemberType NoteProperty
$obj | Add-Member -name "Enabled" -Value $_.Enabled -MemberType NoteProperty
$obj | Add-Member -name "Description" -Value $f -MemberType NoteProperty
If (Test-Path $file)
{
$mbx.alias + ”,” + ($obj | ConvertTo-Csv)[2] | Out-File $file –Append
}
Else
{
$obj | Export-Csv $file -Encoding ASCII -notypeinformation
}
}
$obj = $null
#check for redirects
If ($_.redirectto -ne $null)
{
$obj = New-Object system.object
$obj | Add-Member -name "NetID" -Value $_.alias -MemberType NoteProperty
$obj | Add-Member -name "ForwardType" -Value "Redirct Rule" -MemberType NoteProperty
$obj | Add-Member -name "ForwardAddress" -Value $_.redirectto -MemberType NoteProperty
$obj | Add-Member -name "Enabled" -Value $_.Enabled -MemberType NoteProperty
$obj | Add-Member -name "Description" -Value $c -MemberType NoteProperty
If (Test-Path $file)
{
$mbx.alias + ”,” + ($obj | ConvertTo-Csv)[2] | Out-File $file –Append
}
Else
{
$obj | Export-Csv $file -Encoding ASCII -notypeinformation
}
}
$obj = $null
#check for forwards
If ($_.ForwardTo -ne $null)
{
$obj = New-Object system.object
$obj | Add-Member -name "NetID" -Value $_.alias -MemberType NoteProperty
$obj | Add-Member -name "ForwardType" -Value "Forward Rule" -MemberType NoteProperty
$obj | Add-Member -name "ForwardAddress" -Value $_.forwardto -MemberType NoteProperty
$obj | Add-Member -name "Enabled" -Value $_.Enabled -MemberType NoteProperty
$obj | Add-Member -name "Description" -Value $f -MemberType NoteProperty
If (Test-Path $file)
{
($obj | ConvertTo-Csv)[2] | Out-File $file –Append
}
Else
{
$obj | Export-Csv $file -Encoding ASCII -notypeinformation
}
}
$obj = $null
}
}
}
#increment the start point for the next chunk
$Offset+=$PageSize
#Call the office365 remote session function to close the current one and open a new session
New-O365ExchangeSession $365master
} while($Offset -lt $MbxMax)

Powershell Compare Objects from multiple sources

I'm trying to build out a script to compare multiple CSV files and identify the delta in one master file. I think I'm close to having what I need but, I'm running into an issue when trying to set the value for the property on the master object.
I'm pulling in one CSV file (Sample) that has Computer Name, Location, IP, Active Directory, SCCM that I'm comparing to outputs from Active Directory (Compare) with the same information. I just want to update the first file with either a yes or no that the system is in Active Directory in the column called AD.
Here is the code that I have and need some guidance on fixing it:
$Sample = Import-Csv C:\Scripts\Sample_test_v1.csv
$Compare = Import-Csv C:\Scripts\Sample_AD_v1.csv
$Final = #()
foreach ($Samples in $Sample)
{
$Final = New-Object System.Object
$Final | Add-Member -type NoteProperty -name "Computer Name" -value $Samples.ComputerName
$Final | Add-Member -type NoteProperty -name "IP Address" -value $Samples.IP
$Final | Add-Member -type NoteProperty -name "Location" -value $Samples.Location
If ($Samples.ComputerName -contains $compare)
{$Final | Add-Member -type NoteProperty -name "Active Directory" -value "Yes"}
Else
{$Final | Add-Member -type NoteProperty -name "Active Directory" -value "Yes"}
}
With contains, you want the collection to come first. (Also changes Samples/Sample for clarity)
$Samples = Import-Csv C:\Scripts\Sample_test_v1.csv
$Compare = Import-Csv C:\Scripts\Sample_AD_v1.csv
$NewSamples = foreach ($Sample in $Samples) {
If ($Compare.Computername -contains $Sample.ComputerName) {
$Sample.AD = "Yes"
} Else {
$Sample.AD = "No"
}
$Sample
}
$NewSamples | Export-Csv C:\Scripts\Sample_test_v1.new.csv -notype
I figured out my problem with the below code which works now:
$Final = #()
$Samples = Import-Csv C:\Scripts\Sample_test_v1.csv
$Compare = Import-Csv C:\Scripts\Sample_AD_v1.csv
foreach ($Sample in $Samples)
{
$Sys = New-Object System.Object
$Sys | Add-Member -type NoteProperty -name "Computer Name" -value $Sample.ComputerName
$Sys | Add-Member -type NoteProperty -name "IP Address" -value $Sample.IP
$Sys | Add-Member -type NoteProperty -name "Location" -value $Sample.Location
If ($compare.computername -contains $Sample.ComputerName )
{$Sys | Add-Member -type NoteProperty -name "Active Directory" -value "Yes"}
Else
{ $Sys | Add-Member -type NoteProperty -name "Active Directory" -value "No" }
$Final += $Sys
}

Combine columns from 2 CSV files

This seems very basic yet I can't find or figure out anywhere
I have 2 CSV files I would like to create a new one that will have matched columns.
Huge.csv
"Share","Group","Username","Name","LogonScript"
"\\SHARE\TEST","Group Test","administrator","Administrator name","(no-script)"
"\\SHARE\TEST","Group Test","user1","user name1","logon.bat"
"\\SHARE\TEST","Group Test","user2","user name2","logon.bat"
Little.csv
"Username","Computer","NetworkDrives"
administrator,PC100,M:\\share\it#N:\\share\test
user2,PC102,M:\\share\it#N:\\share\test
Desired output:
output.csv
"Share","Group","Username","Name","LogonScript","Computer","NetworkDrives"
"\\SHARE\TEST","Group Test","administrator","Administrator name","(no-script)",PC100,M:\\share\it#N:\\share\test
"\\SHARE\TEST","Group Test","user1","user name1","logon.bat",,
"\\SHARE\TEST","Group Test","user2","user name2","logon.bat",PC102,M:\\share\it#N:\\share\test
Here's the code I'm working with:
$HugeFile = Import-Csv -Path .\Huge.csv
$LittleFile = Import-Csv -Path .\Little.csv
ForEach ($entryh in $HugeFile) {
$o | add-member NoteProperty -Name "Share" -Value ($entryh.Share)
$o | add-member NoteProperty -Name "Group" -Value ($entryh.Group)
$o | add-member NoteProperty -Name "Username" -Value ($entryh.Username)
$o | add-member NoteProperty -Name "Name" -Value ($entryh.Name)
$o | add-member NoteProperty -Name "LogonScript" -Value
($entryhu.LogonScript)
ForEach ($entryl in $LittleFile) {
If ($($entryh.Username) -eq $($entryl.Username)) {
$o | add-member NoteProperty -Name "Computer" -Value ""
($entryl.Computer)
$o | add-member NoteProperty -Name "NetworkDrives" -Value ""
($entryl.NetworkDrives)
} Else {
$o | add-member NoteProperty -Name "Computer" -Value "," -Force
$o | add-member NoteProperty -Name "NetworkDrives" -Value "," -Force
}
$o | Export-Csv -NoTypeInformation .\output.csv
}
}
}
My code is not working. :/
My second problem is that I am thinking if there a better option because for each "Username" in Huge.csv I have to compare with "Username" in Little.csv.
Maybe creating a hashtable could be more optimal.
Concat Computer and Network a create a value?
Like:
key Computer+NetworkDrive
----------- ---------------------
administrator PC100,M:\\share\it#N:\\share\test
user2 PC102,M:\\share\it#N:\\share\test
Thanks a lot!
Edit
Thanks #Ansgar-Wiechers
Yes, a hashtable is probably the best way to go about this. I'd do it like this:
$additionalData = #{}
Import-Csv .\Little.csv | % {
$additionalData[$_.Username] = $_.Computer, $_.NetworkDrives
}
Import-Csv .\Huge.csv `
| select Share, Group, Username, Name, LogonScript, #{n='Computer';e={}},
#{n='NetworkDrives';e={}} `
| % {
if ( $additionalData.ContainsKey($_.Username) ) {
$_.Computer = $additionalData[$_.Username][0]
$_.NetworkDrives = $additionalData[$_.Username][1]
}
$_
} | Export-Csv -NoTypeInformation .\output.csv
Or, following #mjolinor's suggestion, using separate hashtables for computers and network drives:
$computers = #{}
$netDrives = #{}
Import-Csv .\Little.csv | % {
$computers[$_.Username] = $_.Computer
$netDrives[$_.Username] = $_.NetworkDrives
}
Import-Csv .\Huge.csv `
| select Share, Group, Username, Name, LogonScript, #{n='Computer';e={}},
#{n='NetworkDrives';e={}} `
| % {
if ( $computers.ContainsKey($_.Username) ) {
$_.Computer = $computers[$_.Username]
}
if ( $netDrives.ContainsKey($_.Username) ) {
$_.NetworkDrives = $netDrives[$_.Username]
}
$_
} | Export-Csv -NoTypeInformation .\output.csv