I'm trying to create a report which will get two sets of information, Group name and domain. The problem is that the information will be output into one column instead of two for example:
Group Member Domain
thisIsGroupMember,Domain
but I want it to be like this:
Group Member Domain
thisIsGroupMember, Domain
I also try export-csv but the created csv file only show
Length
32
Here's my code:
$appName = $findone.properties.name
$domain = (($findone.properties.adspath -split ',')[3].substring(3)
$inputstring = "$appName,$domain"
out-file -FilePath "C:\Test\Result.csv" -append -inputObject $inputstring
If your code iterates through a list of objects pulled from AD you can use something like this:
# your foreach code
{
...
$appName = $findone.properties.name
$domain = (($findone.properties.adspath -split ',')[3].substring(3)
$output += ,(New-Object -TypeName psobject -Property #{"Group Member"=$appName;"Domain"=$domain})
}
$output | Export-Csv "C:\Test\Result.csv"
$output is an array of objects being created on the fly with $appName and $domain values. It will then nicely export to a csv after all AD objects are processed.
Related
I need a quick script to convert device names to Object IDs, so that I can perform a bulk upload in Intune. I have the device names saved as a .csv which I import. After running the script the output BulkObjectID.csv comes up empty (0 kb). I am not sure what I could be doing wrong. Thanks in advance for any help.
connect-azuread
$csv = Import-Csv C:\Tools\NEW.csv
$ObjectID=#()
foreach ($DisplayName in $csv){
$ObjectID += get-AzureADDevice -Filter "DisplayName eq '$._DisplayName'" | Select ObjectID
}
$ObjectID
$ObjectID | export-csv -path 'C:\Tools\BulkObjectID.csv' -append
I tried to reproduce the same in my environment and got below results
I have few Azure AD devices existing in my tenant like below:
I created one csv file with display names of above devices like this:
Now, I ran the same script as you and got same output with empty (0 kb) BulkObjectID.csv file like below:
Connect-AzureAD
$csv = Import-Csv C:\test\new.csv
$ObjectID=#()
foreach ($DisplayName in $csv){
$ObjectID += get-AzureADDevice -Filter "DisplayName eq '$._DisplayName'" | Select ObjectID
}
$ObjectID
$ObjectID | export-csv -path 'C:\test\BulkObjectID.csv' -append
Response:
When I checked the folder, empty (0 kb) BulkObjectID.csv file is present like below:
To resolve this, modify your script by making few changes like below:
Connect-AzureAD
$csv = Import-Csv C:\test\new.csv
$ObjectID=#()
foreach ($DisplayName in $csv)
{
$name = $DisplayName.DisplayName
$ObjectID = get-AzureADDevice -Filter "DisplayName eq '$name'" | Select ObjectID
$ObjectID
$ObjectID | export-csv -path 'C:\test\ObjectID.csv' -append
}
Response:
When I checked the folder, ObjectID.csv file is present with device IDs like below:
I was hoping someone can help me out. I am trying to get the date a license was assigned to a user and export it to a new csv. The import csv contains the UserPrincipalName. I was able to narrow down to only show which license I want but having the UPN show next to the license/date would complete this script. Thanks in advance
$getusers = Import-csv -Path 'C:\test\userlist.csv'
foreach ($user in $getusers) {
(Get-AzureADUser -searchstring $User.UserPrincipalName).assignedplans | where {$_.Service -eq 'MicrosoftOffice'} | Select-Object Service,AssignedTimeStamp |
Export-CSV -Path "C:\test\userlist-export.csv" -notypeinformation
}
I would do it this way, first querying the user and storing it in a variable and then filter the AssignedPlans where Service = MicrosoftOffice. To construct the objects you can use [pscustomobject]. Worth noting, the call to Export-Csv should be the last statement in your pipeline (it shouldn't be inside the loop), otherwise you would be replacing the Csv with a new value on each loop iteration instead of appending data.
Import-Csv -Path 'C:\test\userlist.csv' | ForEach-Object {
$azUser = Get-AzureADUser -ObjectId $_.UserPrincipalName
foreach($plan in $azUser.AssignedPlans) {
if($plan.Service -eq 'MicrosoftOffice') {
[pscustomobject]#{
UserPrincipalName = $azUser.UserPrincipalName
Service = $plan.Service
AssignedTimeStamp = $plan.AssignedTimeStamp
}
}
}
} | Export-Csv "C:\test\userlist-export.csv" -NoTypeInformation
This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 5 months ago.
I wrote a script that allows me to query the whole Azure database park:
#$ErrorActionPreference = 'SilentlyContinue'
# Connect to Azure
$azureAccount = Connect-AzAccount
# Get Azure Access Token (we will use this to query the databasees)
#$azureToken = Get-AzAccessToken -ResourceUrl https://database.windows.net
$access_token = (Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
# Queries will be picked up from here
$folderPath = '.\Queries'
# Choose how to format each date ("yyyy-MM-dd") or ("yyyy-MM-dd HH:mm:ss")
$DateTime = (Get-Date).ToString("yyyy-MM-dd")
# List Azure Sunscriptions
Get-Azsubscription | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.Name)"; $a++}
$SubscriptionChoice = Read-Host -Prompt "Copy/paste the name of the Subscription that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
# Iterate into subscriptoins and print names
foreach ($gs in $SubscriptionChoice) {
Select-Azsubscription -Subscription "$gs" | Out-Null
Write-Host "Let's browse into Azure Sunscription: " -NoNewline
Write-Host (Get-AzContext).Subscription.Name -ForegroundColor green
# Fins all Azure SQL Server
Get-AzSqlServer | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.ServerName)"; $a++}
$SqlServerChoice = Read-Host -Prompt "Copy/paste the name of the SQL Server that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
if ($SqlServerChoice = "All"){
$SqlServerChoice = Get-AzSqlServer
}
Foreach ($server in $SqlServerChoice){
$DatabaseChoice = Get-AzSqlDatabase -ServerName $server.ServerName -ResourceGroupName $server.ResourceGroupName | Where-Object DatabaseName -NE "master"
Foreach ($database in $DatabaseChoice){
(Get-ChildItem $folderPath | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} ).Foreach{
Invoke-Sqlcmd -ServerInstance $server.FullyQualifiedDomainName -Database $database.DatabaseName -AccessToken $access_token -InputFile $psitem.FullName | Export-Csv -Path ".\Results\$psitem.csv" -Append -NoTypeInformation
write-host "Executing $psitem on $database.DatabaseName"
}
}
}
}
However each time the query is executed against a database the Write-Hosts returns:
Executing DTU_to_vCore.sql on Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Here a picture:
This Write-Hosts comes from the line:
write-host "Executing $psitem on $database.DatabaseName"
In which you can find the two variables:
$psitem : which is the name of the file that contains the query
$database.DatabaseName : which should be the database name but instead of printing the database name is printing Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Why one of the two variable is not interpreted?
You need to encapsulate your variable property in a subexpression operator $().
write-host "Executing $psitem on $($database.DatabaseName)"
This is because only simple variables get expanded in an expandable string.
References
Only simple variable references can be directly embedded in an
expandable string. Variables references using array indexing or member
access must be enclosed in a subexpression.
Source: about_Quoting_Rules
Subexpression operator $( )
Returns the result of one or more statements. For a single result,
returns a scalar. For multiple results, returns an array. Use this
when you want to use an expression within another expression. For
example, to embed the results of command in a string expression.
PS> "Today is $(Get-Date)"
Today is 12/02/2019 13:15:20
PS> "Folder list: $((dir c:\ -dir).Name -join ', ')"
Folder list: Program Files, Program Files (x86), Users, Windows
Source: about_Operators
I'm having a problem when outputting my foreach loop to a csv file.
My Groups are set like this:
$Groups = "Group1", "Group2", "Group3"
My code is:
$results = ForEach ($Group in $Groups) {
$memberof = get-adgroup $Group | select -expandproperty distinguishedname
Write-Output $Group
Get-ADObject -Filter 'memberof -eq $memberof -and (ObjectClass -eq "user" -or ObjectClass -eq "contact")' -properties * | select name, Objectclass, mail
Write-Output ""
Write-Output ""
}
$results | Export-csv Contacts.csv -NoTypeInformation
The problem seems to be coming from the Write-Output lines but I have no clue why. When I run my code without writing to a csv file, I get the expected result, something like:
NameOfGroup1
name Objectclass mail
---- ----------- ----
User1 user User1#mail.com
User2 user User2#mail.com
#Spaces caused by write-output ""
NameOfGroup2
User1 user User1#mail.com
Contact1 contact Contact1#externalmail.com
Then again when I run my code to write to csv file and have the write-output $Group commented out I get a similar result.
But if I run my full code from the top of this page including the write-output $Group, it comes out like this:
I've figured out what these results represent but I haven't got clue why they do print out like this.
Eseentially the numbers refer to the length of the group name, so the first 17 would be a 17 character group name, and then the number of lines below is equal to the number of contacts and users that are inside that group. The 2 zeros at the end of each group are the length of the write-output "" lines.
What is causing this behavior?
The following code will closely output what you are attempting.
$results = ForEach ($Group in $Groups) {
$memberof = get-adgroup $Group | select -expandproperty distinguishedname
Get-ADUser -Filter "memberof -eq '$memberof' -and (ObjectClass -eq 'user' -or ObjectClass -eq 'contact')" -properties name,ObjectClass,Mail | Select-Object #{n='Group';e={$Group}},name, Objectclass, mail
[pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
[pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
}
$results | Export-csv Contacts.csv -NoTypeInformation
Explanation:
Export-Csv converts an object or array of objects with properties into a CSV file. You can see the same result in the console with ConvertTo-Csv. Properties are converted into columns and property values are placed under their associated columns. When you output a string as in Write-Output $Group, it has a property of Length. To fix this, you need to add $Group as a calculated property in your Select-Object. If you want to do blank lines in your CSV, then you should output another object with all of the property values as ''.
When you mix objects in your PowerShell outputs, you can see unexpected results. Your Get-ADObject outputs a custom object. Your Write-Output lines output a string. Those two object types do not share properties. So you only see the properties for the first object in your array, which is a string. If you put all of the Write-Output statements at the end of your loop, you will see more properties in your CSV. See below for an example that just by reversing the order of processed objects, you get a different result.
$str = "string"
$obj = [pscustomobject]#{property1 = "value1"; property2 = "value2"}
$str,$obj | convertto-csv -notype
"Length"
"6"
$obj,$str | convertto-csv -notype
"property1","property2"
"value1","value2"
,
Notice the properties available to the custom object $obj and the string $str.
$obj | get-member -Type Properties
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
property1 NoteProperty string property1=value1
property2 NoteProperty string property2=value2
$str | get-member -Type Properties
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}
#Function to get the computerlist: Name,OS,IPv4, IPv6,DiskInfo
function Get-ComputerListnDiskInfo{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$True)] [string[]]$ComputerName
)
BEGIN {
Import-Module ActiveDirectory -Cmdlet Get-ADComputer -ErrorAction SilentlyContinue
}
PROCESS {
try{
$computerinfo = Get-ADComputer -Filter * -Properties OperatingSystem
#Information about Name,Ipv4,IPv6,Device,VolumeName,Free,Busy,Size,Pfree,Pbusy for ALL COMPUTERS container
$AllComputerInfo = #()
foreach ($comp in $computerinfo){
#Testing if computers is ON LINE
$TestCon = Tester $comp.name
$test = $TestCon.BooleanV
if($test) {
#write-output "$Test"
$PhysicalDisks = Get-WMIObject -computername $comp.name -query "SELECT * from win32_logicaldisk where DriveType = 3" | Select Deviceid,VolumeName,FreeSpace,Size
$Target = #()
#Create the Object foreach disk and append in the Target Variable
$GetOPNHealthStatus = Get-PhysicalDisk | select FriendlyName,OperationalStatus,HealthStatus
Write-Output "$PhysicalDisk.count"
#write-output $GetOPNHealthStatus.OperationalStatus
$i=0
foreach ($disk in $physicalDisks){
#Get all Items: size,free,busy,pfree and pbusy disk space info (can add a number at the end to set decimals)
$Size=FormatNSetSizeFreeSpace $disk.Size
$Free=FormatNSetSizeFreeSpace $disk.FreeSpace
$Busy=FormatNSetBusySpace $disk.Size $disk.FreeSpace
$Pfree=PercentFreeBusy $Free $size
$PBusy=PercentFreeBusy $Busy $size
#Create a new Object using all the info
$result =New-Object PSObject -Property #{
Device=$disk.DeviceID
VolumeName=$disk.VolumeName
Size=$Size
Free=$Free
Busy=$Busy
Pfree = $PFree
PBusy = $PBusy
OPStatus = $GetOPNHealthStatus.OperationalStatus[$i]
HStatus = $GetOPNHealthStatus.HealthStatus[$i]
}
$i++
#add this info to the target array
$Target+= $result
}
#Add all info into new object
$allIComnDiskInfo=New-Object PSObject -Property #{
Name = $comp.Name
OS = $comp.OperatingSystem
IPV4 = $TestCon.IPv4
IPV6 = $TestCon.IPv6
disksInfo = $Target
}
#and Fill any just add this info to the $Allcomputer info (just online computer's)
$AllComputerInfo+= $allIComnDiskInfo
}
}
return $AllComputerInfo
}
Catch{
Write-Warning $_.Exception.Message
}
}
}
$test = Get-ComputerListnDiskInfo
running $test
$test = Get-ComputerListnDiskInfo
$test
disksInfo : {#{PBusy=8,148; VolumeName=; Busy=10,306; Pfree=91,853; Free=116,178; Device=C:; Size=126,483; OPStatus=O; HStatus=H}}
Name : DC2012
OS : Windows Server 2012 R2 Standard
IPV4 : 192.168.1.251
IPV6 : fe80::cd63:76bf:3d2b:340f%12
And running
$test | Export-Csv here.csv
I got this:
#TYPE System.String
"Length"
"6"
Why is happening this?
Why I don't get all this info?
And how should I search the info contained in the "diskInfo" variable
I tried to pass this $test variable to another function to format it and It seem not to work:
Thank you in advance for the answers
To start out with, you aren't just outputting a custom object, or an array of custom objects. But that's not the first problem I see. The first problem I see is that you have this big function that has a parameter, and then you do this:
$test = Get-ComputerListnDiskInfo
So you call that function with no arguments, so it has no computer to run it against. Some of the parts of the function will probably default to the local computer, but will they all? I don't know, maybe.
So what does $test actually contain? An array. Of what? Well, the first thing that the function outputs is a string:
Write-Output "$PhysicalDisk.count"
So the first item in your array is a string. Then you build a bunch of custom objects and arrays, and what not, and you Return those. Great, the next item in your $test array is a custom object. But $test is not an array of custom objects, or a single custom object, it is an array with a variety of things within it.
That is why Export-CSV will not work.
Basically the issue is this one:
I have an system.object[] in the output while using CSV.
object or similar output when using export-csv