How to add a member to an existing PowerShell object? - powershell

The following powershell gets an object of Computer System information:
> $o = Get-WmiObject -Class Win32_ComputerSystem -ComputerName .
> $o
# output
# Domain : somedomain.com
# Manufacturer : VMware, Inc.
# Model : VMware Virtual Platform
# Name : MYSERVER
# PrimaryOwnerName : Windows User
# TotalPhysicalMemory : 17179332608
I add a new member TotalPhysicalMemoryGB to the object $o, as follows:
> $o = Add-Member -Input $o #{TotalPhysicalMemoryGB=([math]::round($t.TotalPhysicalMemory / 1GB))} -PassThru
This appears to work as I can access the member:
> $o.TotalPhysicalMemoryGB
# output
# 16
However, when I print the whole object again, the member TotalPhysicalMemoryGB does not appear in the member list:
> $o
# output
# Domain : somedomain.com
# Manufacturer : VMware, Inc.
# Model : VMware Virtual Platform
# Name : MYSERVER
# PrimaryOwnerName : Windows User
# TotalPhysicalMemory : 17179332608
What am I doing wrong? How can I get the new member included when I print $o?

You don't print the whole object by just output it to the console. There is a predefined view that specifies which properties of a System.Management.ManagementObject#root\cimv2\Win32_ComputerSystem is printed.
You can get a full list of all properties by using the Format-List cmdlet:
$o | Format-List *
Now you will find your previously added property.
As a workaround, you could also manually select the properties you want to output by using the Select-Object cmdlet:
$o | Select-Object Domain, Manufacturer, Model, Name, PrimaryOwnerName, TotalPhysicalMemory, TotalPhysicalMemoryGB

Related

Export/Import Printer .DRS file with PowerShell

I have 30+ Windows 2012 r2 servers, each with 30+ Zebra printers installed.
I want to be able to use PowerShell import (and export) the human readable .DRS files that can be generated with the print management UI in both the Preferences and Default locations.
I have seen lots of mentions of this: RUNDLL32.EXE PRINTUI.DLL,PrintUIEntry for import/export settings, but the file is not particularly readable, does not conform with requirements to store .DRS files, and I can't seem to get it to import the settings anyway.
I have admin on these servers, I am open to using the reg. but my understanding is that Zebras do custom things in the Devmode key - so it is not just a simple reg dump and conversion
I can use Get-PrintConfiguration and Get-CimInstance but not seeing Darkness, Speed, etc. in these outputs
$printerName = "Zebra_1"
$compNameSource = $env:COMPUTERNAME
$Printer = Get-CimInstance -ClassName Win32_Printer -Filter "Name='$PrinterName'"
$somePrinterConfig = Get-PrintConfiguration -ComputerName $compNameSource -PrinterName $printerName
$Printer.PSObject.Properties | ForEach-Object {
$_.Name, $_.Value
}
$somePrinterConfig.PSObject.Properties | ForEach-Object {
$_.Name, $_.Value
}
output:
Name : Caption
Value : Zebra_1
CimType : String
Flags : Property, ReadOnly, NotModified
IsValueModified : False
Name : Description
Value :
CimType : String
Flags : Property, ReadOnly, NotModified, NullValue
....
.DRS file:
[FileInfo]
Type=Driver Configuration File
Printer Type=201
[Barcodes]
BarcodeNum=6
[BARFONT0]
Name=EAN 13
UseHeight=1
JoinMode=2
StripTrailingSpaces=1
Kind=0
ID=1
Height=160
Expansion=1
Ratio=16908546
Flags=6164
…
[Parameters]
PaperSize=256
FormName=U
PageWidth=508
PageHeight=254
HDPI=300
VDPI=300
Orientation=3
Quantity=1
Cutter=0
BatchCut=0
Darkness=26
Speed=2
…

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

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
#>

PowerShell Scripting for System Center VMM

Am new to scripting kindly help me write a script that will connect to VMM and get details such as below.
Name : ABC Machine
CPUCount : 8
Memory : 8192
DynamicMemoryEnabled : False
VHDType : DynamicallyExpanding
MaximumSize : 214748364800
Size : 4194304
Location : C:\ClusterStorage\Volume3\CRB\CRB Test Machine_disk_1.vhdx
Classification : Silver
VHDType : DynamicallyExpanding
MaximumSize : 4748364800
Size : 41304
Location : C:\ClusterStorage\Volume2\CRB\CRB Test Machine_disk_2.vhdx
Classification : Silver
I have been able to get individual commands to get the info however I am not able to make a script that will do it for all VMs and convert disk sizes to GB
My working commands are
Get-SCVirtualMachine -Name "ABC Machine" | select Name, CPUCount, Memory, DynamicMemoryEnabled | fl
$DiskINfo = Get-SCVirtualDiskDrive -VMMServer "abc.abcgroupcloud.com" -VM "ABC Machine"
$DiskINfo.VirtualHardDisk | select VHDType, MaximumSize, Size, Location, Classification
1- create an array with all the VM names (or read it from a file with get-content)
2- use a foreach loop to excecute you script over all these VM
3- use a calulated property to display the size in Gb
$computers=#("ABC machine","XYZ machine")
$computers | foreach-object {
Get-SCVirtualMachine -Name $_ | select Name, CPUCount, Memory, DynamicMemoryEnabled | fl
$DiskINfo = Get-SCVirtualDiskDrive -VMMServer "abc.abcgroupcloud.com" -VM $_
$DiskINfo.VirtualHardDisk | select VHDType, MaximumSize, #{Name="Size in Gb";Expression={$($_.size)Mb / 1Gb}}, Location, Classification
}
Old question, but just to add some info.
This will get all the Virtual Machines in your host group in VMM, after entering the correct host group name.
$VMs will be the array, which will contain all the details you are after.
$hg = Get-SCVMHostGroup -Name "My Hostgroup Name"
$hosts = Get-SCVMHost -VMHostGroup $hg
$VMs = $null
ForEach ($h in $hosts)
{
$VMs += Get-SCVirtualMachine -VMHost $h
}

I am trying to write a PowerShell script that will combine 2 WMI commands together

Get-WmiObject -Class Win32_ComputerSystem; -Class Win32_Bios -ComputerName computer001, computer002 | Name, Caption, Identifyingnumber, vendor, UserName Export-CSV ComputerList.csv
Is what I have so far.
I am trying to get this type of output
Model: OptiPlex 760
Name: Computer006
UserName: Domain\UserName
SerialNumber: M4RQFQZ
If it can be exported into excel with headers, that would be great too. I have 10 remote stores I need to run this for.
You need to use one Get-WmiObject-call per WMI class and create a custom object with the combined data. Ex:
#$servers = "computer001", "computer002"
$servers = "localhost", "localhost" #test
$servers | ForEach-Object {
$CS = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $_
$BIOS = Get-WmiObject -Class Win32_Bios -ComputerName $_
New-Object -TypeName psobject -Property #{
Model = $CS.Model
Name = $CS.Name
UserName = $CS.UserName
SerialNumber = $BIOS.SerialNumber
}
}
UserName Name Model SerialNumber
-------- ---- ----- ------------
FRODEPC\Frode FRODEPC System Product Name System Serial Number
FRODEPC\Frode FRODEPC System Product Name System Serial Number
You could use pipe it through Format-List Model, Name, UserName, SerialNumber to get a list-view, but I won't work if you want to export it (to export, pipe it directly to Export-CSV ...)
Model : System Product Name
Name : FRODEPC
UserName : FRODEPC\Frode
SerialNumber : System Serial Number
Model : System Product Name
Name : FRODEPC
UserName : FRODEPC\Frode
SerialNumber : System Serial Number
As you can see I have a custom built computer, but it should display proper model and serialnumber values for a prebuilt OEM-machine.

NetBIOS domain of computer in PowerShell

How can I get the NetBIOS (aka 'short') domain name of the current computer from PowerShell?
$ENV:USERDOMAIN displays the domain of the current user, but I want the domain that the current machine is a member of.
I've discovered you can do it pretty easily in VBScript, but apparently ADSystemInfo isn't very nice to use in PowerShell.
Update
Here's my final solution incorporating the suggestion of using Win32_NTDomain, but filtering to the current machine's domain
$wmiDomain = Get-WmiObject Win32_NTDomain -Filter "DnsForestName = '$( (Get-WmiObject Win32_ComputerSystem).Domain)'"
$domain = $wmiDomain.DomainName
In most cases, the default NetBIOS domain name is the leftmost label in the DNS domain name up to the first 15 bytes (NetBIOS names have a limit of 15 bytes).
The NetBIOS domain name may be changed during the installation of the Active Directory, but it cannot be changed.
The WIN32_ComputerSystem WMI object gives informations on a Windows computer
PS C:\> Get-WmiObject Win32_ComputerSystem
Domain : WORKGROUP
Manufacturer : Hewlett-Packard
Model : HP EliteBook 8530w (XXXXXXXXX)
Name : ABCHPP2
PrimaryOwnerName : ABC
TotalPhysicalMemory : 4190388224
So the domain Name is given by :
PS C:\> (gwmi WIN32_ComputerSystem).Domain
But in domain installation, the DNS name is given. In this case, you can use nbtstat -n command to find the NetBIOS domain name which is displayed like this <DOMAIN><1B>.
The PowerShell Command may be :
nbtstat -n | Select-String -Pattern "^ *(.*) *<1B>.*$" | % {$_ -replace '^ *(.*) *<1B>.*$','$1'}
Here is another way using WMI
PS C:\> (gwmi Win32_NTDomain).DomainName
Use env: to get environment settings through PowerShell
NetBIOS: $env:userdomain
FQDN: $env:userdnsdomain
To see all the values:
dir env: (no $)
import-module activedirectory
(Get-ADDomain -Identity (Get-WmiObject Win32_ComputerSystem).Domain).NetBIOSName
From Here
# Retrieve Distinguished Name of current domain.
$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Root = $Domain.GetDirectoryEntry()
$Base = ($Root.distinguishedName)
# Use the NameTranslate object.
$objTrans = New-Object -comObject "NameTranslate"
$objNT = $objTrans.GetType()
# Invoke the Init method to Initialize NameTranslate by locating
# the Global Catalog. Note the constant 3 is ADS_NAME_INITTYPE_GC.
$objNT.InvokeMember("Init", "InvokeMethod", $Null, $objTrans, (3, $Null))
# Use the Set method to specify the Distinguished Name of the current domain.
# Note the constant 1 is ADS_NAME_TYPE_1779.
$objNT.InvokeMember("Set", "InvokeMethod", $Null, $objTrans, (1, "$Base"))
# Use the Get method to retrieve the NetBIOS name of the current domain.
# Note the constant 3 is ADS_NAME_TYPE_NT4.
# The value retrieved includes a trailing backslash.
$strDomain = $objNT.InvokeMember("Get", "InvokeMethod", $Null, $objTrans, 3)
OP is after "computer domain" so the answer would be $GetComputerDomain (below) but I will add the $GetUserDomain also for reference.
$GetComputerDomain = ([System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain()).Name
$GetUserDomain = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).Name
I find the wmi (gwmi) option to be extremely slow, especially, when you are querying the Win32_NTDomain class. I have a multi-trusted domain environment and it takes forever when I just need that simple info quick.
Use the Active Directory Cmdlet Get-ADDomain:
(Get-ADDomain -Current LocalComputer).NetBIOSName
The below powershell command works great! I tested after trying various solutions.
If you use the following .Net command:
[System.Net.Dns]::GetHostByAddress('192.168.1.101').hostname
It works too, but it is using DNS to resolve, in my case, we have WINS setup to support an application that requires it, so can't use it. Below is what I ended up using as part of a script I use to check for WINS registration for each client:
$IPAddress = "<enterIPAddress>" (remove brackets, just enter IP address)
(nbtstat -A $IPAddress | ?{$_ -match '\<00\> UNIQUE'}).Split()[4]
http://social.technet.microsoft.com/Forums/en-US/f52eb2c7-d55d-4d31-ab4e-09d65d366771/how-to-process-cmd-nbtstat-a-ipaddress-output-and-display-the-computer-name-in-powershell?forum=ITCG
The above link has the thread and conversation.
Using NetGetJoinInformation and P/Invoke:
Add-Type -MemberDefinition #"
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern uint NetApiBufferFree(IntPtr Buffer);
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int NetGetJoinInformation(
string server,
out IntPtr NameBuffer,
out int BufferType);
"# -Namespace Win32Api -Name NetApi32
function GetDomainName {
$pNameBuffer = [IntPtr]::Zero
$joinStatus = 0
$apiResult = [Win32Api.NetApi32]::NetGetJoinInformation(
$null, # lpServer
[Ref] $pNameBuffer, # lpNameBuffer
[Ref] $joinStatus # BufferType
)
if ( $apiResult -eq 0 ) {
[Runtime.InteropServices.Marshal]::PtrToStringAuto($pNameBuffer)
[Void] [Win32Api.NetApi32]::NetApiBufferFree($pNameBuffer)
}
}
This can also be done by using .NET framework (which is much faster than WMI)
PS > [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
Will return
HostName : SurfaceBook
DomainName : mydomain.com
NodeType : Hybrid
DhcpScopeName :
IsWinsProxy : False
Using the ADSystemInfo COM object should work, with no delay from Win32_NTDomain lookup:
$ADSystemInfo = New-Object -ComObject "ADSystemInfo"
$ADSystemInfo.GetType().InvokeMember("DomainShortName", "GetProperty", $null, $ADSystemInfo, $null)
There are other AD-related properties available from this COM object too:
https://learn.microsoft.com/en-us/windows/win32/adsi/iadsadsysteminfo-property-methods
[EDITED - Originally included code for the WinNTSystemInfo COM object instead but a commenter pointed out this only returns the user's short domain - but ADSystemInfo does return the computer's short domain]
Here is another faster method than Win32_NTDomain, for getting the NetBIOS domain of the computer.
# Get the computer system CIM/WMI
$computersystem = Get-CimInstance Win32_ComputerSystem
# Create a Windows Identity Principal object based on the name and domain in Win32_ComputerSystem
$ComputerPrincipal = [System.Security.Principal.WindowsIdentity]::new("$($computersystem.name)#$($computersystem.domain)")
# Split the NetBIOS name on \ and get the first value which should be the domain
($ComputerPrincipal.Name -split "\\")[0]
# Bonus point, the WindowsIdentity Principal has a bunch of other useful information.
# Like quick enumeration of the groups it's in (but needs to be translated from SID to NTAccount format).
$ComputerPrincipal.Groups.Translate([System.Security.Principal.NTAccount]).value