How to get Windows.System.Profile.SystemIdentification.Id in PowerShell? - powershell

I am trying to get a key using PowerShell that will uniquely identify a Windows computer that is relatively durable, i.e., doesn't change between re-installs of Windows.
I came across Windows.System.Profile.SystemIdentification which is part of the Windows UWP API but unfortunately so far, I have been unsuccessful in getting this with PowerShell.
How to get Windows 10 Device ID in UWP application?
I have been trying for the past several days and the farthest I have gone is the following:
PS> [Windows.System.Profile.SystemIdentification,Windows.System.Profile,ContentType=WindowsRuntime] | Out-Null
PS> $systemID = [Windows.System.Profile.SystemIdentification]::GetSystemIdForPublisher()
PS> $systemID
Id Source
-- ------
System.__ComObject Uefi
PS> $systemID | Get-Member
TypeName: Windows.System.Profile.SystemIdentificationInfo
Name MemberType Definition
---- ---------- ----------
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
ToString Method string ToString()
Id Property Windows.Storage.Streams.IBuffer Id {get;}
Source Property Windows.System.Profile.SystemIdentificationSource Source {get;}
How can I get the Id property which has a type of Windows.Storage.Streams.IBuffer Id {get;} ?

For this IBuffer you shuld use
Windows.Security.Cryptography.CryptographicBuffer.EncodeToHexString( systemID );

In case someone else comes across this, here's a working version of the info provided above...
# Use reflection syntax ( [class, namespace, contentType] ) to call GetSystemIdForPublisher()
$systemID = [Windows.System.Profile.SystemIdentification, Windows.System.Profile, ContentType = WindowsRuntime]::GetSystemIdForPublisher()
# And because PowerShell was designed for use by AI and people who think in hieroglyphics:
[Windows.Security.Cryptography.CryptographicBuffer, Windows.Security.Cryptography, ContentType = WindowsRuntime].
GetMethod('EncodeToHexString', [type[]]#([Windows.Storage.Streams.IBuffer, Windows.Storage.Streams, ContentType = WindowsRuntime])).
Invoke($null, #($systemID.Id))

Related

How to read timezone id from GET-TIMEZONE function response in powershell

I am new to powershell, so do not know what is the best way to read id of timezone from the GET-TIMEZONE function response in powershell.
The function returns response in this format
I want to read the Id value. Which is India Standard Time in this example.
Any leads?
As requested by Matt Johnson-Pint here my comment as answer.
The Get-TimeZone cmdlet returns the current time zone or a list of available time zones. Without using parameters, it returns the timezone for the local computer.
The returned value(s) are always object(s) with properties as shown in the OPs screenshot.
If you want the value of just one of these properties. you can use either the dot syntax
(Get-TimeZone).Id
which because of the brackets, makes PowerShell execute the cmdlet first and from that returned object, you pick the apropriate property to get its value.
Another way is to use Select-Object and expand the property you need in order to receive the value only like this:
Get-TimeZone | Select-Object -ExpandProperty Id
Without parameter -ExpandProperty, this will return a new object with one property named Id.
Objects usually also have methods besides properties. To show these, you can pipe the result through to another cmdlet called Get-Member (or gm for short)
Get-TimeZone | Get-Member * # using the asteriks, the cmdlet returns all members
which results in
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.TimeZoneInfo other), bool Equals(System.Object obj), bool IEquatable[TimeZoneInfo].E...
GetAdjustmentRules Method System.TimeZoneInfo+AdjustmentRule[] GetAdjustmentRules()
GetAmbiguousTimeOffsets Method timespan[] GetAmbiguousTimeOffsets(System.DateTimeOffset dateTimeOffset), timespan[] GetAmbiguousTimeOf...
GetHashCode Method int GetHashCode()
GetObjectData Method void ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Se...
GetType Method type GetType()
GetUtcOffset Method timespan GetUtcOffset(System.DateTimeOffset dateTimeOffset), timespan GetUtcOffset(datetime dateTime)
HasSameRules Method bool HasSameRules(System.TimeZoneInfo other)
IsAmbiguousTime Method bool IsAmbiguousTime(System.DateTimeOffset dateTimeOffset), bool IsAmbiguousTime(datetime dateTime)
IsDaylightSavingTime Method bool IsDaylightSavingTime(System.DateTimeOffset dateTimeOffset), bool IsDaylightSavingTime(datetime dat...
IsInvalidTime Method bool IsInvalidTime(datetime dateTime)
OnDeserialization Method void IDeserializationCallback.OnDeserialization(System.Object sender)
ToSerializedString Method string ToSerializedString()
ToString Method string ToString()
BaseUtcOffset Property timespan BaseUtcOffset {get;}
DaylightName Property string DaylightName {get;}
DisplayName Property string DisplayName {get;}
Id Property string Id {get;}
StandardName Property string StandardName {get;}
SupportsDaylightSavingTime Property bool SupportsDaylightSavingTime {get;}

Why does `[SomeType] | Get-Member -Static` return static members of `SomeType` instead of those of `System.RuntimeType`?

Let's take an example. If understand correctly, System.IO.FileStream is a class, but [System.IO.FileStream] is an object: it's an instance of the class System.RuntimeType.
If I run [System.IO.FileStream] | Get-Member, I'll get the members of System.RuntimeType (technically, of its instance):
TypeName: System.RuntimeType
Name MemberType Definition
---- ---------- ----------
AsType Method type AsType()
Clone Method System.Object Clone()
Equals Method bool Equals(System.Object obj), bool Equals(type o)
FindInterfaces Method type[] FindInterfaces(System.Reflection.TypeFilter filter, System.Object filterCriteria)
...
TypeHandle Property System.RuntimeTypeHandle TypeHandle {get;}
TypeInitializer Property System.Reflection.ConstructorInfo TypeInitializer {get;}
UnderlyingSystemType Property System.Type UnderlyingSystemType {get;}
According to the documentation:
To get information about static members, the members of the class, not of the instance, use the Static parameter.
But if I run [System.IO.FileStream] | Get-Member -Static now I get:
TypeName: System.IO.FileStream
Name MemberType Definition
---- ---------- ----------
Equals Method static bool Equals(System.Object objA, System.Object objB)
ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object objB)
Synchronized Method static System.IO.Stream Synchronized(System.IO.Stream stream)
Null Property static System.IO.Stream Null {get;}
Q1. These are the static members of System.IO.FileStream, not System.RuntimeType. Why is that?
The documentation also says:
We use :: to indicate to Windows PowerShell that we want to work with a static method or property.
This made me realize that [System.IO.FileStream]::Null refers to the static property Null of the class System.IO.FileStream.
Q2. Does it mean that Powershell sometimes sees [System.IO.FileStream] as the class System.IO.FileStream (when dealing with static members), and sometimes as an instance of System.RuntimeType?
By default, Get-Member without -Static always acts on the type of its input objects.
[System.IO.FileStream] is an instance of a PowerShell type literal ([<type-name>]), whose type is System.RuntimeType, which is a PowerShell-internal class that derives from System.Reflection.TypeInfo and ultimately System.Type.
Therefore, [System.IO.FileStream] | Get-Member outputs information about the members of System.RuntimeType - and so would any type literal (e.g., [int] | Get-Member would yield the same output).
By contrast, Get-Member with -Static:
acts on the input object itself if it happens to be a System.RunTimeType instance, such as type literal [System.IO.FileStream]; otherwise, as usual, the input object's type is operated on.
reports only the static members of the input object / type.
Therefore, [System.IO.FileStream] | Get-Member -Static reports the static members of type System.IO.FileStream - as would passing an instance of type System.IO.FileStream; e.g., [System.IO.FileStream]::new($PROFILE, 'Open') | Get-Member -Static
A curious omission, as of PowerShell Core 7.0, is that you cannot use Get-Member to request instance members by type; the only way to get a type's instance members is to pass an actual instance as input; however, the challenge is that an instance is not always easy to come by, so getting instance members by type would be helpful,
which this GitHub issue requests.
In the meantime, you can call .GetMembers() on a type, as you demonstrate in your own answer here.

PowerCLI - How to filter datastores by hosts which use them

How would I filter an array of data stores so that I am left with those that have a Host in their ExtensionData.Host array?
I have tried:
$Datastores = Get-Datastore
$HostDS = $Datastores | Where-Object{$_.ExtensionData.Host -contains $clusterhost}
But this doesn't work, because the host array in $Datastore.ExtensionData.Host is not of the datastore objects, but of DatastoreHostMount objects. The host mount objects have the IDs of the hosts I want, but I do not know how to compare them against the ID of the $clusterhost I am trying to compare them against.
Can I accomplish what I am trying to do here through filtering? I am trying to avoid another call of Get-Datastore for efficiency.
there is a key in the object that you need use in your where clause:
$hostds = Datastores | where-object{$_.extensiondata.host.key -eq $clusterhost}
Name FreeSpaceGB CapacityGB
---- ----------- ----------
Name2 x,xxx.xxx xx,xxx.xxx
Name1 x,xxx.xxx xx,xxx.xxx
$datastores.extensiondata.host |gm
TypeName: VMware.Vim.DatastoreHostMount
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Key Property VMware.Vim.ManagedObjectReference Key {get;set;}
LinkedView Property VMware.Vim.DatastoreHostMount_LinkedView LinkedView {get;}
MountInfo Property VMware.Vim.HostMountInfo MountInfo {get;set;}
That key had the host name in it...

Difference between "(gl -stack)" and "gl -stack"

I just wonder why I'm getting two different member lists when embedding an expression between parentheses, e.g. gl -stack. It seems that without the parenthesis, the expression is evaluated completely and the result passed at once to the next pipeline component. But with parenthesis, the single objects within the collection are passed one by one so that Get-Member is invoked for the objects in the collection instead for the collection itself.
Please see the following PowerShell interaction for an example with Get-Location -Stack.
Thanks in advance!
PS C:\temp\loc1> pushd
PS C:\temp\loc1> pushd ..\loc2
PS C:\temp\loc2> gl -stack
Path
----
C:\temp\loc1
C:\temp\loc1
PS C:\temp\loc2> gl -stack | gm
TypeName: System.Management.Automation.PathInfoStack
Name MemberType Definition
---- ---------- ----------
Clear Method System.Void Clear()
Contains Method bool Contains(System.Management.Automation.PathInfo...
CopyTo Method System.Void CopyTo(System.Management.Automation.Pat...
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.Generic.Stack`1+Enumerator[[Syst...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
Peek Method System.Management.Automation.PathInfo Peek()
Pop Method System.Management.Automation.PathInfo Pop()
Push Method System.Void Push(System.Management.Automation.PathI...
ToArray Method System.Management.Automation.PathInfo[] ToArray()
ToString Method string ToString()
TrimExcess Method System.Void TrimExcess()
Count Property System.Int32 Count {get;}
Name Property System.String Name {get;}
PS C:\temp\loc2> (gl -stack) | gm
TypeName: System.Management.Automation.PathInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Drive Property System.Management.Automation.PSDriveInfo Drive {get;}
Path Property System.String Path {get;}
Provider Property System.Management.Automation.ProviderInfo Provider {...
ProviderPath Property System.String ProviderPath {get;}
Get-Location -Stack returns a PathInfoStack object as you have seen. That object is derived from Stack<T> which implements ICollection. When you put an expression inside () PowerShell evaluates that expression. If the result is a collection then it is iterated and output. You can see the same with this simple function:
PS> function GetArray() { ,#(1,2,3) }
PS> GetArray | Foreach {$_.GetType().FullName}
System.Object[]
PS> (GetArray) | Foreach {$_.GetType().FullName}
System.Int32
System.Int32
System.Int32

How to use PowerShell to access methods and properties of a Third-Party OLE DLL?

I am trying to write a PowerShell script which could access methods and properties of a third-party OLE DLL.
The software vendor provided a working example in vbscript to achieve the same result. Below is an excerpt of the codes:
Set objOLE = CreateObject("NETIQOLE.APPMANAGER")
objOLE.Logon strInstance, strRepository, strUserID, strPwd
...
However, when I tried to code in PowerShell as below:
$objOLE = New-Object -ComObject "NETIQOLE.APPMANAGER"
$objOLE | Get-Member
I got output below and didn't see any relevant method or property.
TypeName: System.__ComObject
Name MemberType Definition
---- ---------- ----------
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
ToString Method string ToString()
Is there anything I can do to access to this OLE Dll's methods and proerties? Any advice or sample codes are welcome. Thank you in advance.
Thank you both for your kind responses. The link given by #Ekkehard.Horner worked. It really save my day.
The working codes are now:
$credential = "...", "...", "...", "..."
[System.__ComObject].InvokeMember("Logon", [System.Reflection.BindingFlags]::InvokeMethod, $null, $netiqObj, $credential)