Problemas con VBScript - Regresar cuando se ejecuta como servicio
-
18-09-2019 - |
Pregunta
Estoy trabajando en un script que se ejecuta bajo una utilidad de instalación personalizada, que se ejecuta como un servicio. Para obtener el nombre de usuario actual, el script ejecuta este comando:
str_Acct_Name_Val = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Logon User Name"
str_Acct_Name = RegRead(str_Acct_Name_Val)
Cuando ejecuto el script desde el símbolo del sistema, puede leer ese valor bien (en una cuenta de administrador). Cuando se intenta leer el valor con los privilegios de servicio/sistema local, la lectura falla.
¿Cuál es el problema aquí?
Editar: información adicional. Cuando se ejecuta como un servicio que llama al nombre de usuario actual, devuelve "sistema" y supongo que HKCU no "existe" bajo la vista del sistema, ya que técnicamente no hay usuario actual. Hay un usuario que inició sesión en ese momento, pero no en el alcance del script en ejecución. ¿Tal vez hay en algún lugar en HKLM, podría encontrar el usuario que se registra actualmente?
Solución
Si está decidido a obtener información del registro, deberá escanear las claves en HKEY_USERS (excepto .DEFECTO y *_Classes) para averiguar a los usuarios cuyos perfiles están cargados y que se registran así. Así es como el sistema de sysinternals Psloggedon La herramienta funciona, por cierto; Puede echar un vistazo a su código fuente (Archive.org lo tiene) para obtener la idea.
Alternativamente, si puede usar WMI, puede obtener la lista de los usuarios registrados en enumerar el Win32_LogonSession
instancias de clase y recuperar lo asociado Win32_Account
objetos; algo como esto:
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
También está el Win32ComputerSystem.UserName
Propiedad que contiene el nombre del usuario registrado cuyo escritorio está actualmente activo:
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
Otros consejos
HRM, me pregunto si funcionaría para usar el comando de host Windows Scripting para el usuario que se registra actualmente. Creo que eso funcionaría incluso si se le llame desde una cuenta de servicio.
Set WSHNetwork = CreateObject("WScript.Network")
strUSERID = UCase(WSHNetwork.UserName)
Si su proceso se está ejecutando como un servicio, como "sistema local", entonces devolverá el "sistema" como el usuario actual. El HKCU al comienzo de la clave de registro significa HKEY_CURRENT_USER, que será "sistema".
Como Windows puede tener múltiples usuarios que iniciarían sesión, incluso en versiones de "nivel de consumidor" (gracias al cambio rápido de usuarios), no hay una forma confiable de determinar quién es el usuario "actual", que yo sepa. Dependiendo de cómo se invoque el servicio del instalador, podría probar algo como tener un proceso que se ejecute en el inicio de cada usuario (es decir, los programas de inicio en el menú de inicio) que se registra con el servicio para decirle el nombre del nombre de la sesión actualmente iniciada. El usuario es. Este proceso probablemente también podría comunicarse con el servicio cuando ese usuario se desvía del usuario rápido, por lo que también puede manejar el caso en el que más de un usuario se registra en la máquina.