All,
I am currently developing a program that will enable users to create and switch desktops as they so please. However, I am having a bit of trouble with the GetUserObjectInformation API. I either get a value of 0 being returned or so many errors I am about to go nuts. Does anyone know the correct way of calling this in VB.Net 2005. I have tried many different variations but none seem to work. I do know that I need to call it once to get the lpnLengthNeeded which will then ReDim pvInfo(lpnLengthNeeded - 1) so that it will be able to hold all of the data. Now nLength I am not sure exactly what needs to go their as I am so lost right now I don't know which way I'm going.
Here is the link to the documentation from MS in C. So if anyone knows how to do it please let me know. I am trying to get the Desktop Name in case you were wondering. Thanks.
Also, here is a link to EE that I have been trying to get some feedback on if you need what all I have tried.
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/Q_21715367.html
Jason

API GetUserObjectInformation
Bruno Denuit - MSFT
Okay. Here is my form load and the declaration
<DllImport(
"user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ Public Function GetUserObjectInformation(ByVal hObj As IntPtr, ByVal nIndex As Int32, ByRef pvInfo As Byte(), ByVal nLength As Byte(), ByRef lpnLengthNeeded As Integer) As Boolean End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim i As Short Dim tempDesktopName As String Dim tempDesktopHandle As Integer 'Check to see if INI File Exists If System.IO.File.Exists(INIFILE) = False ThenSystem.IO.File.Create(INIFILE).Close()
End IfGetDesktopName()
'Get Desktop Count and Set Auto Switch to ValueDesktopCount = GetFromINI(
"Main", "Desktop Count", 1, INIFILE)btnAutoSwitch.Checked = GetFromINI(
"Main", "Auto Switch", False, INIFILE) 'Get Default Desktop Information TrytDefaultDesktop = GetThreadDesktop(GetCurrentThreadId())
hDefaultDesktop = OpenInputDesktop(0,
False, DESKTOP_SWITCHDESKTOP)sDefaultDesktop =
"Default" Catch ex As ExceptionMsgBox(
"Error Code: " & Err.LastDllError, MsgBoxStyle.Critical, "Open Input Desktop Error") End Try 'Setup Desktops If DesktopCount > 1 Then For i = 1 To DesktopCount - 1tempDesktopName = GetFromINI(
"Desktop" & i, "Desktop Name", Nothing, INIFILE) If tempDesktopName <> "" Then TrytempDesktopHandle = CreateDesktop(tempDesktopName,
Nothing, 0, 0, GENERIC_ALL, 0) Catch ex As ExceptionMsgBox(
"Error Code: " & Err.LastDllError, MsgBoxStyle.Critical, "Create Desktop Error") End Try If tempDesktopHandle <> 0 ThenbtnToolStrip =
New ToolStripButton With btnToolStrip.Text = tempDesktopName
.ToolTipText =
"Desktop" & i End WithToolStrip1.Items.Add(btnToolStrip)
End If End If Next End If 'Register Bar TryRegisterBar()
Catch ex As ExceptionMsgBox(
"Error: " & ex.Message, MsgBoxStyle.Critical, "Register Bar Error") End Try 'Disable btnDefaultDesktop since we always start herebtnDefault.Enabled =
False 'Setup Current DesktophCurrentDesktop = hDefaultDesktop
sCurrentDesktop =
"Default"End Sub
Private Function GetDesktopName() As String Const ERROR_INSUFFICIENT_BUFFER& = 122 Const ERROR_PROC_NOT_FOUND& = 127 Dim buffer(15) As Byte Dim lpNeeded As Integer Dim threadID As Integer = GetCurrentThreadId() Dim desktop As IntPtr = GetThreadDesktop(threadID) Dim nLength() As Byte TryGetUserObjectInformation(desktop, UOI_NAME,
Nothing, nLength, lpNeeded) Catch ex As ExceptionMsgBox(Err.LastDllError)
End Try If lpNeeded <> 0 Then ReDim buffer(lpNeeded - 1) ReDim nLength(lpNeeded - 1) TryGetUserObjectInformation(desktop, UOI_NAME, buffer, nLength, lpNeeded + 1)
Catch ex As ExceptionMsgBox(Err.LastDllError)
End Try Dim i As Integer = 0 For i = 0 To buffer.Length - 1MsgBox(buffer(i).ToString)
Next End If End FunctionNow the thing is that in the GetDesktopName() Function is just a cluster. I am trying to do the best I can with it. Let me know if you need to see anymore of the code. But that is pretty much it. Basically what I need to do is get the desktopname on startup of the application since I can't move the process to a different desktop while it has hooks in a different one. So I have to Create another Process of the current application.
Thanks.
Jason
SujathaJaganathan
Mattias,
Thank you very much. We had tried the StringBuilder method before but we left nLength as an Integer. So we kept getting an error or it returned nothing. Any who. Here is the code again how I used it.
API Declaration
p(GetCurrentThreadId()), UOI_NAME, pvInfo, Nothing, lengthNeeded)
p(GetCurrentThreadId()), UOI_NAME, pvInfo, lengthNeeded, lengthNeeded)
Public Declare Function GetUserObjectInformation Lib "user32" Alias "GetUserObjectInformationA" (ByVal hObj As IntPtr, ByVal nIndex As Int32, ByVal pvInfo As System.Text.StringBuilder, ByVal nLength As Byte, ByRef lpnLengthNeeded As Integer) As Boolean
Form1_Load Event
Dim lengthNeeded As Integer
Dim pvInfo As New System.Text.StringBuilder
GetUserObjectInformation(GetThreadDeskto
If lengthNeeded <> 0 Then
GetUserObjectInformation(GetThreadDeskto
MsgBox(pvInfo.ToString)
End If
Thanks again. Very much appreciate it. :)
Jason
BPeck
Your declaration is overly generic. If you know you're going to request UOI_NAME you may as well type the pvInfo parameter accordingly. I think this should work better
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Function GetUserObjectInformation(ByVal hObj As IntPtr, ByVal nIndex As Int32, ByVal pvInfo As StringBuilder, ByVal nLength As Byte, ByRef lpnLengthNeeded As Integer) As Boolean
hal9000plus
Sorry, nLength should be an Integer, I accidentally left it as Byte.
You should also make sure your StringBuilder is large enough with the line
pvInfo = New StringBuilder(lengthNeeded)
noahmattern
Jason,
Can we see the code around the call to getobject and it's declaration in your project