views:

301

answers:

3

I am working on a script that runs under a custom installation utility, which is running as a service. To get the current user name the script executes this command:

str_Acct_Name_Val = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Logon User Name"
str_Acct_Name = RegRead(str_Acct_Name_Val)

When I run the script from the command prompt, it can read that value just fine (under an administrator account). When the value is attempted to be read with service/local system privileges, the read fails.

What is the problem here?

EDIT: Some additional information. When running as a service calling the current user name returns "SYSTEM" and my guess is that HKCU doesn't "exist" under the view of the SYSTEM, since there is technically no current user. There is a user logged in at the time, but not in the scope of the running script. Maybe there is somewhere in HKLM I could find the currently logged on user?

A: 

Hrm, I wonder if it would work to use the Windows Scripting Host command for the currently logged in user. I would think that would work even if called from a service account.

Set WSHNetwork = CreateObject("WScript.Network")    
strUSERID = UCase(WSHNetwork.UserName)
unrealtrip
Nope, that'll be System.
Helen
A: 

If your process is running as a service, as "LOCAL SYSTEM", then it will indeed return "SYSTEM" as the current user. The HKCU at the beginning of the registry key means HKEY_CURRENT_USER, which will be "SYSTEM".

As Windows can have multiple users logged on, even on "consumer level" versions (thanks to Fast User Switching), there's no reliable way to determine who the "current" user is, as far as I'm aware. Depending on how the installer service is invoked, you could try something like having a process that runs on startup for each user (i.e. in Startup programs in the Start menu) that registers with the service to tell it what the name of the currently logged on user is. This process could probably also communicate to the service when that user is fast-user switched away from, so it can also handle the case where more than one user is logged onto the machine.

Rob
A: 

If you are determined to get information from the registry, you will have to to scan the keys under HKEY_USERS (except .DEFAULT and *_Classes) to find out the users whose profiles are loaded and who are thus logged on. This is how the SysInternals PsLoggedOn tool works, by the way; you can take a look at its source code (Archive.org has it) to get the idea.

Alternatively, if you can use WMI, you can get the list of the logged on users by enumerating the Win32_LogonSession class instances and retrieving the associated Win32_Account objects; something like this:

strComputer = "."

Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") 

Set colSessions = oWMI.ExecQuery _ 
    ("SELECT * FROM Win32_LogonSession WHERE LogonType = 2")  ' Interactive sessions only

For Each oSession in colSessions 
  Set colAccounts = oWMI.ExecQuery("ASSOCIATORS OF {Win32_LogonSession.LogonId=" & oSession.LogonId & "} " _ 
    & "WHERE AssocClass=Win32_LoggedOnUser Role=Dependent" ) 
  For Each oAccount in colAccounts
    WScript.Echo "Caption: " & oAccount.Caption
    WScript.Echo "Domain: "  & oAccount.Domain
    WScript.Echo "Name: "    & oAccount.Name
  Next 
Next

There's also the Win32ComputerSystem.UserName property that holds the name of the logged on user whose desktop is currently active:

strComputer = "." 
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
Set colItems = oWMI.ExecQuery("SELECT * FROM Win32_ComputerSystem") 
For Each objItem in colItems 
  Wscript.Echo objItem.UserName
Next
Helen