#Requires -Version 3 #Requires -module ActiveDirectory Function Convert-ADValues{ <# .Synopsis Converts all active directory values from Get-ADUser, Get-ADComputer and all other Get-AD* functions to a value which can be piped to Export-CSV. .DESCRIPTION Convert-ADvalues reads the value of each object passed to it from Get-AD* functions found in the ActiveDirectory Module. (For a list, run "Get-Command get-ad* | select -Property name") Each of these propety values is converted to a readable string. This includes dates (lastlogontimestamp, expirationdate, etc. and multi-valued attributes such as proxyaddresses. Hex values are converted to comma delimited decimal strings. Optionally included is the ntSecurityDescriptor property. .Parameter ADObject This is a Microsoft.ActiveDirectory.Management assembly object, typically from Get-ADComputer, Get-ADDOmainController, etc. .Parameter GetSecurity If switch is present, the nTSecurityDescriptor basic values are enumerated. Note that you must return the ntSecurityDescriptor in the AD object properties for this to work. .Parameter TranslateGroups If is present, group memberships are converted from distinguished name to NTDomain\SamAccountName format. You must return memberof for this. The property memberof is replace with "member" in returned results. .Parameter ExpandCerts If present, this converts the "Certificate" attributes to a readable string. It does not translate the usercertificate attribute .Parameter CertDelim This is the delimiter between multiple certificates. By default it is a new line character .Parameter ReportPropertyNamesAndCount If present, the additional query fields PropertyNames (containing a list of AD properties returned), and PropertyCount (containing a count of the list of AD properties returned) are returned. Not sure why anyone would want this, but it is included for completeness. .EXAMPLE C:\PS> $u = Get-ADUser -Filter {surname -eq "smith"} -properties * C:\PS> Convert-ADValues $u These two lines get a list of all properties for users with the last name Smith (excluding Security) .EXAMPLE C:\PS>$u = Get-ADUser -Filter {surname -eq "smith"} -properties * C:\PS>$u | Convert-ADValues | Export-CSV -notypeInformation -Path $env:userprofile\desktop\ADInfo.csv These two lines get a list of all properties for users with the last name Smith (excluding Security), and exports it to ADInfo.csv .Example C:\PS>Get-ADComputer -Identity $env:COMPUTERNAME -Properties * | Convert-ADValues This gets a list of all properties for the current computer (excluding Security) .Example C:\PS>Get-ADUser -Identity $env:USERNAME -Properties * | Convert-ADValues -GetSecurity This gets a list of all properties, including security descriptors for the current user .Example C:\PS>Get-ADUser -Identity $env:USERNAME -Properties memberof | Convert-ADValues -TranslateGroups This gets a list of default user properties and a members property from membersof in the NTDomain\Name' format. .Example C:\PS>Get-ADUser -Identity $env:USERNAME -Properties whencreated, ntSecurityDescriptor | Convert-ADValues -GetSecurity This gets a list of the default properties (DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName) plus the whenCreated and security descriptors for the current user .Example C:\PS>Get-ADForest | Convert-ADValues Get information about the current AD forest, expanding all information. (This is interesting in a large domain -- try it) .LINK http://www.akaplan.com/blog/2013/07/convert-data-from-get-aduser-and-get-adcomputer-for-export-csv/ .NOTES #alan dot kaplan at va dot gov #07-26-13 Initial version #08-05-13 Fixed handling of binary, null and empty values #08-06-13 Changed delimiter to semi-colon for values with commas #12-27-13 Added switch for enumerating ACLs for nTSecurityDescriptor, changed names of variables away from users, improved comment based help #01-02-14 Removed write-host of Security type added while debugging. Added Online Help. Moved Load-Module ActiveDirectory top, clarified Help to make clear that you must return nTSecurityDescriptor for it to be expanded with -GetSecurity. Removed return of PropertyNames and PropertyCount unless you use ReportPropertyNamesAndCount parameter. Changed output type to PSObject from Array. Added Requires statement for Version 3. #10-08-15 Added support for Microsoft.GroupPolicy.WmiFilter #02-02-16 Added new switch for getting expanded certificate information - Subject, Serial Number, Date Effective, Expires, Handle and Issuer #09-27-16 Added TranslateGroups, fixed return of certs when not present #11-18-16 Simplified and improved get-security #03-28-17 Fixed ExpandCerts, added CertDelim, added dot source reminder #> [CmdletBinding(HelpURI="http://www.akaplan.com/blog/2013/07/convert-data-from-get-aduser-and-get-adcomputer-for-export-csv/")] [OutputType([PSObject])] Param ( # $ADObject info appears in help description [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelinebyPropertyName=$true, ValueFromRemainingArguments=$false, Position=0)][Object[]]$ADObject, [Parameter(Mandatory=$false)][switch]$GetSecurity, [Parameter(Mandatory=$false)][switch]$ExpandCerts, [Parameter(Mandatory=$false)]$CertDelim="`n", [Parameter(Mandatory=$false)][switch]$ReportPropertyNamesAndCount, [Parameter(Mandatory=$False)][switch]$TranslateGroups ) Begin{ } Process { # Execute once for each pipeline (get-ad*) object $ADItem = $_ $ADObjectProps = [ordered]@{} #note that using get-member won't work here $prop = $ADItem.psobject.Properties foreach ($p in $prop){ $delim = ", " $ADPropVal=$CertPropVal="" #Create value based on the Type of Value if ($p.Value -ne $null ) { Switch ($p.TypeNameOfValue){ #this is a multi-value. Certificates are handled separately Microsoft.ActiveDirectory.Management.ADPropertyValueCollection { if($p.Name -eq "Certificates") { if ($ExpandCerts -eq $true) { $CertificateInfo = $adItem.Certificates | foreach {New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $_} foreach ($cert in $CertificateInfo){ $CertPropVal +="Subject: " + $cert.subject.ToString() + "; SerialNumber:" + $cert.SerialNumber.ToString() + "; Effective:" + $cert.NotBefore.ToString() + "; Expires:" + $cert.NotAfter.ToString() + "; Handle:" + $cert.Handle.ToString() + "; Issuer:" + $cert.Handle.ToString() + $CertDelim $ADPropVal += $CertPropVal } }Else{ $v= $p.value For ($i = 0; $i -le $v.count; $i++) { if ($v.value[$i]) { if ($v.value[$i].ToString().Contains(",")){$delim = "; "} $ADPropVal +="Subject:" + $v.value[$i].Subject.ToString() + "; Handle: " + $v.value[$i].Handle.ToString() + "; Issuer:" + $v.value[$i].Issuer.ToString() + $CertDelim } } } } #Not a certificate Else { $v= $p.value #kluge to pick up UserCertificate Array in item 0 if ($v.count -eq 1){ if ($v.value.length -lt 200 ) {$ADPropVal = $v.value.ToString()} Else { $ADPropVal = [string]::Join(",",$v.item(0))}} Else{ #All other ADPropertyValueCollection if ($v.contains(",")){$delim = "; "} For ($i = 0; $i -le $v.count; $i++) { if ($v.value[$i]) { if ($v.value[$i].ToString().Contains(",")){$delim = "; "} $ADPropVal +=$v.value[$i].ToString() + $delim } } } } $ADPropVal = $ADPropVal.TrimEnd(", ") $ADPropVal = $ADPropVal.TrimEnd("; ") $ADPropVal = $ADPropVal.TrimEnd("`n") $ADObjectProps.add($p.name,$ADPropVal) } #Second value for Switch - date value System.int64 { if ($p.value -eq 9223372036854775807){ $ADObjectProps.add($p.name,"Never") } Else { $ADObjectProps.add($p.name,[DateTime]::FromFileTime($p.Value)) } } #Third Switch #change bytes to look as they do when you look at string value System.Byte[] { $v= $p.value if ($v.count -eq 1) {$ADPropVal=$v.tostring()} Else { For ($i = 0; $i -le $v.count-1; $i++) { if ($v.item($i)) { $ADPropVal +=$v.item($i).ToString()+$delim } } } #Cleanup $ADObjectProps.add($p.name,$ADPropVal.TrimEnd($delim)) } System.DirectoryServices.ActiveDirectorySecurity { if ($GetSecurity){ $v= $p.value $v.access | foreach { $ADPropVal +=$_.IdentityReference.ToString()+" ("` +$_.AccessControlType.ToString()+" - "` +$_.ActiveDirectoryRights.ToString()+");" } }ELSE{$ADPropVal = "Security Not Enumerated"} #Cleanup $ADObjectProps.add($p.name,$ADPropVal.TrimEnd(";")) } System.Collections.ICollection{ $delim = ", " $v=$p.value.GetEnumerator().split("") For ($i = 0; $i -le $v.count; $i++) { if ($v[$i]) { $ADPropVal +=$v[$i].ToString() + $delim } } #Cleanup $ADObjectProps.add($p.name,$ADPropVal.TrimEnd(", ")) } Microsoft.GroupPolicy.WmiFilter{ $ADObjectProps.add($p.name,$p.Value.name ) $ADObjectProps.add('WMIFilter Description',$p.Value.Description) $ADObjectProps.add('WMIFilter Path',$p.value.path) } Microsoft.GroupPolicy.UserConfiguration{ $ADObjectProps.add('User Settings Enabled',$p.Value.enabled ) } Microsoft.GroupPolicy.ComputerConfiguration{ $ADObjectProps.add('Computer Settings Enabled',$p.Value.enabled ) } #all other types return as is default { if ($p.Name -ne 'CertificateInfo'){ $ADObjectProps.add($p.name,$p.Value.ToString()) } } } #Don't report PropertyNames and PropertyCounts unless requested if (!($ReportPropertyNamesAndCount)){ if ($p.Name -match "Property") {$ADObjectProps.remove($p.name)} } }ELSE{ #show empty and null values $ADObjectProps.add($p.name,"") }#ELSE ends } #ForEach Ends if (($TranslateGroups.IsPresent -eq $true) -and ($prop.name -contains "memberof")) { $GroupInfo = $ADObjectProps.MemberOf.split(";") | foreach {Get-NTNameFromDN $_.trim()} $t = ($GroupInfo | sort) -join "; " $ADObjectProps.Remove('MemberOf') $ADObjectProps.Add('Member',$t) } #convert hashtable to object. Pipelining fails without this. New-Object PSObject -property $ADObjectProps } } Function Get-NTNameFromDN($DNPath){ #Based on #http://www.itadmintools.com/2011/09/translate-active-directory-name-formats.html #Intialize NameTranslate ComObject $oNameTrans=New-Object -ComObject NameTranslate #Initialize with Global Catalog search ADS_NAME_INITTYPE_GC=3 [System.__ComObject].InvokeMember(“init”,”InvokeMethod”,$null,$oNameTrans,(3,$null)) #Take anything as input NameType UNKNOWN = 8 [System.__ComObject].InvokeMember(“Set”,”InvokeMethod”,$null,$oNameTrans,(8,$DNPath)) #Return in format NTDNAME is also 3 $NTName = [System.__ComObject].InvokeMember(“Get”,”InvokeMethod”,$null,$oNameTrans,3) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($oNameTrans) | Out-Null Return $NTName }