fredag den 4. marts 2011

Get username of process

So this is one more of those I hate WMI things. I needed to know the username of the owner of a process. As always I stumbled over

Public Shared Function GetProcessUserName(ByVal Process As Process) As String
    Dim sq As New ObjectQuery("Select * from Win32_Process Where ProcessID = '" & Process.Id & "'")
    Dim searcher As New ManagementObjectSearcher(sq)
    If searcher.Get.Count = 0 Then Return Nothing
    For Each oReturn As ManagementObject In searcher.Get
        Dim o As String() = New String(1) {}
        oReturn.InvokeMethod("GetOwner", DirectCast(o, Object()))
        Return o(1) & "\" & o(0)
    Return ""
End Function

it works, sure, but it isn't pretty and its WMI … did I mention I hate WMI ?

    TokenUser = 1
End Enum

Public Structure TOKEN_USER
End Structure

<StructLayout(LayoutKind.Sequential)> _
    Public Sid As IntPtr
    Public Attributes As Integer
End Structure

<DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function GetTokenInformation(ByVal hToken As IntPtr, ByVal tokenInfoClass As TOKEN_INFORMATION_CLASS, ByVal pTokenInfo As IntPtr, ByVal tokenInfoLength As Integer, <Out()> ByRef returnLength As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Public Shared Function GetProcessUserName(ByVal Process As Process) As String
    Dim hToken As IntPtr
        If (Not OpenProcessToken(Process.Handle, _
            TOKEN_QUERY, hToken)) Then
            'Throw New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error)
            Return ""
        End If
    Catch ex As Exception
        'Throw ex
        Return ""
    End Try
    Dim tokenInfoSize As Integer = 250
    Dim userTokenInfo As IntPtr = Marshal.AllocHGlobal(CInt(tokenInfoSize))
    If GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenUser, userTokenInfo, tokenInfoSize, tokenInfoSize) Then
        Dim tokUser As TOKEN_USER = DirectCast(Marshal.PtrToStructure(userTokenInfo, GetType(TOKEN_USER)), TOKEN_USER)
        Dim a As New SecurityIdentifier(tokUser.User.Sid)
        Return a.Translate(GetType(NTAccount)).ToString
    End If
    Return False
End Function

I love it! and it almost use the same amount of code lines … *cough*

1 kommentar: