Wow! A lot of new things here!
[BRIEF OFF-TOPIC INTRO]: I don't like large systems with huge documentation... When I learned IBM-1130 assembly language and OS functions in 1977, I could read the extensive documentation
and found things! When I started to write programs for the (new) IBM-PC around 1981 I could read the books and manuals and found the things I wanted, and the same happened with a lot of products of that era, like all Turbo-languages (TASM, Pascal, C), dBase IV, Clipper, FrameWork and a long et cetera... I am not talking about I knew all possible features of all such products, but that when I had a problem I read the manuals and solved it!
The world changed for me in this respect when I started to study the Windows-32 API. It was/is very,
very hard to find the things I wanted from the Win32-API documentation. Note that I am
not talking about the huge amount of information that these products have, but about the frequently very poor ("incoherent") way to organize such information when it is presented to the user. When I have a problem, I frequently have not idea on which part of the API documentation I must search looking for such a feature. I must review several (frequently many) sections and review a very large amount of (non related) information until I found what I was looking for. It seems that the way to learn to use certain modern systems was designed with the purpose of be intrinsically difficult...
The Windows Management Instrumentation (WMI) is another product of such a type. It have a few NameSpaces, many Classes in each NameSpace, and a ton of Properties in each Class. If you want to get a certain data, which NameSpace/Class/Property gives such information? There is no easy way to know it. You need to review many,
many properties until find the required one!
As I said, I hate large systems with bad documentation... [END OF INTRO]
Compo wrote: ↑23 Feb 2022 05:53
atfon wrote: ↑22 Feb 2022 13:05
I doubt I have to tell most of you on this forurm, but for those who might not be aware, you can get a list of WMI aliases Friendly Name and Corresponding full name with this command:
Whilst that may be useful to some, it doesn't really provide all of the information needed to translate one methodology to another.
It provides the FriendlyName and Target, which is great, however there is still more information needed, and that is the NameSpace...
Let's take an example: the FriendlyName
alias itself, when run from the default namespace ROOT\CIMV2, i.e.
still produces output, as you've seen, but in order to do that it also needs to, behind the scenes, switch to the appropriate namespace, ROOT\CLI
To find out that namespace you could probably currently do it like this:
Code: Select all
%SystemRoot%\System32\wbem\WMIC.exe alias WHERE FriendlyName="alias" GET /Value 2>NUL | %SystemRoot%\System32\findstr.exe "^FriendlyName= ^NameSpace= ^Target="
After read this information, I did several tests until I completed this program that I called
wmicAlias.bat:
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem wmicAlias.bat: List the data of "alias" Alias from wmic.exe
rem Antonio Perez Ayala
for /F "tokens=1* delims==" %%a in (
'WMIC.exe alias GET /Value ^| findstr.exe "^Description= ^FriendlyName= ^Target= ^NameSpace="') do (
if "%%a" equ "Description" (
set "Description=%%b"
) else (
if defined Description (
echo/
for /F "delims=." %%c in ("!Description!") do echo Description=%%c.
set "Description="
)
set "%%a=%%b"
echo %%a=!%%a:~0,-1!
)
)
I run this program to get a list of WMIC.exe "Alias" (wmicAlias.txt); this is a part of such output:
Code: Select all
Description=Network adapter management.
FriendlyName=NICConfig
Target=Select * from Win32_NetworkAdapterConfiguration
NameSpace=ROOT\CIMV2
Description=Management of the system driver for a base service.
FriendlyName=SysDriver
Target=Select * from Win32_SystemDriver
NameSpace=ROOT\CIMV2
Description=Tape drive management.
FriendlyName=TapeDrive
Target=Select * from Win32_TapeDrive
NameSpace=ROOT\CIMV2
. . . . .
Description=This provides access to the aliases available on the local system.
FriendlyName=Alias
Target=Select * from Msft_CliAlias
NameSpace=ROOT\cli
. . . . .
After that, I wanted to modify
wmiClass.bat program in order to get classes from a given NameSpace. The modification was pretty simple thanks to JScript's "Arguments.Named" feature:
Code: Select all
@if (@CodeSegment == @Batch) @then
@echo off
if "%~1" neq "/?" CScript //nologo //E:JScript "%~F0" %* & goto :EOF
echo Show properties of a WMI class (via a JScript collection)
rem Antonio Perez Ayala
rem - 2022/02/21: version 1
rem - 2022/02/23: version 1.1: /NS option added
echo/
echo wmiClass [/NS:namespace] [class [prop1 prop2 ...]]
echo/
echo If no class is given, show the names of all WMI classes.
echo/
echo If just the class is given, show the names of all its properties.
echo/
echo If a list of properties is given, show their values. For example:
echo wmiClass Win32_LocalTime Year Month Day Hour Minute Second
echo/
echo If /NS option is given, specify the NameSpace (default: \root\cimv2):
echo wmiClass /NS:\root\cli MSFT_CliAlias
goto :EOF
@end
// http://msdn.microsoft.com/en-us/library/aa393741(v=vs.85).aspx
var args = WScript.Arguments.Unnamed,
options = WScript.Arguments.Named,
colItems;
if ( args.length > 1 ) { // Show values of given properties
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa394606(v=vs.85).aspx
colItems = GetObject("WinMgmts:"+(options.Exists("NS")?options.Item("NS"):"")).ExecQuery("Select * from " + args.Item(0));
for ( var e = new Enumerator(colItems); ! e.atEnd(); e.moveNext() ) {
for ( var i = 1; i < args.length; i++ ) {
WScript.Stdout.WriteLine(args.Item(i)+"="+eval("e.item()."+args.Item(i)));
}
}
} else if ( args.length == 1 ) { // Show all properties of given class
// Method suggested by: http://msdn.microsoft.com/en-us/library/aa392315(v=vs.85).aspx
// https://gallery.technet.microsoft.com/f0666124-3b67-4254-8ff1-3b75ae15776d
colItems = GetObject("WinMgmts:"+(options.Exists("NS")?options.Item("NS"):"")).Get(args.Item(0)).Properties_;
for ( var e = new Enumerator(colItems); ! e.atEnd(); e.moveNext() ) {
WScript.Stdout.WriteLine(e.item().Name);
}
} else { // Show all classes
// https://gallery.technet.microsoft.com/scriptcenter/5649568b-074e-4f5d-be52-e8b7d8fe4517
colItems = GetObject("WinMgmts:"+(options.Exists("NS")?options.Item("NS"):"")); // if no NameSpace given, imply ("WinMgmts:\root\cimv2")
for ( var e = new Enumerator(colItems.SubclassesOf()); ! e.atEnd(); e.moveNext() ) {
WScript.Stdout.WriteLine(e.item().Path_.Class);
}
}
After that, I wanted to test the new /NS option, so I reviewed the wmicAlias.txt list looking for a NameSpace other than ROOT\CIMV2 and this is the first one I found:
Code: Select all
Description=Remote Desktop NIC management.
FriendlyName=RDNIC
Target=Select * from Win32_TSNetworkAdapterSetting
NameSpace=ROOT\CIMV2\TerminalServices
... so I did this test:
Code: Select all
wmiClass /NS:ROOT\CIMV2\TerminalServices Win32_TSNetworkAdapterSetting
C:\Users\Antonio\Documents\Test\FindRepl\wmiClass.bat(45, 4) (null): 0x8004100E
What happened? This error indicate that such "ROOT\CIMV2\TerminalServices" NameSpace does
not exists! (and remembers me that I should add some error detection code that show informative messages)
After guessing what is happening here, I concluded that "ROOT\CIMV2\TerminalServices" could not be a
NameSpace! Perhaps the NameSpace is the usual ROOT\CIMV2 and the class is TerminalServices\Win32_TSNetworkAdapterSetting, but this don't works. I tried all possible combinations of "ROOT\CIMV2", "TerminalServices" and "Win32_TSNetworkAdapterSetting" as NameSpace/Class/Property but it don't works either. This means that when wmic.exe gets the
RDNIC Alias (FriendlyName), it process such a name in a way that is
not the standard (documented?) way! (at least, not with the WMI knowledge I have so far)
[This is very frustrating but, want you know what is even worst? The future reply of someone expert in WMI that will say: "Of course! You just need to put the X part in Y site! Isn't it obvious?" I hate WMI and wmic.exe...]
Ok. Anyway, I did several tests including /NS:ROOT\CIMV2 option and it seems to work correctly. Then, I look for another NameSpace different than ROOT\CIMV2 and ROOT\CIMV2\TerminalServices in wmicAlias.txt list and found the only one:
Code: Select all
Description=This provides access to the aliases available on the local system.
FriendlyName=Alias
Target=Select * from Msft_CliAlias
NameSpace=ROOT\cli
... so I did this test:
Code: Select all
wmiClass /NS:ROOT\cli Msft_CliAlias
Connection
Description
Formats
FriendlyName
PWhere
Qualifiers
Target
Verbs
Excellent! This means that the new /NS option works correctly...
I extended previous test and run this:
Code: Select all
wmiClass /NS:ROOT\cli Msft_CliAlias Connection Description Formats FriendlyName PWhere Qualifiers Target Verbs > wmiAliasClass.txt
... so I get a file with alias listing similar to the previous wmicAlias.txt one, but this time generated without the aid of wmic.exe!
This is the segment of such a file that corresponds to OS alias:
Code: Select all
Connection=
Description=Installed Operating System/s management.
Formats=
FriendlyName=OS
PWhere=
Qualifiers=null
Target=Select * from Win32_OperatingSystem
Verbs=
After that, I devised a new /A:alias wmiClass.bat option that get a wmic.exe alias (like "OS") and retrieve the corresponding class via "/NS:ROOT\cli Msft_CliAlias FriendlyName Target" properties. This feature will allow us to get WMI values using the same names of wmic.exe; for example:
I am working on such new version now...
Antonio