Creating a script to gather PC information - to assist those asking for help
Moderator: DosItHelp
Re: Creating a script to gather PC information - to assist those asking for help
penpen
I tested your approach and it took ages. But you're right that it looks pretty much the same Let me try again tomorrow ...
Steffen
I tested your approach and it took ages. But you're right that it looks pretty much the same Let me try again tomorrow ...
Steffen
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Creating a script to gather PC information - to assist those asking for help
aGerman wrote:Thanks! Tried it at work and it returns the right results in no time
I'm curious what Douglas' results will be using your approach.
n
Runs in under a second, with accurate results.
penpen wrote:That's nearly the same solution, i've given above (with a removed flaw, but a (probably slower) "for /F" instead of "AND ...").
I thought you've tested it, and it is slower because it's "querying the Win32_GroupUser class"?!
That's what I thought, too. Apparently, the manner of querying Win32_GroupUser affects the processing speed. The key difference is in this line, where %%b is the admin group name:
Code: Select all
WMIC path Win32_GroupUser Where (GroupComponent^="Win32_Group.Name=\"%%b\",domain=\"%computername%\""^) get PartComponent
We've got nested equals signs in the WHERE clause (GroupComponent="Win32_Group.Name=\"Administrators\"), so maybe we're comparing 'GroupComponent' to the object returned by 'Win32_Group.Name="Administrators"', rather than the text string "Administrators". Maybe? I don't understand it at all. Compo, can you explain what's happening, here?
Meanwhile, I'm all for dropping GPRESULT and going with this.
Edit: Whoops. Spoke too soon. This approach find IT-group admins, but not me. See next post for details.
Last edited by douglas.swehla on 25 Aug 2016 17:35, edited 1 time in total.
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Creating a script to gather PC information - to assist those asking for help
penpen wrote:Code: Select all
2>nul wmic path win32_groupuser where (GroupComponent="win32_Group.Name=\"%adminGroupName%\",Domain=\"%userDomain%\"" ^
AND PartComponent="Win32_UserAccount.Name=\"%userName%\",Domain=\"%userDomain%\"")
aGerman wrote:penpen
I tested your approach and it took ages. But you're right that it looks pretty much the same Let me try again tomorrow ...
Steffen
I just tested penpen's code (didn't test earlier, sorry penpen), and rather than taking ages, I immediately got "No Instance(s) Available." More on that in a second.
douglas.swehla wrote:The key difference is in this line, where %%b is the admin group name:Code: Select all
WMIC path Win32_GroupUser Where (GroupComponent^="Win32_Group.Name=\"%%b\",domain=\"%computername%\""^) get PartComponent
. . . I don't understand it at all.
I've been experimenting to understand all this, and there are a few interesting things going on here. The first is that penpen's code searches for Domain=\"%userDomain%\", while compo's searches for domain=\"%computername%\". On my machine, "%userDomain%" expands to "US", rather than the local machine name. That explains why I get no results: there are no local admins that are part of the nation-wide domain. I thought it might account for the long search search time that aGerman is getting (searching the whole network rather than local machine), but if that were the case, then I would expect my search to take ages, and then say "No Instances", so I don't quite know what to make of that.
The next is the difference between the format of the query and the result. Both of these commands return the same result:
Code: Select all
WMIC path Win32_GroupUser Where (GroupComponent^="Win32_Group.Name=\"Administrators\",domain=\"%computername%\""^) get
WMIC path Win32_GroupUser Where (GroupComponent^="Win32_Group.domain=\"%computername%\",Name=\"Administrators\""^) get
GroupComponent PartComponent
Win32_Group.domain="MyComputerName",Name="Administrators" \\MyComputerName\root\cimv2:Win32_UserAccount.Domain="MyComputerName",Name="SomeITGuy"
Win32_Group.domain="MyComputerName",Name="Administrators" \\MyComputerName\root\cimv2:Win32_Group.Domain="US",Name="Domain Admins"
Win32_Group.domain="MyComputerName",Name="Administrators" \\MyComputerName\root\cimv2:Win32_Group.Domain="US",Name="XYZ_WKSTN_ADMINS"
Win32_Group.domain="MyComputerName",Name="Administrators" \\MyComputerName\root\cimv2:Win32_Group.Domain="US",Name="ALL_WKSTN_ADMINS"
Note that in the results, the domain portion of the group always comes before the name portion, even though the order is reversed in the first command. So, even though the query looks like it's matching a string, it's not, exactly. I think there must be some kind of implied AND syntax that's used to identify and match on object IDs. Again, not a WMI master, so if anybody knows otherwise, please chime in.
The last and biggest thing is the issue that I pointed out when proposing GPRESULT. My organization does some kind of weird security thing where my login name (%username%) is used as the first part of two different local account names, neither of which is assigned to any local groups. Both the NET command and WMI's Win32_UserAccount use these account names, and neither uses my login name, so both of these tools fail to recognize me as an administrator.
Since WMI doesn't recognize me as an admin, even when it's working at a sane speed, I have to retract my earlier endorsement of Compo's method, at least for now.
For what it's worth, my admin rights are handled by a third-party program. To get to an admin prompt, I search the Start menu for CMD, right-click on the result, and instead of "Run as admin", click "Run with Third-Party Program Name". That opens an instance of CMD.EXE with the title "Administrator: c:\windows\system32\cmd.exe" and current directory set to "C:\windows\system32", just like I'd get normally. This is a fairly recent change, and I'm pretty sure the weird account name stuff was in place before that, so I don't think they're directly related. If anyone has ideas on how to take that into account and still get a working solution from WMIC, I'd love to hear it.
Re: Creating a script to gather PC information - to assist those asking for help
My code has (at minimum) one flaw:
Instead of "Administratoren" there should be "%adminGroupName%" (which contains localized version of "Administrators" ; all without doublequotes);
other localizations just give the wrong answer (because there is no group "Administratoren"), german localized windows should return the right answer.
I'm unsure about your (douglas.swehla) value of the environment variable "UserDomain":
I thought (but i may error an that point) that it should contain the name of the domain that contains the user's account ("US" is very unlikely because it is probably stored at your companies server pcs which i assume doesn't hold all "US" accounts) and not the name of the domain, the computer/server belongs to (which i assume why this value is set to "US").
But this should explain why you got no result.
Using "%ComputerName%" is probably better because that domain node most probably exists.
When using parentheses "()" in the "where-Clause" strings may contain serialized calls to constructors (which is needed here, because "GroupComponent" is no simple string or integer value):
So '(GroupComponent^="Win32_Group.Name=\"Administrators\",domain=\"%computername%\""^)' advices to compare the "GroupComponent" with the object created by the constructor 'Win32_Group(AttributeList("Name=Administrators", domain="%computername%"))'.
If you reverse the order then 'Win32_Group(AttributeList(domain="%computername%", "Name=Administrators"))' is called, which should result in an equal object.
Sidenotes:
1) One cannot use
'GroupComponent="\\\\%computername%\\root\\cimv2:Win32_Group.Domain\=\"%computername%\"\,Name\=\"Administrators\""'
because types are mismatching (Win32_Group versus string), so the verb should be invalid.
2) Using different lists ('(GroupComponent^="Win32_Group.Name=\"Administrators\"")', or '(GroupComponent^="Win32_Group.Name=\"Administrators\",domain="%computername%",Caption=\"abc\"")' ) should be valid but should result in nothing found, because the objects doesn't match, so one have to use exactly "Name" and "Domain".
penpen
Edit 1: Nearly completely changed.
Instead of "Administratoren" there should be "%adminGroupName%" (which contains localized version of "Administrators" ; all without doublequotes);
other localizations just give the wrong answer (because there is no group "Administratoren"), german localized windows should return the right answer.
I'm unsure about your (douglas.swehla) value of the environment variable "UserDomain":
I thought (but i may error an that point) that it should contain the name of the domain that contains the user's account ("US" is very unlikely because it is probably stored at your companies server pcs which i assume doesn't hold all "US" accounts) and not the name of the domain, the computer/server belongs to (which i assume why this value is set to "US").
But this should explain why you got no result.
Using "%ComputerName%" is probably better because that domain node most probably exists.
If i remind right:douglas.swehla wrote:Note that in the results, the domain portion of the group always comes before the name portion, even though the order is reversed in the first command. So, even though the query looks like it's matching a string, it's not, exactly. I think there must be some kind of implied AND syntax that's used to identify and match on object IDs. Again, not a WMI master, so if anybody knows otherwise, please chime in.
When using parentheses "()" in the "where-Clause" strings may contain serialized calls to constructors (which is needed here, because "GroupComponent" is no simple string or integer value):
So '(GroupComponent^="Win32_Group.Name=\"Administrators\",domain=\"%computername%\""^)' advices to compare the "GroupComponent" with the object created by the constructor 'Win32_Group(AttributeList("Name=Administrators", domain="%computername%"))'.
If you reverse the order then 'Win32_Group(AttributeList(domain="%computername%", "Name=Administrators"))' is called, which should result in an equal object.
Sidenotes:
1) One cannot use
'GroupComponent="\\\\%computername%\\root\\cimv2:Win32_Group.Domain\=\"%computername%\"\,Name\=\"Administrators\""'
because types are mismatching (Win32_Group versus string), so the verb should be invalid.
2) Using different lists ('(GroupComponent^="Win32_Group.Name=\"Administrators\"")', or '(GroupComponent^="Win32_Group.Name=\"Administrators\",domain="%computername%",Caption=\"abc\"")' ) should be valid but should result in nothing found, because the objects doesn't match, so one have to use exactly "Name" and "Domain".
penpen
Edit 1: Nearly completely changed.
Last edited by penpen on 25 Aug 2016 21:59, edited 1 time in total.
Re: Creating a script to gather PC information - to assist those asking for help
I never heard about something like that.douglas.swehla wrote:The last and biggest thing is the issue that I pointed out when proposing GPRESULT. My organization does some kind of weird security thing where my login name (%username%) is used as the first part of two different local account names, neither of which is assigned to any local groups. Both the NET command and WMI's Win32_UserAccount use these account names, and neither uses my login name, so both of these tools fail to recognize me as an administrator.
...
If that is really is a third-party program which name has it?
The method of creating a directory under system32 does not mean you have admin rights (although i must admit it is highly probable); you also could be:
- a user/group member of "SYSTEM" (don't know if this is a user / group account),
- a group member of "NT SERVICE\TrustedInstaller" (which is a virtual account that is a virtual member of "Administrators"),
But you should really fire any admin who adds you to one of the above groups... (i hope this is not how your (douglas.swehla) organization has implemented it ).
penpen
PS: I nearly completely changed my above post.
Re: Creating a script to gather PC information - to assist those asking for help
penpen
My apologies. I tried your code again and it worked great. I don't know what happened last time. Probably I overwrote the old code but forgot to save the file or something like that
(When that didn't work last time I run wmic path win32_groupuser separatly and without WHERE clause which took ages again. FWIW That was confirmed today as well.)
Steffen
My apologies. I tried your code again and it worked great. I don't know what happened last time. Probably I overwrote the old code but forgot to save the file or something like that
(When that didn't work last time I run wmic path win32_groupuser separatly and without WHERE clause which took ages again. FWIW That was confirmed today as well.)
Steffen
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Creating a script to gather PC information - to assist those asking for help
penpen wrote:Instead of "Administratoren" there should be "%adminGroupName%" (which contains localized version of "Administrators" ; all without doublequotes)
I made that change when testing, and also substituted "Administrators" directly. Both had the same result: No Instances.
penpen wrote:I'm unsure about . . . the environment variable "UserDomain":
I thought (but i may error an that point) that it should contain the name of the domain that contains the user's account ("US" is very unlikely because it is probably stored at your companies server pcs which i assume doesn't hold all "US" accounts) and not the name of the domain, the computer/server belongs to (which i assume why this value is set to "US").
But this should explain why you got no result.
Using "%ComputerName%" is probably better because that domain node most probably exists.
I couldn't say where accounts are stored, and don't really understand what "domain node" means in this context. When I log into Windows on this machine, I log into domain "US". When I run tools that identify local users in the format 'domain\name", the domain portion is the name of the local machine, which is the same as the asset tag. Since admin privileges are granted on a per-machine basis, it makes sense to me that we'd want to match on %computername%. If that's what you mean by domain node, then I agree.
penpen wrote:When using parentheses "()" in the "where-Clause" strings may contain serialized calls to constructors (which is needed here, because "GroupComponent" is no simple string or integer value):
So '(GroupComponent^="Win32_Group.Name=\"Administrators\",domain=\"%computername%\""^)' advices to compare the "GroupComponent" with the object created by the constructor 'Win32_Group(AttributeList("Name=Administrators", domain="%computername%"))'.
If you reverse the order then 'Win32_Group(AttributeList(domain="%computername%", "Name=Administrators"))' is called, which should result in an equal object.
Excellent explanation, thanks! I wondered why it broke when I tried changing the parentheses to quotes. I thought it was just messing up the character escaping.
I wanted to try using the PartComponent to identify the GroupComponent, but kept getting "invalid query" error. Can you tell me what's wrong with the code below? Is it to do with escaping the backslashes, or something else entirely?
Code: Select all
rem :: Compo's code to find GroupComponent, with group name already found
WMIC path Win32_GroupUser Where (GroupComponent^="Win32_Group.Name=\"Administrators\",domain=\"%computername%\""^) get PartComponent
rem :: Results from above. (Note mix of "%computername%" and "US" in Domain fields.)
rem :: I've manually substituted "%computername%" for the actual text, and obfuscated some other details.
PartComponent
\\%computername%\root\cimv2:Win32_UserAccount.Domain="%computername%",Name="ITGuy74"
\\%computername%\root\cimv2:Win32_Group.Domain="US",Name="Domain Admins"
\\%computername%\root\cimv2:Win32_Group.Domain="US",Name="XYZ_WKSTN_ADMINS"
\\%computername%\root\cimv2:Win32_Group.Domain="US",Name="ALL_WKSTN_ADMINS"
rem :: To reverse the search, I should be able to just flip it around, right?
rem :: I provide the Domain and Name properties of the PartComponent (Win32_Account object),
rem :: and get back the GroupComponent. Except, none of these work.
rem :: The middle one returns "Invalid query", and the other two just sit there.
rem :: I can't tell if they're hung, just running forever.
rem :: Same results with "Win32_Account" instead of "Win32_UserAccount".
WMIC path Win32_GroupUser Where (PartComponent^="Win32_UserAccount.Domain=\"%computername%\",Name=\"ITGuy74\""^) get GroupComponent
WMIC path Win32_GroupUser Where (PartComponent^="\\%computername%\root\cimv2:Win32_UserAccount.Domain=\"%computername%\",Name=\"ITGuy74\""^) get GroupComponent
WMIC path Win32_GroupUser Where (PartComponent^="\\\\%computername%\\root\\cimv2:Win32_UserAccount.Domain=\"%computername%\",Name=\"ITGuy74\""^) get GroupComponent
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Creating a script to gather PC information - to assist those asking for help
penpen wrote:I never heard about something like that.
If that is really is a third-party program which name has it?
It's called Avecto Defendpoint. Here is a blurb from the support team describing it:
In an on-going effort to strengthen the security of our ecosystem with respect to privileged access, Identity and Access Management has invested in an endpoint security product for workstations known as Avecto Defendpoint. The purpose of Defendpoint is to provide a more granular elevation of privileged access for users that require local administrative rights to their workstation while also providing more robust metrics around what applications and activities end-users are using their elevated rights for.
For workstation admin rights please follow instructions on the below attachment to get the software loaded on the machine where you need workstation admin rights. Once the software is loaded you will have admin rights - no other action needs to be done.
I skimmed the info at https://www.avecto.com/defendpoint/privilege-management, and it sounds like the tool grants privileges to applications, rather than to users. On a normal system, when you are logged in as a standard user, and you select "Run as administrator...", you're prompted to enter an admin user's credentials. On my work machine, when I select "Run with Defendpoint", I'm not prompted for other credentials, so there must be someplace where "UserID can tell CMD.EXE to run in elevated mode" is recorded. I expect GPRESULT is pulling its data from that place. If we can figure out what that place is, then maybe we can get to it through WMIC or REG or some other faster tool. There is an "Avecto Defendpoint Modified Token" group on my machine, so maybe access is brokered through that somehow. I'm still trying to figure that out.
penpen wrote:The method of creating a directory under system32 does not mean you have admin rights (although i must admit it is highly probable); you also could be:
- a user/group member of "SYSTEM" (don't know if this is a user / group account),
- a group member of "NT SERVICE\TrustedInstaller" (which is a virtual account that is a virtual member of "Administrators")
I don't think I'm a member of either of those. Will check in a bit to confirm.
I take your point that I might not strictly be an admin on this machine, using the normal definition. We must remember, though, that the question "Is the user a member of the Administrators group?" is a proxy for "Does the user have administrator-like rights?", which is in turn a proxy for "Can the user use command-line tools that are normally restricted to admin-level users?". In my case, the answers are "No", "Kind of", and "Yes", respectively. What we really want to know is whether the user can run FSUTIL or edit the Registry or do any of the things that require elevation, and I can do those things.
So, given the funky way that account permissions are handled by my workplace, how can we determine that programatically? So far, the only way I've found is with GPRESULT. I'm going dig a little deeper into the account/group/permissions info, and try to get you guys a better description of what's going on so that, if there's a better way to do this, we can figure it out. Hopefully, that will be later today, but might be tomorrow.
Re: Creating a script to gather PC information - to assist those asking for help
@aGerman
Np, i have formulated it too hard: Sorry for that.
I just was curious why there was such big difference.
Actually i can't see a reason why it should fail.
Have you tested them from within a for loop (or why did you escape some characters)?
(If yes, then try from cmd line.)
There are too many possibilities to just guess.
In additon you won't see all accounts using wmi only.
The best summary about that i found here:
http://superuser.com/questions/248315/list-of-hidden-virtual-windows-user-accounts/638376.
But i don't like to create fiules/directories only to check for admin rights:
In "my" University such accesses (creating/deleting/writing to objects in system directries) are logged, and our admin invites that user to explain herself/himself.
(Only on "important" computers.)
penpen
Np, i have formulated it too hard: Sorry for that.
I just was curious why there was such big difference.
+douglas.swehla wrote:I couldn't say where accounts are stored, and don't really understand what "domain node" means in this context. When I log into Windows on this machine, I log into domain "US". When I run tools that identify local users in the format 'domain\name", the domain portion is the name of the local machine, which is the same as the asset tag. Since admin privileges are granted on a per-machine basis, it makes sense to me that we'd want to match on %computername%. If that's what you mean by domain node, then I agree.
The first and third command should be what you are searching for (if i understand it right).douglas.swehla wrote:I wanted to try using the PartComponent to identify the GroupComponent, but kept getting "invalid query" error. Can you tell me what's wrong with the code below? Is it to do with escaping the backslashes, or something else entirely?Code: Select all
rem :: Compo's code to find GroupComponent, with group name already found
WMIC path Win32_GroupUser Where (GroupComponent^="Win32_Group.Name=\"Administrators\",domain=\"%computername%\""^) get PartComponent
rem :: Results from above. (Note mix of "%computername%" and "US" in Domain fields.)
rem :: I've manually substituted "%computername%" for the actual text, and obfuscated some other details.
PartComponent
\\%computername%\root\cimv2:Win32_UserAccount.Domain="%computername%",Name="ITGuy74"
\\%computername%\root\cimv2:Win32_Group.Domain="US",Name="Domain Admins"
\\%computername%\root\cimv2:Win32_Group.Domain="US",Name="XYZ_WKSTN_ADMINS"
\\%computername%\root\cimv2:Win32_Group.Domain="US",Name="ALL_WKSTN_ADMINS"
rem :: To reverse the search, I should be able to just flip it around, right?
rem :: I provide the Domain and Name properties of the PartComponent (Win32_Account object),
rem :: and get back the GroupComponent. Except, none of these work.
rem :: The middle one returns "Invalid query", and the other two just sit there.
rem :: I can't tell if they're hung, just running forever.
rem :: Same results with "Win32_Account" instead of "Win32_UserAccount".
WMIC path Win32_GroupUser Where (PartComponent^="Win32_UserAccount.Domain=\"%computername%\",Name=\"ITGuy74\""^) get GroupComponent
WMIC path Win32_GroupUser Where (PartComponent^="\\%computername%\root\cimv2:Win32_UserAccount.Domain=\"%computername%\",Name=\"ITGuy74\""^) get GroupComponent
WMIC path Win32_GroupUser Where (PartComponent^="\\\\%computername%\\root\\cimv2:Win32_UserAccount.Domain=\"%computername%\",Name=\"ITGuy74\""^) get GroupComponent
Actually i can't see a reason why it should fail.
Have you tested them from within a for loop (or why did you escape some characters)?
(If yes, then try from cmd line.)
Thanks, i will read into (as early as i got some more time).douglas.swehla wrote:It's called Avecto Defendpoint (...)
(...)
(...) I'm still trying to figure that out.
There are too many possibilities to just guess.
In additon you won't see all accounts using wmi only.
The best summary about that i found here:
http://superuser.com/questions/248315/list-of-hidden-virtual-windows-user-accounts/638376.
I also don't think this.douglas.swehla wrote:I don't think I'm a member of either of those. Will check in a bit to confirm.
You are right: I lost that out of my eyes.douglas.swehla wrote:What we really want to know is whether the user can run FSUTIL or edit the Registry or do any of the things that require elevation, and I can do those things.
But i don't like to create fiules/directories only to check for admin rights:
In "my" University such accesses (creating/deleting/writing to objects in system directries) are logged, and our admin invites that user to explain herself/himself.
(Only on "important" computers.)
penpen
Re: Creating a script to gather PC information - to assist those asking for help
I removed the JScript part and replaced it with WMIC in order to shorten the code. All of you guys are very welcome to try it out and give a feedback. Thanks!
Steffen
//EDIT
09/09/2016 replaced %sys32% with %__APPDIR__%, changed code page to get the Windows version, added the contents of %__APPDIR__% and %PATHEXT% to the output, corrected wrong WHOAMI handling
09/07/2016 removed clock hours, added ComSpec and AutoRun check
09/03/2016 corrected the WMIC registry handling
09/01/2016 corrected the code page handling, removed CLIP
08/31/2016 switch to ANSI code page when outputting the DIR format
08/29/2016 corrected unit of visible RAM, added alternative file for DIR format
Code: Select all
@echo off
set ex_noreg=Disabled
2>nul set "ex_noreg=Enabled "
set de_noreg=Disabled
if "!!"=="" (set de_noreg=Enabled )
setlocal EnableExtensions DisableDelayedExpansion
cd /d "%~dp0"
>"%temp%\info.txt" echo [code^]
:: prepare some variables to shorten lines in the script
set "International=Control Panel\International"
set "CurrentVersion=SOFTWARE\Microsoft\Windows NT\CurrentVersion"
set "CodePage=SYSTEM\CurrentControlSet\Control\Nls\CodePage"
set "CMDproc=Software\Microsoft\Command Processor"
set /a "HKCU=80000001, HKLM=80000002, HKU=80000003"
:: try to assign variables for used tools in order to make the script run even if the path or pathext variables are corrupted
if exist "%__APPDIR__%chcp.com" (set "chcp=%__APPDIR__%chcp.com") else (set "chcp=echo" &>>"%temp%\info.txt" echo chcp.com not found.)
if exist "%__APPDIR__%find.exe" (set "find=%__APPDIR__%find.exe") else (set "find=echo" &>>"%temp%\info.txt" echo find.exe not found.)
if exist "%__APPDIR__%findstr.exe" (set "findstr=%__APPDIR__%findstr.exe") else (set "findstr=echo" &>>"%temp%\info.txt" echo findstr.exe not found.)
if exist "%__APPDIR__%gpresult.exe" (set "gpresult=%__APPDIR__%gpresult.exe") else (set "gpresult=" &>>"%temp%\info.txt" echo gpresult.exe not found.)
if defined gpresult >nul 2>nul %gpresult% /? || (set "gpresult=" &>>"%temp%\info.txt" echo gpresult.exe not accessible.)
if exist "%__APPDIR__%net.exe" (set "net=%__APPDIR__%net.exe") else (set "net=echo" &>>"%temp%\info.txt" echo net.exe not found.)
if exist "%SystemRoot%\notepad.exe" (set "notepad=%SystemRoot%\notepad.exe") else if exist "%__APPDIR__%notepad.exe" (
set "notepad=%__APPDIR__%notepad.exe"
) else (set "notepad=%__APPDIR__%cmd.exe /k type" &>>"%temp%\info.txt" echo notepad.exe not found.)
if exist "%__APPDIR__%ping.exe" (set "ping=%__APPDIR__%ping.exe") else (set "ping=(for /l %%i in (0 1 10000) do echo %%i>nul)&echo" &>>"%temp%\info.txt" echo ping.exe not found.)
if exist "%__APPDIR__%reg.exe" (set "reg=%__APPDIR__%reg.exe") else (set "reg=foo?.exe" &>>"%temp%\info.txt" echo reg.exe not found.)
if exist "%__APPDIR__%whoami.exe" (set "whoami=%__APPDIR__%whoami.exe") else (set "whoami=" &>>"%temp%\info.txt" echo whoami.exe not found.)
if defined whoami >nul 2>nul %whoami% /? || (set "whoami=" &>>"%temp%\info.txt" echo whoami.exe not acessible.)
if exist "%__APPDIR__%wbem\WMIC.exe" (set "wmic=%__APPDIR__%wbem\WMIC.exe") else (set "wmic=" &>>"%temp%\info.txt" echo wmic.exe not found.)
if defined wmic >nul 2>nul %wmic% /? || (set "wmic=" &>>"%temp%\info.txt" echo wmic.exe not accessible.)
>>"%temp%\info.txt" echo --------------------------------------------------------------------------------
:: shorten WMI StdRegProv command lines
set "RegHead=set "dat="&for /f "tokens=1* delims==" %%i in ('2^>nul %wmic% /NameSpace:\\root\default Class StdRegProv Call"
set "RegTail=^|%findstr% /rc:"\^<[su]Value = "') do for %%k in (%%j) do set "dat=%%~k""
:: list of directories to check if missing in the path variable
set dirs="%SystemRoot%","%SystemRoot\System32%","%__APPDIR__%wbem","%__APPDIR__%WindowsPowerShell\v1.0"
:: list of tools to check if missing in the path environment
set tools=certutil,choice,clip,debug,forfiles,gpresult,icacls,openfiles,powershell,robocopy,timeout,whoami,wmic
:: check reg access
%reg% query "HKCU\%International%" >nul 2>&1 && (set "RegUserInternational=1") || (set "RegUserInternational=0")
%reg% query "HKU\.DEFAULT\%International%" >nul 2>&1 && (set "RegDefInternational=1") || (set "RegDefInternational=0")
%reg% query "HKLM\%CurrentVersion%" >nul 2>&1 && (set "RegSysCurrentVersion=1") || (set "RegSysCurrentVersion=0")
%reg% query "HKLM\%CodePage%" >nul 2>&1 && (set "RegSysCodePage=1") || (set "RegSysCodePage=0")
%reg% query "HKCU\%CMDproc%" >nul 2>&1 && (set "RegUserCMDproc=1") || (set "RegUserCMDproc=0")
%reg% query "HKLM\%CMDproc%" >nul 2>&1 && (set "RegSysCMDproc=1") || (set "RegSysCMDproc=0")
:: check AutoRun settings
set "AutoRunUser="
>"%temp%\autorun.tmp~" type nul
if %RegUserCMDproc%==1 (
2>nul %reg% query "HKCU\%CMDproc%" /v AutoRun |>"%temp%\autorun.tmp~" %find% "REG_"
) else if defined wmic (
2>nul %wmic% /NameSpace:\\root\default Class StdRegProv Call GetExpandedStringValue hDefKey="&H%HKCU%" sSubKeyName="%CMDproc%" sValueName="AutoRun" |>"%temp%\autorun.tmp~" %findstr% /rc:"\<[su]Value = "
)
<"%temp%\autorun.tmp~" set /p "AutoRunUser="
set "AutoRunSys="
>"%temp%\autorun.tmp~" type nul
if %RegSysCMDproc%==1 (
2>nul %reg% query "HKLM\%CMDproc%" /v AutoRun |>"%temp%\autorun.tmp~" %find% "REG_"
) else if defined wmic (
2>nul %wmic% /NameSpace:\\root\default Class StdRegProv Call GetExpandedStringValue hDefKey="&H%HKLM%" sSubKeyName="%CMDproc%" sValueName="AutoRun" |>"%temp%\autorun.tmp~" %findstr% /rc:"\<[su]Value = "
)
<"%temp%\autorun.tmp~" set /p "AutoRunSys="
del "%temp%\autorun.tmp~"
:: check elevation and Admin membership
set "RunAs="
%net% session >nul 2>&1 && (set "RunAs=Yes")
if not defined RunAs if defined wmic (
2>nul %wmic% /NameSpace:\\root\default Class StdRegProv Call CheckAccess hDefKey="&H%HCU%" sSubKeyName="S-1-5-19" uRequired="&H1" |>nul %find% "TRUE" && set "RunAs=Yes"
)
if not defined RunAs set "RunAs=No"
set "LocalAdmin="
if defined whoami 2>nul %whoami% /groups|>nul %findstr% /i "\<S-1-5-32-544\>" && set "LocalAdmin=Yes" || set "LocalAdmin=No"
if not defined LocalAdmin if defined wmic (
for /f "tokens=1* delims==" %%i in (
'%wmic% path Win32_Group WHERE "LocalAccount='TRUE' AND SID='S-1-5-32-544'" GET Name /value'
) do for /f "delims=" %%k in ("%%j") do (
for /f "tokens=1* delims=:" %%l in ('2^>nul %gpresult% /r /scope user ^| %findstr% /n /c:"--------" /c:"%%k"') do (
set "check="
for /f "delims=- " %%n in ("%%m") do set "check=1"
if not defined check (
set "n=%%l"
set "LocalAdmin=No"
) else for /f %%n in ('set /a n') do if %%n lss %%l set "LocalAdmin=Yes"
)
)
) else set "LocalAdmin=Not found"
:: International
for %%a in ("iDate" "LocaleName") do set "%%~a="
if %RegUserInternational%==1 (call :RegInternational) else if defined wmic call :WmiInternational
if not defined iDate set "iDate=0"
if not defined LocaleName call :MUI
if "%iDate%"=="0" (set "format=mm/dd/yy") else if "%iDate%"=="1" (set "format=dd/mm/yy") else if "%iDate%"=="2" (set "format=yy/mm/dd")
:: ProductName
set "ProductName="
if %RegSysCurrentVersion%==1 (call :RegProductName) else if defined wmic call :WmiProductName
if not defined ProductName for /f "tokens=1* delims==" %%i in ('2^>nul %wmic% os get Caption /value') do set "ProductName=%%j"
:: Extensions and DelayedExpansion
for %%a in (es eu ds du) do set "%%a=Disabled"
if %RegUserCMDproc%==1 (call :RegUserProc) else if defined wmic call :WmiUserProc
if %RegSysCMDproc%==1 (call :RegSysProc) else if defined wmic call :WmiSysProc
if not defined eu set "eu=%ex_noreg%"
if not defined du set "du=%de_noreg%"
:: Code Pages
set "OEMCP=" &set "ACP="
if %RegSysCodePage%==1 (call :RegCodePage) else if defined wmic call :WmiCodePage
if not defined OEMCP for /f "tokens=2 delims=:" %%i in ('%chcp%') do set /a "OEMCP=%%~ni"
if not defined ACP (
if defined wmic (
for /f "tokens=2 delims==" %%i in ('%wmic% os get CodeSet /value') do set /a "ACP=%%i"
)
)
:: checks path
:: removes random double quotes, adds double quotes, removes trailing slash
:: http://stackoverflow.com/questions/5471556/pretty-print-windows-path-variable-how-to-split-on-in-cmd-shell/5472168#5472168
set "p=%path:"=""%"
set "p=%p:^=^^%"
set "p=%p:&=^&%"
set "p=%p:|=^|%"
set "p=%p:<=^<%"
set "p=%p:>=^>%"
set "p=%p:;=^;^;%"
set p=%p:""="%
set "p=%p:"=""%"
set "p=%p:;;="";""%"
set "p=%p:^;^;=;%"
set "p=%p:""="%"
set "p=%p:"=""%"
set "p=%p:"";""=";"%"
set "p=%p:"""="%"
set "p=%p:\"="%"
:: Check for 64 bit windows.
set "bit="
if defined wmic (
for /f "tokens=1* delims==" %%i in ('2^>nul %wmic% os GET OSArchitecture /value') do for /f "delims=" %%k in ("%%j") do set "bit=%%k"
)
if defined bit (echo "%bit%"|%find% "64" >nul && set "bit=64" || set "bit=32") else (
echo "%PROCESSOR_ARCHITECTURE%"|%find% "86" >nul && set "bit=32" || (
if exist "%SystemRoot%\SysWOW64\" (set "bit=64") else set "bit=32"
)
)
:: RAM space
set "ram="
if defined wmic (
for /f "tokens=1* delims==" %%i in ('2^>nul %wmic% os GET TotalVisibleMemorySize /value') do for /f "delims=" %%k in ("%%j") do set "ram=%%k"
)
:: get Windows version and the DIR command format to display
if "%notepad:~-3%"=="exe" (
>nul %chcp% %ACP%
for /f "delims=" %%a in ('^>nul %chcp% %ACP% ^&ver') do set "WinVer=%%a"
if exist "%SystemDrive%\pagefile.sys" (
for /f "delims=" %%a in ('^>nul %chcp% %ACP% ^&dir "%SystemDrive%\pagefile.sys" /a ^|%find% ":"') do set "DirFormat=%%a"
) else for /f "delims=" %%a in ('^>nul %chcp% %ACP% ^&dir "%__APPDIR__%ntoskrnl.exe" /a ^|%find% ":"') do set "DirFormat=%%a"
>nul %chcp% %OEMCP%
) else (
for /f "delims=" %%a in ('ver') do set "WinVer=%%a"
if exist "%SystemDrive%\pagefile.sys" (
for /f "delims=" %%a in ('dir "%SystemDrive%\pagefile.sys" /a ^|%find% ":"') do set "DirFormat=%%a"
) else for /f "delims=" %%a in ('dir "%__APPDIR__%ntoskrnl.exe" /a ^|%find% ":"') do set "DirFormat=%%a"
)
set "pad= "
:: create the information file and send the information to the clipboard if clip is available
>>"%temp%\info.txt" (
setlocal EnableDelayedExpansion
echo Windows version : !WinVer!
echo Product name : !ProductName!, !bit! bit
echo Performance indicators : Processor Cores: !NUMBER_OF_PROCESSORS! Visible RAM: !ram! kilobytes&echo(
echo Date/Time format : (!format!^) !date! !time!
echo __APPDIR__ : !__APPDIR__!
echo ComSpec : !comspec!
echo PathExt : !PathExt!
echo Extensions : system: !es! user: !eu!
echo Delayed expansion : system: !ds! user: !du!
echo Locale name : !LocaleName! Code Pages: OEM !OEMCP! ANSI !ACP!
echo DIR format : !DirFormat!
echo Permissions : Elevated Admin=!RunAs!, Admin group=!LocalAdmin!
if defined AutoRunSys echo System Autorun found : !AutoRunSys!
if defined AutoRunUser echo User AutoRun found : !AutoRunUser!
endlocal&echo(
rem report if path elements are missing
for %%i in (%dirs%) do (
set "found="
setlocal EnableDelayedExpansion
for %%j in ("!p!") do (
endlocal
if /i "%%~i"==%%j set "found=1"
setlocal EnableDelayedExpansion
)
endlocal
if not defined found echo(%pad%Missing from the PATH environment: %%~i
)
rem report if tools are missing
for %%i in (%tools%) do for /f "tokens=1,2 delims=?" %%j in ("%%~i.exe?%%~i.com") do if "%%~$PATH:j%%~$PATH:k"=="" (
echo(%pad%Missing from the tool collection: %%i
)
echo [/code^]
)
:: load the information into Notepad where it can also be copied to the clipboard
start "" %notepad% "%temp%\info.txt" & %ping% -n 2 127.0.0.1 >nul & del "%temp%\info.txt"
goto :eof
:: ~~~~~~~~~ Sub Routines ~~~~~~~~~
:RegInternational
for /f "tokens=1,2*" %%a in ('%reg% query "HKCU\%International%" /v "iDate" 2^>nul ^| %find% "REG_"') do set "%%~a=%%~c"
if %RegDefInternational%==1 for /f "tokens=1,2*" %%a in ('%reg% query "HKU\.DEFAULT\%International%" /v "iDate" 2^>nul ^| %find% "REG_"') do if not defined %%~a set "%%~a=%%~c"
for /f "tokens=1,2*" %%a in ('%reg% query "HKCU\%International%" /v "LocaleName" 2^>nul ^| %find% "REG_"') do set "%%~a=%%~c"
goto :eof
:WmiInternational
%RegHead% GetStringValue hDefKey^="&H%HKCU%" sSubKeyName^="%international%" sValueName^="iDate" %RegTail%
if not defined dat %RegHead% GetStringValue hDefKey^="&H%HKU%" sSubKeyName^=".DEFAULT\%international%" sValueName^="iDate" %RegTail%
if defined dat (set "iDate=%dat%") else set "iDate=0"
%RegHead% GetStringValue hDefKey^="&H%HKCU%" sSubKeyName^="%international%" sValueName^="LocaleName" %RegTail%
if defined dat (set "LocaleName=%dat%") else set "LocaleName="
goto :eof
:MUI
for /f "tokens=2 delims=={}" %%i in ('2^>nul %wmic% os get MUILanguages /value') do set "LocaleName=%%i"
if defined LocaleName (
set "LocaleName=%LocaleName:"=%"
) else (
setlocal EnableDelayedExpansion
for /f %%i in ('dir /ad /b "%__APPDIR__%??-??"^|%findstr% /x "[a-z][a-z]-[a-z][a-z]"') do (
if exist "%__APPDIR__%%%i\ulib.dll.mui" set "LocaleName=!LocaleName!,%%i"
)
if defined LocaleName (for /f %%j in ("!LocaleName:~1!") do (endlocal &set "LocaleName=%%j")) else endlocal
)
goto :eof
:RegProductName
for /f "tokens=2*" %%a in ('%reg% query "HKLM\%CurrentVersion%"^|%find% /i "ProductName"') do set "ProductName=%%b"
goto :eof
:WmiProductName
%RegHead% GetStringValue hDefKey^="&H%HKLM%" sSubKeyName^="%CurrentVersion%" sValueName^="ProductName" %RegTail%
if defined dat (set "ProductName=%dat%") else set "ProductName="
goto :eof
:RegUserProc
%reg% query "HKCU\%CMDproc%" /v "EnableExtensions" 2>nul|%find% "0x1">nul && set "eu=Enabled "
%reg% query "HKCU\%CMDproc%" /v "DelayedExpansion" 2>nul|%find% "0x1">nul && set "du=Enabled "
goto :eof
:WmiUserProc
%RegHead% GetDWORDValue hDefKey^="&H%HKCU%" sSubKeyName^="%CMDproc%" sValueName^="EnableExtensions" %RegTail%
if "%dat%"=="1" set "eu=Enabled "
%RegHead% GetDWORDValue hDefKey^="&H%HKCU%" sSubKeyName^="%CMDproc%" sValueName^="DelayedExpansion" %RegTail%
if "%dat%"=="1" set "du=Enabled "
goto :eof
:RegSysProc
%reg% query "HKLM\%CMDproc%" /v "EnableExtensions" 2>nul|%find% "0x1">nul && set "es=Enabled "
%reg% query "HKLM\%CMDproc%" /v "DelayedExpansion" 2>nul|%find% "0x1">nul && set "ds=Enabled "
goto :eof
:WmiSysProc
%RegHead% GetDWORDValue hDefKey^="&H%HKLM%" sSubKeyName^="%CMDproc%" sValueName^="EnableExtensions" %RegTail%
if "%dat%"=="1" set "es=Enabled "
%RegHead% GetDWORDValue hDefKey^="&H%HKLM%" sSubKeyName^="%CMDproc%" sValueName^="DelayedExpansion" %RegTail%
if "%dat%"=="1" set "ds=Enabled "
goto :eof
:RegCodePage
for /f "tokens=3" %%a in ('%reg% query "HKLM\%CodePage%" /v "OEMCP"') do set /a "OEMCP=%%a"
for /f "tokens=3" %%a in ('%reg% query "HKLM\%CodePage%" /v "ACP"') do set /a "ACP=%%a"
goto :eof
:WmiCodePage
%RegHead% GetStringValue hDefKey^="&H%HKLM%" sSubKeyName^="%CodePage%" sValueName^="OEMCP" %RegTail%
if defined dat (set "OEMCP=%dat%") else set "OEMCP="
%RegHead% GetStringValue hDefKey^="&H%HKLM%" sSubKeyName^="%CodePage%" sValueName^="ACP" %RegTail%
if defined dat (set "ACP=%dat%") else set "ACP="
goto :eof
Steffen
//EDIT
09/09/2016 replaced %sys32% with %__APPDIR__%, changed code page to get the Windows version, added the contents of %__APPDIR__% and %PATHEXT% to the output, corrected wrong WHOAMI handling
09/07/2016 removed clock hours, added ComSpec and AutoRun check
09/03/2016 corrected the WMIC registry handling
09/01/2016 corrected the code page handling, removed CLIP
08/31/2016 switch to ANSI code page when outputting the DIR format
08/29/2016 corrected unit of visible RAM, added alternative file for DIR format
Re: Creating a script to gather PC information - to assist those asking for help
Is there a specific reason for using pagefile.sys?
I'd suggest an essential file, such as %WinDir%\system32\ntoskrnl.exe, one defined in the system environment such as, %comspec% or even using one of the files you've already determined the existence of elsewhere in the script.
I'd suggest an essential file, such as %WinDir%\system32\ntoskrnl.exe, one defined in the system environment such as, %comspec% or even using one of the files you've already determined the existence of elsewhere in the script.
Re: Creating a script to gather PC information - to assist those asking for help
Compo wrote:Is there a specific reason for using pagefile.sys?
Its size is another indicator for the performance. Thus, it's a good choice in my opinion.
Steffen
Re: Creating a script to gather PC information - to assist those asking for help
Regardless of reasons why it shouldn't be, I know of many people who remove it or simply move it, and there are many sites explaining how to do so.
Re: Creating a script to gather PC information - to assist those asking for help
Point taken. Thanks! As soon as I update the script next time I'll choose another file.
Steffen
Steffen
Re: Creating a script to gather PC information - to assist those asking for help
Compo wrote:Regardless of reasons why it shouldn't be, I know of many people who remove it or simply move it, and there are many sites explaining how to do so.
You're right Compo, as I ran without a page file for years.
I would comment though that a person who has disabled or moved their page file is likely to have a fairly good ability and understanding of general computer technology and will have a good level of awareness of information needed in batch scripting.
The point of pagefile.sys was that it shows the amount of virtual ram and also the last boot time as a byproduct of the file list itself. These give indications that may be useful in diagnosing a problem but aren't harmful in any way. Accordingly I'd suggest that the c:\pagefile.sys be tested for and if it doesn't exist then a different file can be used.
aGerman, you've taken this a long way with all the input here.
This is the output of your last script as a sample.
Code: Select all
----------------------------------------------------------------------------
Windows version : Microsoft Windows [Version 6.3.9600]
Product name : Windows 8.1 Pro with Media Center, 32 bit
Performance indicators : Processor Cores: 8 Visible RAM: 3390680 Bytes
Date/Time format : dd/mm/yy (24 hours) Mon 29/08/2016 23:03:15.81
Extensions : system: Enabled user: Enabled
Delayed expansion : system: Disabled user: Disabled
Locale name : en-AU Code Pages: OEM 850 ANSI 1252
DIR format : 29/08/2016 05:42 3,484,418,048 pagefile.sys
Permissions : Elevated Admin=No, Admin group=Yes
The RAM figure seems to be Kbytes. I didn't check the script to see (brain fade).