Link to home
Start Free TrialLog in
Avatar of jskfan
jskfanFlag for Cyprus

asked on

a Script to retrieve user profile name

a Script to retrieve user profile name
I am looking for a script that ca retrieve the name of the user profile created on the workstation.
workstations are members of the domain and users have an account in the domain.

Sometimes when looking into C:\Documents and Settings, you can see username by itself and sometimes username.domainname.

it's hard to know which one is the user using.

Thanks
Avatar of tojo2k
tojo2k

Is the user logged in?  The profile will be in an environment variable called USERPROFILE for each user.
I modified this for you in VB.net to retrieve a list of all local users together with their profile:
https://www.experts-exchange.com/questions/21919448/Get-List-of-User-Profiles.html

See code:

The attached file contains the compiled binary - rename txt to exe - if you dont have vb.net installed.
Form:
 
Public Class Form1
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim buf, ans As String
        Dim lp As New ListProfiles
 
        ans = ""
        ' Get profiles for the local PC
        For Each buf In lp.GetProfiles("")
            ans &= buf & vbCr
        Next
 
        MsgBox(ans)
 
    End Sub
End Class
 
 
 
 
 
 
Class:
 
Imports Microsoft.Win32
Imports System.Collections.Specialized
Imports System.Runtime.InteropServices
 
 
Public Class ListProfiles
 
    'BOOL LookupAccountSid(
    '  LPCTSTR lpSystemName,
    '  PSID lpSid,
    '  LPTSTR lpName,
    '  LPDWORD cchName,
    '  LPTSTR lpReferencedDomainName,
    '  LPDWORD cchReferencedDomainName,
    '  PSID_NAME_USE peUse
    ');
    Private Declare Auto Function LookupAccountSid Lib "advapi32.dll" ( _
        ByVal lpSystemName As String, _
        ByVal lpSid As IntPtr, _
        ByVal lpName As String, _
        ByRef cchName As Integer, _
        ByVal lpReferenceDomainName As String, _
        ByRef cchReferencedDomainName As Integer, _
        ByRef peUse As Integer _
    ) As Boolean
 
    'BOOL ConvertStringSidToSid(
    '  LPCTSTR StringSid,
    '  PSID* Sid
    ');
    Private Declare Auto Function ConvertStringSidToSid Lib "advapi32.dll" ( _
        ByVal StringSid As String, _
        ByRef Sid As IntPtr _
    ) As Boolean
 
    'BOOL ConvertSidToStringSid(
    '  PSID Sid,
    '  LPTSTR* StringSid
    ');
    Private Declare Auto Function ConvertSidToStringSid Lib "advapi32.dll" ( _
        ByVal Sid As IntPtr, _
        ByRef StringSid As IntPtr _
    ) As Boolean
 
    Private Const NAME_SIZE As Integer = 64
 
    Public Function GetProfiles(ByVal RemotePC As String) As StringCollection
        Dim ans As New StringCollection
        Dim reg_hklm, key, subkey As RegistryKey
        Dim keyname, UserID As String
        Dim RawSID() As Byte
        Dim RawProfile As String
 
        ' open the registry (could be remote)
        If RemotePC <> "" Then
            reg_hklm = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, RemotePC)
        Else
            reg_hklm = Registry.LocalMachine
        End If
 
        ' Get the list of profiles from the registry
        key = reg_hklm.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", False)
        If Not IsNothing(key) Then
            ' loop thru each subket
            For Each keyname In key.GetSubKeyNames
                subkey = key.OpenSubKey(keyname, False)
                RawSID = CType(subkey.GetValue("SID", Nothing), Byte())
                RawProfile = subkey.GetValue("ProfileImagePath", Nothing)
 
                If Not IsNothing(RawSID) Then
                    UserID = SidToName(RemotePC, RawSID)
                Else
                    ' If we don't have an imbedded SID, then we
                    ' use the key name instead
                    UserID = SidToName(RemotePC, keyname)
                End If
 
                ' add the UserID to our String Collection
                ans.Add(UserID & " - " & RawProfile)
            Next
        End If
 
        Return ans
    End Function
 
 
    '
    ' Take a "raw" SID (as a byte array) and determine the User ID (used in
    ' GetProfiles) (overloaded)
    '
    Private Function SidToName(ByVal RemotePC As String, ByVal RawSid As Byte()) As String
        Dim Sid As IntPtr
        Dim gch As GCHandle
        Dim ans As String
 
        ' get a safe pointer to the SID array of bytes
        gch = GCHandle.Alloc(RawSid, GCHandleType.Pinned)
        Sid = Marshal.UnsafeAddrOfPinnedArrayElement(RawSid, 0)
        ans = SidToName(RemotePC, Sid)
        gch.Free()
 
        Return ans
    End Function
 
    '
    ' Take a String version of a SID and generate a User ID (used in
    ' GetProfiles) (overloaded)
    '
    Private Function SidToName(ByVal RemotePC As String, ByVal sid_string As String) As String
        Dim sid As IntPtr
 
        sid = StringToSID(sid_string)
        If IsNothing(sid) Then
            Return sid_string
        End If
 
        Return SidToName(RemotePC, sid)
    End Function
 
    '
    ' Take an IntPtr SID and generate the User ID (overloaded)
    '
    Private Function SidToName(ByVal RemotePC As String, ByVal sid As IntPtr) As String
        Dim UserName, name, domain_name As String
        Dim name_len, domain_len, peUse As Integer
 
        name_len = NAME_SIZE
        domain_len = NAME_SIZE
        name = Space(name_len)
        domain_name = Space(domain_len)
 
        ' look up the Account associated with that SID
        If LookupAccountSid(RemotePC, sid, name, name_len, domain_name, domain_len, peUse) = False Then
            ' if the lookup fails, return the SID as as string
            Return SIDtoString(sid)
        End If
 
        ' put the name parts together
        If domain_len > 0 Then
            UserName = Left(domain_name, domain_len) & "\" & Left(name, name_len)
        Else
            If RemotePC = "" Then
                RemotePC = Environment.MachineName
            End If
            UserName = RemotePC & "\" & Left(name, name_len)
        End If
 
        Return UserName
    End Function
 
    '
    ' Convert a "raw" SID (as a byte array) into a string (overloaded)
    '
    Private Function SIDtoString(ByVal sidbyte As Byte()) As String
        Dim sid As IntPtr
        Dim gch As GCHandle
        Dim ans As String
 
        ' get a safe pointer
        gch = GCHandle.Alloc(sidbyte, GCHandleType.Pinned)
        sid = Marshal.UnsafeAddrOfPinnedArrayElement(sidbyte, 0)
        ans = SIDtoString(sid)
        gch.Free()
 
        Return ans
    End Function
 
    ' Convert a SID into the string version of the SID
    '
    Private Shared Function SIDtoString(ByVal sid As IntPtr) As String
        Dim ans As String
        Dim pStr As IntPtr
 
        ConvertSidToStringSid(sid, pStr)
        ans = Marshal.PtrToStringAuto(pStr)
        Marshal.FreeHGlobal(pStr)
 
        Return ans
    End Function
 
    '
    ' Convert a string representation of a SID into a real SID
    '
    Private Function StringToSID(ByVal buf As String) As IntPtr
        Dim sid As IntPtr
 
        If ConvertStringSidToSid(buf, sid) = False Then
            Return Nothing
        End If
 
        Return sid
    End Function
End Class

Open in new window

WindowsApplication1.zip
Basically the code above does the same like this script - but also converts the sid to a user name, so you know which profile belongs to which user
On Error Resume Next
 
Const HKEY_LOCAL_MACHINE = &H80000002
 
strComputer = "."
 
Set objRegistry=GetObject("winmgmts:\\" & _ 
    strComputer & "\root\default:StdRegProv")
 
strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys
 
For Each objSubkey In arrSubkeys
    strValueName = "ProfileImagePath"
    strSubPath = strKeyPath & "\" & objSubkey
    objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE,strSubPath,strValueName,strValue
    Wscript.Echo strValue
Next

Open in new window

Avatar of jskfan

ASKER

your last script looks like is run as a logon script.
if I replace  the strComputer = "."  with strComputer = "Realcomputername or Ip address."
then run it with Psexec remotely would that work
but I want the output to a text file so that I can see the profile name
another thing I want to know about this script, does it retrieve the profile name if the user is logged off??

I have added the last script just to show how to take the profiles out of the registry - so it takes ALL profiles even if the user is logged off (I think).
Here the code that writes a text file:
On Error Resume Next
 
Const HKEY_LOCAL_MACHINE = &H80000002
 
strComputer = "."
 
Set objRegistry=GetObject("winmgmts:\\" & _ 
    strComputer & "\root\default:StdRegProv")
 
strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys
 
 
'Open file
Set fso = CreateObject("Scripting.FileSystemObject") 
Set txtstr = fso.CreateTextFile("profiles.txt", True)
 
 
'Output
For Each objSubkey In arrSubkeys
    strValueName = "ProfileImagePath"
    strSubPath = strKeyPath & "\" & objSubkey
    objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE,strSubPath,strValueName,strValue
    txtstr.WriteLine strValue
Next
 
txtstr.close

Open in new window

Avatar of jskfan

ASKER

I meant the:  strComputer = "."

Means the script can do the job only if you make it as a logon script, since the variable doesn't specify any computer name.

I would like to have a script that reads computer names or IP from a text file and output the result to another text file.
if you can modify your script to do so, that would be great.

>I meant the:  strComputer = "."
"." is localhost
You can remotely connect to the registry of another system if you have the rights.


>Means the script can do the job only if you make it as a logon script
Why? I don't know what you mean. I don't take it as logon script. I testet it locally as logged on user and remotely on a computer where no one is logged on.


>since the variable doesn't specify any computer name.
ignore this fact - in you original question you just wanted "a Script to retrieve user profile name".
This script returns ALL user profiles registered on the machine it runs (or it connects to if you set strComputer to another value).


>I would like to have a script that reads computer names or IP from a text file
>and output the result to another text file
>if you can modify your script to do so, that would be great
So your goal is that you run the script let's say on the domain controler which collects all profiles stored on the clients given in text file?
Avatar of jskfan

ASKER

ok...to make it simple,
let's say there is a remote computer in the network named "RemComputer"
so in the script I can just replace ""strComputer = "."  with  strComputer = "RemComputer"
I will run the script from my compyter and this will work??



ASKER CERTIFIED SOLUTION
Avatar of cmorbach
cmorbach
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jskfan

ASKER

Thanks a lot it works