Jump to content
Sign in to follow this  
mec02

How to detect userprofiletype

Recommended Posts

mec02

Hi

how can i detect the type of the logged on userprofile (local or roaming)? I need a solution for registry or file/folder so i can do it within an autoit-script.

Thanks a lot.

MEC

Share this post


Link to post
Share on other sites
PsaltyDS

You could check the $oUser.profilePath attribute.

:idea:

Edit: Even better, UserEnv.dll with GetProfileType function:

Global Const $PT_LOCAL = 0
Global Const $PT_TEMPORARY = 1
Global Const $PT_ROAMING = 2
Global Const $PT_MANDATORY = 4

$iProfileType = 0
$aRET = DllCall("UserEnv.dll", "int", "GetProfileType", "DWORD*", $iProfileType)
Switch $iProfileType
    Case $PT_LOCAL
        $sProfileType = "Local"
    Case $PT_TEMPORARY
        $sProfileType = "Temporary"
    Case $PT_ROAMING
        $sProfileType = "Roaming"
    Case $PT_MANDATORY
        $sProfileType = "Mandatory"
EndSwitch
ConsoleWrite("Your profile type is:  " & $sProfileType & " (" & $iProfileType & ")" & @LF)

:)

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
mec02

Hi

it seems there is anything wrong. I get on local and roaming profiles the result "Roaming" because the variable $aRET is empty after dll-call. $iProfileType is always the same as set, it was not changed by the dll-call.

I'm a rookie in calling dlls, can you help me?

Should i check the $oUser.profilePath attribute? How can i do it?

Thanks

MEC

Share this post


Link to post
Share on other sites
PsaltyDS

Hmm, can't test because I don't have a roaming profile available here. Looks like the ByRef "DWORD*" didn't work. Try it this way, using a regular struct "ptr" and with some extra error handling added:

Global Const $PT_LOCAL = 0
Global Const $PT_TEMPORARY = 1
Global Const $PT_ROAMING = 2
Global Const $PT_MANDATORY = 4

$tProfileType = DllStructCreate("dword ProfileType")
DllStructSetData($tProfileType, "ProfileType", 0xFF) ; To verify it changes
$pProfileType = DllStructGetPtr($tProfileType)
$aRET = DllCall("UserEnv.dll", "int", "GetProfileType", "ptr", $pProfileType)
If (@error = 0) And $aRET[0] Then
    $iProfileType = DllStructGetData($tProfileType, "ProfileType")
    Switch $iProfileType
        Case $PT_LOCAL
            $sProfileType = "Local"
        Case $PT_TEMPORARY
            $sProfileType = "Temporary"
        Case $PT_ROAMING
            $sProfileType = "Roaming"
        Case $PT_MANDATORY
            $sProfileType = "Mandatory"
        Case Else
            $sProfileType = "<INVALID>"
    EndSwitch
    ConsoleWrite("Your profile type is:  " & $sProfileType & " (" & $iProfileType & ")" & @LF)
Else
    ConsoleWrite("Error:  @error = " & @error & "; $aRET[0] = " & $aRET[0] & @LF)
EndIf

:idea:

Edit: Note $aRET is an array. DllCall() always returns an array. If you look into the DllCall() being made, you see return type is "int" but that "int" is stored in the $aRet array. So the error checking tests $aRet[0] to see what the return value was.

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
mec02

Hi PsaltyDS

now it runs properly. :idea:

Thank you very much.

MEC

Share this post


Link to post
Share on other sites
trancexx

Hmm, can't test because I don't have a roaming profile available here. Looks like the ByRef "DWORD*" didn't work.

It worked. Like this:
$aRET = DllCall("userenv.dll", "bool", "GetProfileType", "dword*", 0)
;If @error Or Not $aRET[0] Then Return SetError(1, 0, "")
$iProfileType = $aRET[1] ;<- this!
;...

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
PsaltyDS

It worked. Like this:

$aRET = DllCall("userenv.dll", "bool", "GetProfileType", "dword*", 0)
;If @error Or Not $aRET[0] Then Return SetError(1, 0, "")
$iProfileType = $aRET[1] ;<- this!
;...
Hmm... That's cool if it works, but how do you arrive at that from the definition of the function?

Quoting MSDN on GetProfileType:

Parameters

pdwFlags [out]

DWORD

Pointer to a variable that receives the profile type. If the function succeeds, it sets one or more of the following values:

Making a value type ByRef in DllCall() doesn't usually mean it shows up in the returned array, does it?

:idea:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
trancexx

Hmm... That's cool if it works, but how do you arrive at that from the definition of the function?

Quoting MSDN on GetProfileType:

Making a value type ByRef in DllCall() doesn't usually mean it shows up in the returned array, does it?

:idea:

Because if you read DllCall() function description (byref related):

* - Add * to the end of another type to pass it by reference. For example "int*" passes a pointer to an "int" type.

And then:

Otherwise an array is returned that contains the function return value and a copy of all the parameters (including parameters that the function may have modified when passed by reference).

You will see that's what's really wanted by the GetProfileType function.

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
PsaltyDS

And then:

You will see that's what's really wanted by the GetProfileType function.

Aha! I had the first part, but missed the connection to the second part. Thanks.

Global Const $PT_LOCAL = 0
Global Const $PT_TEMPORARY = 1
Global Const $PT_ROAMING = 2
Global Const $PT_MANDATORY = 4

$aRET = DllCall("UserEnv.dll", "int", "GetProfileType", "DWORD*", -1)
If (@error = 0) And $aRET[0] Then
    $iProfileType = $aRET[1] ; [1] = first parameter (modified ByRef)
    Switch $iProfileType
        Case $PT_LOCAL
            $sProfileType = "Local"
        Case $PT_TEMPORARY
            $sProfileType = "Temporary"
        Case $PT_ROAMING
            $sProfileType = "Roaming"
        Case $PT_MANDATORY
            $sProfileType = "Mandatory"
        Case Else
            $sProfileType = "<INVALID>"
    EndSwitch
    ConsoleWrite("Your profile type is:  " & $sProfileType & " (" & $iProfileType & ")" & @LF)
Else
    ConsoleWrite("Error:  @error = " & @error & "; $aRET[0] = " & $aRET[0] & @LF)
EndIf

:idea:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
trancexx

Aha! I had the first part, but missed the connection to the second part. Thanks.

Global Const $PT_LOCAL = 0
Global Const $PT_TEMPORARY = 1
Global Const $PT_ROAMING = 2
Global Const $PT_MANDATORY = 4

$aRET = DllCall("UserEnv.dll", "int", "GetProfileType", "DWORD*", -1)
If (@error = 0) And $aRET[0] Then
    $iProfileType = $aRET[1] ; [1] = first parameter (modified ByRef)
    Switch $iProfileType
        Case $PT_LOCAL
            $sProfileType = "Local"
        Case $PT_TEMPORARY
            $sProfileType = "Temporary"
        Case $PT_ROAMING
            $sProfileType = "Roaming"
        Case $PT_MANDATORY
            $sProfileType = "Mandatory"
        Case Else
            $sProfileType = "<INVALID>"
    EndSwitch
    ConsoleWrite("Your profile type is:  " & $sProfileType & " (" & $iProfileType & ")" & @LF)
Else
    ConsoleWrite("Error:  @error = " & @error & "; $aRET[0] = " & $aRET[0] & @LF)
EndIf

:idea:

Yes, except you are not checking error properly. If error do occur with DllCall() you will exit unexpectedly because you are trying to access non-existing array. (edit: will try to access) Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
mec02

Hi

why have i to declare the constants?

Can i do it on this way:

$aRET = DllCall("UserEnv.dll", "int", "GetProfileType", "DWORD*", -1)
If (@error = 0) And $aRET[0] Then
    $iProfileType = $aRET[1] ; [1] = first parameter (modified ByRef)
    Switch $iProfileType
        Case 0
            $sProfileType = "Local"
        Case 1
            $sProfileType = "Temporary"
        Case 2
            $sProfileType = "Roaming"
        Case 3
            $sProfileType = "Mandatory"
        Case Else
            $sProfileType = "<INVALID>"
    EndSwitch
    ConsoleWrite("Your profile type is:  " & $sProfileType & " (" & $iProfileType & ")" & @LF)
Else
    ConsoleWrite("Error:  @error = " & @error & "; $aRET[0] = " & $aRET[0] & @LF)
EndIf

Share this post


Link to post
Share on other sites
PsaltyDS

Yes, except you are not checking error properly. If error do occur with DllCall() you will exit unexpectedly because you are trying to access non-existing array. (edit: will try to access)

No, the 'AND' makes it safe because it only tests $aRET[0] if @error = 0. If @error = 0 then DllCall() always returns an array. If @error <> 0 then $aRET[0] is not attempted because AND is already not satisfied. Demo:
$aRET = 0
SetError(1)

If (@error = 0) AND $aRET[0] Then
    ConsoleWrite("OK" & @LF)
Else
    ConsoleWrite("FAIL" & @LF)
EndIf

why have i to declare the constants?

Can i do it on this way:

No need to declare the constants unless you might re-use the function, where it would make things simpler (like in a UDF file). They were included for future reference.

:idea:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
trancexx

No, the 'AND' makes it safe because it only tests $aRET[0] if @error = 0. If @error = 0 then DllCall() always returns an array. If @error <> 0 then $aRET[0] is not attempted because AND is already not satisfied. Demo:

$aRET = 0
SetError(1)

If (@error = 0) AND $aRET[0] Then
    ConsoleWrite("OK" & @LF)
Else
    ConsoleWrite("FAIL" & @LF)
EndIf

You had this:

$aRET = 0
SetError(1)
If (@error = 0) And $aRET[0] Then
    ;...
    ;ConsoleWrite("Your profile type is:  " & $sProfileType & " (" & $iProfileType & ")" & @LF)
Else
    ConsoleWrite("Error:  @error = " & @error & "; $aRET[0] = " & $aRET[0] & @LF)
EndIf

Right?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
PsaltyDS

You're right. I was only looking at the 'IF' line, but it will fail in the 'Else' because of the console write with $aRET[0].

Doh! :idea:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
jterwelp

Is there a way to modify this solution to work with older versions of AutoIt? Specifically 3.2.4.9, which does not support appending "*" to the type in order to pass by reference. Thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×