Obtain display name with spaces from powershell or cmd - AzuredAD only - powershell

I am try to pull just the display name (first and last name) from cmd or powershell. (AzureAD - not on-prem AD)
I have gotten a couple of different commands but all of them keep the name together.
Examples:
$env:UserName = jatonjustice
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name = azureAD\jatonjustice
I am trying to find a way where the result has the first and last name separated or maybe just the first and just the last name as an alternate idea.(Like: `Jaton Justice') I can't parse it myself as I don't know what the display name will be upfront. (AzureAD - not on-prem AD)
Any ideas for this?
research:
How do I get the current username in Windows PowerShell?
How to get an Azure Active Directory username in Windows Powershell?
Thanks

$env:UserName should return SamAccountName, rather than user's name.
'Get-ADUser -Property *' should show you all info about the user you are querying, you should be able to find a property called GivenName and Surname.

$search = [adsisearcher]"(SamAccountName=$env:USERNAME)"
$search.PropertiesToLoad.AddRange(#('givenname','sn'))
$adAccount = $search.FindOne()
$firstName = $adAccount.Properties.givenname
$lastName = $adAccount.Properties.sn
$fullname = "$firstName $lastName"

All you are after is explained and detailed by examples in the PowerShell help files. More on that later.
As for ...
'but all of them keep the name together. Examples:'
...and they are supposed to, by design.
Using those, you are asking for the local logged-on username (SamAccountName, which is a short name defined in the user profile on the localhost and in ADDS/AAD - for the UPN, SamAccountName#DomainName.com) with those, not ADDS/AAD name specifics.
If you want First and last from the locally logged-on user, then you have to have that populated in the account, or you have to ask for it from ADDS/AAD. What is your use case?
If you are on PSv5x and higher there is this module:
# Results
<#
Get-Module -Name '*local*'
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Binary 1.0.0.0 Microsoft.PowerShell.LocalAccounts {Add-LocalGroupMember, Disable-LocalUser, Enable-LocalUser, Get-LocalGroup...}
#>
You get local user details this way.
Get-LocalUser | Select-Object -Property '*' -First 1
# Results
<#
AccountExpires :
Description : Built-in account for administering the computer/domain
Enabled : False
FullName :
PasswordChangeableDate :
PasswordExpires :
UserMayChangePassword : True
PasswordRequired : True
PasswordLastSet :
LastLogon :
Name : Administrator
SID : S-1-5-21-2047949552-857980807-821054962-500
PrincipalSource : Local
ObjectClass : User
#>
Note that on his local account, Fullname is not populated. So, obviously, you can't use that, nor can you extrapolate from the name/SamAccoutnName property.
So, you can ask for the locally logged on username in a number of ways,...
# Get loggedon users
$env:UserName
[System.Environment]::UserName
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
(Invoke-CimMethod -InputObject $(
Get-CimInstance Win32_Process -Filter "name = 'explorer.exe'"
) -MethodName GetOwner).User
Get-WmiObject Win32_Process -Filter "name='explorer.exe'" |
Select Name, #{
Name = 'UserName'
Expression = {"$($PSItem.GetOwner().Domain)\$($PSItem.GetOwner().User)"}
} |
Sort-Object UserName, Name
(Get-Process -Name 'explorer' -IncludeUserName).UserName
(
Get-WMIObject -ClassName Win32_ComputerSystem |
Select-Object -Property Username
).username
[adsisearcher]"(SamAccountName=$env:USERNAME)"
whoami
... then use that Name/SamAccountName to ask ADDS/AAD what the user FullName or whatever you wish is.
If you are on an earlier version, you need to install one of these modules from Microsofts' powershelgallery.com...
Find-Module -Name '*local*'
# Results
<#
Version Name Repository Description
------- ---- ---------- -----------
...
1.6 localaccount PSGallery A Simple module to allow the management of local users and groups on a computer
1.0.0.0 Microsoft.PowerShell.LocalAccounts PSGallery Provides cmdlets to work with local users and local groups
3.0 LocalUserManagement PSGallery a module that performs various local user management functions
...
0.1.1 LocalAccountManagement PSGallery Manage local and remote user accounts and profiles
...
#>
... and do the same thing or use WMI, ADSI, etc.
[adsisearcher]"(SamAccountName=$env:USERNAME)"
# Results
<#
CacheResults : True
ClientTimeout : -00:00:01
PropertyNamesOnly : False
Filter : (SamAccountName=TestUser)
PageSize : 0
PropertiesToLoad : {}
ReferralChasing : External
SearchScope : Subtree
ServerPageTimeLimit : -00:00:01
ServerTimeLimit : -00:00:01
SizeLimit : 0
SearchRoot :
Sort : System.DirectoryServices.SortOption
Asynchronous : False
Tombstone : False
AttributeScopeQuery :
DerefAlias : Never
SecurityMasks : None
ExtendedDN : None
DirectorySynchronization :
VirtualListView :
Site :
Container :
#>
Now, back to my 'read the help file comment.'
Get-ADUser | MS DOcs
https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-aduser?view=windowsserver2019-ps
# Example 3: Get all of the properties for a specified user
Get-ADUser -Identity $env:USERNAME -Properties '*'
# Results
<#
Surname : David
Name : Chew David
UserPrincipalName :
GivenName : David
Enabled : False
SamAccountName : ChewDavid
ObjectClass : user
SID : S-1-5-21-2889043008-4136710315-2444824263-3544
ObjectGUID : e1418d64-096c-4cb0-b903-ebb66562d99d
DistinguishedName : CN=Chew David,OU=NorthAmerica,OU=Sales,OU=UserAccounts,DC=FABRIKAM,DC=COM
#>

Related

PowerShell 5.1 using ExpandedProperty but not getting desired output

Given:
PowerShell 5.1
If I run the following:
Get-Service -ComputerName WKSP000D1E3F -DisplayName *bit*
I get this:
Status Name DisplayName
------ ---- -----------
Stopped BDESVC BitLocker Drive Encryption Service
Stopped Check Point Bit... Check Point Endpoint Security Bitlo...
But I want to expand both Name and DisplayName, so I do this:
Get-Service -ComputerName WKSP000D1E3F -DisplayName *bit* | Select -ExpandProperty Name
and get this:
BDESVC
Check Point Bitlocker Management
How do I get all the columns with column headers, like the first output above except without ellipses?
Status Name DisplayName
------ ---- -----------
Stopped BDESVC BitLocker Drive Encryption Service
Stopped Check Point Bit... Check Point Endpoint Security Bitlo...
Get-Service -DisplayName *wmi*
Status Name DisplayName
------ ---- -----------
Stopped wmiApSrv WMI Performance Adapter
Running WMIRegistrationSe… Intel(R) Management Engine WMI Provid…
I find myself using | Out-GridView if desired output isn't being shown.
Get-Service -DisplayName *wmi* |
Out-GridView
Out-GridView Result
Alternatively, you could use | Format-List if you're not set on using Table View
Get-Service -DisplayName *wmi* |
Format-List
Name : wmiApSrv
DisplayName : WMI Performance Adapter
Status : Stopped
DependentServices : {}
ServicesDependedOn : {}
CanPauseAndContinue : False
CanShutdown : False
CanStop : False
ServiceType : Win32OwnProcess
Name : WMIRegistrationService
DisplayName : Intel(R) Management Engine WMI Provider Registration
Status : Running
DependentServices : {}
ServicesDependedOn : {}
CanPauseAndContinue : False
CanShutdown : False
CanStop : True
ServiceType : Win32OwnProcess
If you only want Status,Name,DisplayName headers,
Get-Service -DisplayName *wmi* |
Select-Object -Property Status, Name, DisplayName |
Format-List
Status : Stopped
Name : wmiApSrv
DisplayName : WMI Performance Adapter
Status : Running
Name : WMIRegistrationService
DisplayName : Intel(R) Management Engine WMI Provider Registration
The ... are just a display problem (the data is there in full).
If you use Select-Object's -ExpandProperty parameter, you by definition only get property values, and since these values are strings in your case, that's all you get (albeit without truncation).
To prevent the for-display truncation, pipe to Format-Table -AutoSize, though note that this requires PowerShell to collect all output from the input command first, before starting to display output (see next section for alternatives).
Get-Service -ComputerName WKSP000D1E3F -DisplayName *bit* | Format-Table AutoSize
Note: Since the console (terminal) window width is always the limiting factor, -AutoSize can result in fewer columns getting displayed.
If possible, you can exclude columns that aren't of interest, by specifying only those that are, via -Property (you may omit this parameter name, becasue it is positionally implied); e.g.:
Get-Service -ComputerName WKSP000D1E3F -DisplayName *bit* |
Format-Table -Property Status, Name -AutoSize
Alternatives that avoid -AutoSize and its collect-everything-first behavior:
Use -Wrap, which doesn't truncate, but uses (artificial) line breaks to spread values that don't fit into the column across multiple lines.
Get-Service -ComputerName WKSP000D1E3F -DisplayName *bit* | Format-Table -Wrap
If you know the maximum width of a column of interest ahead of time, you can use a calculated property to prescribe a column's width; e.g.:
Get-Service -ComputerName WKSP000D1E3F -DisplayName *bit* |
Format-Table Status,
#{ Expression='Name'; Width=40 },
DisplayName

Strange DNS record duplication with Powershell?

While recently working with the native Powershell DNS commandlets, specifically Get-DNSServerResourceRecord, I noticed something strange that does not make sense to me.
When I look into my zone using native DNS tools, LDAP query tools, or even ADSIedit, I see only a single DNS object representing a given hostname.
However, when I do the same with Powershell, I instead get two objects for a given host, one for the NETBIOS name, and the other for the FQDN. All other attributes are the same, including the IP.
For example, if I had a computer named computer1: This is what I see.
PS C:\> Get-DnsServerResourceRecord -ZoneName 'mydomain.local' -RRType A -ComputerName 'DNSServer1' | Where-Object {$_.hostname -like "Computer1*"} | fl *
DistinguishedName : DC=computer1.mydomain.local,DC=mydomain.local,cn=MicrosoftDNS,DC=DomainDnsZones,DC=mydomain,DC=local
HostName : COMPUTER1.mydomain.local
RecordClass : IN
RecordData : DnsServerResourceRecordA
RecordType : A
Timestamp :
TimeToLive : 01:00:00
Type : 1
PSComputerName :
CimClass : root/Microsoft/Windows/DNS:DnsServerResourceRecord
CimInstanceProperties : {DistinguishedName, HostName, RecordClass, RecordData...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
DistinguishedName : DC=computer1,DC=mydomain.local,cn=MicrosoftDNS,DC=DomainDnsZones,dc=mydomain,dc=local
HostName : COMPUTER1
RecordClass : IN
RecordData : DnsServerResourceRecordA
RecordType : A
Timestamp :
TimeToLive : 01:00:00
Type : 1
PSComputerName :
CimClass : root/Microsoft/Windows/DNS:DnsServerResourceRecord
CimInstanceProperties : {DistinguishedName, HostName, RecordClass, RecordData...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
I'm so confused at why Powershell is showing this and where it's actually pulling it from. I cannot locate those FQDN objects using native LDAP tools, even ADFind.
Is this some weird artifact/bug of the Powershell DNS cmdlets? Or does DNS records store dual entries for a given host, but only display one using native tools?
Neither make sense to me, as I would not expect a cmdlet to just make up DN values on the fly, and this doesn't occur for all host records.The latter does not seem possible as this is not occurring for all records in the zone. I have about 100 more records without the fqdn than with (10926 vs 10824).
EDIT If it helps, here is an ADFind query for the same object (and wildcard).
C:\temp>adfind -h dnsserver1 -domaindns -f "(&(name=computer1*))" name
AdFind V01.57.00cpp Joe Richards (support#joeware.net) November 2021
Using server: dnsserver1.mydomain.local:389
Directory: Windows Server 2016
Base DN: DC=DomainDnsZones,DC=ad,DC=ewsad,DC=net
dn:DC=computer1,DC=mydomain.local,CN=MicrosoftDNS,DC=DomainDnsZones,DC=mydomain,DC=local
>name: computer1
1 Objects returned
I can confirm this behavior.
In powershell, this returns 2 results for many of the computers (maybe all, I didn't check)
Get-DnsServerResourceRecord -ZoneName 'domain.com' -RRType A -ComputerName dnserver1 | where hostname -like Computer1*
DistinguishedName : DC=Computer1.domain.com,DC=domain.com,cn=MicrosoftDNS,DC=DomainDnsZones,DC=domain,DC=com
HostName : Computer1.domain.com
RecordClass : IN
RecordData : DnsServerResourceRecordA
RecordType : A
Timestamp : 12/8/2022 9:00:00 AM
TimeToLive : 00:20:00
Type : 1
PSComputerName :
CimClass : root/Microsoft/Windows/DNS:DnsServerResourceRecord
CimInstanceProperties : {DistinguishedName, HostName, RecordClass, RecordData...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
DistinguishedName : DC=Computer1,DC=domain.com,cn=MicrosoftDNS,DC=DomainDnsZones,DC=domain,DC=com
HostName : Computer1
RecordClass : IN
RecordData : DnsServerResourceRecordA
RecordType : A
Timestamp : 12/8/2022 9:00:00 AM
TimeToLive : 00:20:00
Type : 1
PSComputerName :
CimClass : root/Microsoft/Windows/DNS:DnsServerResourceRecord
CimInstanceProperties : {DistinguishedName, HostName, RecordClass, RecordData...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
But a dsquery results in one record.
dsquery computer -name computer1* -s dnsserver1
"CN=Computer1,OU=Computers,DC=domain,DC=com"
You can confirm only one of these is a real AD object.
$recordlist = Get-DnsServerResourceRecord -ZoneName 'domain.com' -RRType A -ComputerName dnserver1 | where hostname -like Computer1*
foreach($record in $recordlist){
Write-Host "Checking DN $($record.DistinguishedName)" -ForegroundColor Cyan
$found = $record.DistinguishedName |
Get-ADObject -ErrorAction SilentlyContinue
if($found){
Write-Host "Record found in AD" -ForegroundColor Green
}
else{
Write-Host "Record not in AD" -ForegroundColor DarkGray
}
}
So I must conclude thus far the evidence does indicate the Get-DnsServerResourceRecord is adding a duplicated record with the FQDN as well. Hopefully someone can find or knows why it was implemented in this manner.

The server is unwilling to process request

I am trying use powershell to add OU called Calder under an OU called Branches but I keep getting the error New-ADOrganizationalUnit : The server is unwilling to process the request., Also I am running powershell as a admin
Here is what I put in powershell
New-ADOrganizationalUnit "Calder" -Path "OU=Branches, DC=company.epl, DC=local
Here is the full error
New-ADOrganizationalUnit : The server is unwilling to process the
request At line:1 char:1
+ New-ADOrganizationalUnit "Calder" -Path "OU=Branches, DC=company.epl …
+ + CategoryInfo :NotSpecified: (OU=Calder, OU+Br...y.epl, DC=local:Strin g) [New-ADOrganizationalUnit] :
ActiveDirectoryServer:O,Microsoft.ActiveDirectory.Management.Commands.NewADOrganizationalUnit
I've generally seen this error when I've got my fully qualified DN mistyped. If that is the case, using a search to grab the intended OU object helps.
PS> $MYOU = Get-ADOrganizationalUnit -filter 'Name -like "Branches"'
PS> $MYOU.DistinguishedName
OU=Branches,dc=MyCompany,dc=ccTLD
PS> New-ADOrganizationalUnit "Calder" -Path $MYOU.DistinguishedName
PS> Get-ADOrganizationalUnit -filter 'Name -like "Calder"'
City :
Country :
DistinguishedName : OU=Calder,OU=Branches,dc=MyCompany,dc=ccTLD
LinkedGroupPolicyObjects : {}
ManagedBy :
Name : Calder
ObjectClass : organizationalUnit
ObjectGUID : 559c4242-505a-c165-15d5-562b5fb99103
PostalCode :
State :
StreetAddress :
If it's not just an incorrect OU path, try appending -Verbose to the command and see if there's a better indication of what exactly went awry.

How to get object type/identifier?

In PowerShell, when I work with Active Directory specifically, often I'll compile an object containing a list of groups of people usually with $x = get-adgroup -filter {name -like "*"} | select-object name which gives me a list with a header or object type name:
name
----------
name1
name2
name3
How can I access the name header of the object or even change it to something else?
Can it be done similarly to the way I would access the string of the first entry like $x[0].name?
Further, is there a more generic way to access the string associated with an arbitrary entry?
I'm being asked to a lot of "programming" in PowerShell related to AD so any resources you can provide to help me would be greatly appreciated.
If you want to change the name you can create an expression for it in your select block:
get-adgroup -filter {name -like "*"} | select-object #{Name="WhatYouWannaCallIt";Expression={$_.Name}}
This would now give you:
WhatYouWannaCallIt
------------------
name1
name2
name3
The two things that I think you are asking for is a programmatic way to determine the name of a given property in an object.
(get-aduser $user | select name).psobject.properties
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : Matt
TypeNameOfValue : System.String
Name : name
IsInstance : True
The Name property of .psobject.properties contains most of this information and I think you might be looking for.
Was going to answer the second part with what Arco444 just said about using select-object
Do you mean:
$x = get-adgroup -filter {name -like "*"}
$x.name
or
(get-adgroup -filter {name -like "*"}).name

how to extract the text from a Microsoft.IIs.PowerShell.Framework.ConfigurationElement object

If I run the command in powershell:
C:\Get-Website
it outputs
Name ID State Physical Path Bindings
---- -- ----- ------------- --------
Default Web Site 1 %SystemDrive%\inetpub\wwwroot http *:80:
net.tcp 808:*
net.pipe *
net.msmq localhost
msmq.formatname
localhost
But if I try to select just the Bindings:
C:\Get-Website | where {$_.Name -eq "Default Web Site"} | select Bindings
It returns:
bindings : Microsoft.IIs.PowerShell.Framework.ConfigurationElement
How do I extract the contents of this object into a useful format?
The bindings property is a collection so you have to use the ExpandProperty parameter:
Get-Website -Name "Default Web Site" | select -ExpandProperty Bindings
To drill down further:
get-website -name "Default Web Site" | select -ExpandProperty Bindings | Select -ExpandProperty Collection
Recently I was working on similar command but for list all Sites and its bindings. In IIS this is what i did :
get-childItem |
select * , #{Name="SiteBindings"; Expression = {($_.Bindings.Collection | %{$_.protocol + " " + $_.BindingInformation} | Out-String).replace("`r","" ) }}
Note the replace("`r","" ). It is needed if you need to export to CSV.
There's also the Get-WebBinding cmdlet that can be used if you don't want to start from Get-Website.
Import-Module WebAdministration
Get-WebBinding
This will display all of the binding info for all websites, and you can filter it down further from there.
Here's sample output of running the above command.
protocol : http
bindingInformation : *:80:
sslFlags : 0
isDsMapperEnabled : False
certificateHash :
certificateStoreName :
ItemXPath : /system.applicationHost/sites/site[#name='Default Web Site' and #id='1']
RunspaceId : b7052f71-a213-437c-a97f-00fb9fa84a7f
Attributes : {Microsoft.IIs.PowerShell.Framework.ConfigurationAttribute,
Microsoft.IIs.PowerShell.Framework.ConfigurationAttribute,
Microsoft.IIs.PowerShell.Framework.ConfigurationAttribute,
Microsoft.IIs.PowerShell.Framework.ConfigurationAttribute…}
ChildElements : {}
ElementTagName : binding
Methods : {Microsoft.IIs.PowerShell.Framework.ConfigurationMethod,
Microsoft.IIs.PowerShell.Framework.ConfigurationMethod,
Microsoft.IIs.PowerShell.Framework.ConfigurationMethod,
Microsoft.IIs.PowerShell.Framework.ConfigurationMethod…}
Schema : Microsoft.IIs.PowerShell.Framework.ConfigurationElementSchema