Sign in to follow this  
Followers 0

Change windows profile icon tile

10 posts in this topic

Posted

Taken from Joco Blog

If you compile this with .NET v2.0.50727 it generates an exe that can be used to change windows user profile icon tile by using command line.

syntax

tile_replace.exe "username" "pathtobmp"

eg

tile_replace.exe "ndog" "C:\ProgramData\Microsoft\User Account Pictures\Default Pictures\usertile12.bmp"

I would like to convert to this autoit 3, so no .NET framework overhead needed. Any ideas?

c:\Tile_replace.cs

using System;
using System.Runtime.InteropServices;

namespace FejesJoco
{
    class Program
    {
        [DllImport("shell32.dll", EntryPoint = "#262", CharSet = CharSet.Unicode, PreserveSig = false)]
        public static extern void SetUserTile(string username, int whatever, string picpath);

        [STAThread]
        static void Main(string[] args)
        {
            SetUserTile(args[0], 0, args[1]);
        }
    }
}

test.cmd

"C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe" "c:\Tile_replace.cs"
Tile_replace.exe "%USERNAME%" "C:\ProgramData\Microsoft\User Account Pictures\Default Pictures\usertile12.bmp"

Share this post


Link to post
Share on other sites



Posted

I have not tested, but I think it should look like:

$sUserName = "UserName"
$sPicPath = "C:\pic.jpg"

$hPicPath = DLLStructCreate("wchar[128]")
DllStructSetData($hPicPath, 1, $sPicPath)

$hUserName = DLLStructCreate("wchar[128]")
DllStructSetData($sUserName, 1, $sUserName)

$aRet = DllCall(@SystemDir & "\shell32.dll", "long", 262, "ptr", DllStructGetPtr($hUserName), "int", 0, "ptr", DllStructGetPtr($hPicPath))
MsgBox(4096, "SetUserTile", $aRet[1])

Share this post


Link to post
Share on other sites

Posted

NDog, did you get this working?

I recently discovered Joco's article too and built the .exe.

but i too would like to convert it to AutoIt as we use that

for our login scripts.

But i cannot get jscript's example to work.

$aRet[1]
does return something but nothing

happens, no usertile is created...

Share this post


Link to post
Share on other sites

Posted

Ok for anyone else looking into creating UserTile's with AutoIt,

I think i found it:

In this thread the original

author fejesjoco suggested you might have to call CoInitialize first.

Also, the username needs to be in DOMAIN\username or COMPUTERNAME\username format

So now it looks like this:

$sUserName = "DOMAIN\rvdmast"
$sPicPath = "\\server\data\fotos\rvdmast.jpg"

; call CoInitialize
DLLCall("ole32.dll","int","CoInitialize","ptr",0)

$hPicPath = DLLStructCreate("wchar[128]")
DllStructSetData($hPicPath, 1, $sPicPath)

$hUserName = DLLStructCreate("wchar[128]")
DllStructSetData($hUserName, 1, $sUserName)

$aRet = DllCall(@SystemDir & "\shell32.dll", "long", 262, "ptr", DllStructGetPtr($hUserName), "int", 0, "ptr", DllStructGetPtr($hPicPath))

MsgBox(4096, "SetUserTile", $aRet[0])

This seems to work.

Share this post


Link to post
Share on other sites

Posted

Thanks for this, I've also been looking at this recently because I looking at making use of photos stored in AD and wanted to combine the c# and powerscript into one logon script.

For those interested:

$objConnection = ObjCreate ( "ADODB.Connection" )
$objConnection.Provider = "ADsDSOObject"
$objConnection.Open ( "Active Directory Provider" )
; Set AD connection for command
$objCommand = ObjCreate ( "ADODB.Command" )
If Not IsObj ( $objCommand ) Then
    Exit
EndIf
$objCommand.ActiveConnection = $objConnection
$objRootDSE = ObjGet ( "LDAP://RootDSE" )
If @Error Then
    Exit
EndIf
$strDNSDomain = $objRootDSE.Get ( "defaultNamingContext" )  ; Retrieve the current AD domain name
$strHostServer = $objRootDSE.Get ( "dnsHostName" )
$strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & @UserName & ");distinguishedName;subtree"
$objRecordSet = $objConnection.Execute ($strQuery)
$LDAP = ObjGet ( "LDAP://" & $objRecordSet.fields (0).value )
$thumbnailPhoto = $LDAP.thumbnailPhoto
$objConnection.Close ( )
If $thumbnailPhoto = "" Then
    Exit
EndIf
 
 
; Store the User's photo in their profile folder
$File = FileOpen ( @UserProfileDir & "\usertile.jpg", 18 )
FileWrite ( $File, $thumbnailPhoto )
FileClose ( $File )
 
; call CoInitialize
DLLCall("ole32.dll","int","CoInitialize","ptr",0)
$hPicPath = DLLStructCreate("wchar[128]")
DllStructSetData($hPicPath, 1, @UserProfileDir & "\usertile.jpg")
$hUserName = DLLStructCreate("wchar[128]")
DllStructSetData($hUserName, 1,  @LogonDomain & "\" & @UserName)
$aRet = DllCall(@SystemDir & "\shell32.dll", "long", 262, "ptr", DllStructGetPtr($hUserName), "int", 0, "ptr", DllStructGetPtr($hPicPath))

If no image is stored then you could always use a default image such as company logo etc.

Share this post


Link to post
Share on other sites

Posted

Hello,

I've been looking for a way to change users tile image for a long time but for some reason the answers in this post don't seem to work for me and I don't understand why. I copied rvdmast's post, added some consolewrite debugging lines:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=chg_profile_pic.exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

If @UserName = "administrator" Then
    $domain = "\\" & EnvGet("JOINEDDOMAIN")
Else
    $domain = EnvGet("LOGONSERVER")
EndIf


$sUserName = "mathsdom\ad453"
$sPicPath = $domain & "\websites\htdocs-damtp\people\photos\all\root-pr.jpg"

; call CoInitialize
$dllcl = DLLCall("ole32.dll","int","CoInitialize","ptr",0)
ConsoleWrite ("$dllcl = " & $dllcl[1] & @CRLF)

$hPicPath = DLLStructCreate("wchar[128]")
ConsoleWrite ("$hPicPath = " & $hPicPath & @CRLF)

$hUserName = DLLStructCreate("wchar[128]")
DllStructSetData($hUserName, 1, $sUserName)
ConsoleWrite ("$hUserName = " & $hUserName & @CRLF)

$aRet = DllCall(@SystemDir & "\shell32.dll", "long", 262, "ptr", DllStructGetPtr($hUserName), "int", 0, "ptr", DllStructGetPtr($hPicPath))

MsgBox(4096, "SetUserTile", $aRet[0])

and get the following back:

+>13:08:34 AU3Check ended.rc:0
>Running:(3.3.6.1):C:\Program Files\AutoIt3\autoit3.exe "\\mathsdom\netlogon\scripts\change_profile_picture\change_picture2.au3"    
$dllcl = 0x00000000
$hPicPath =
$hUserName =
+>13:08:36 AutoIT3.exe ended.rc:0
>Exit code: 0   Time: 3.026

the msgbox returns with:

---------------------------

SetUserTile

---------------------------

-2147024893

---------------------------

OK

---------------------------

The tile doesn't change.

I don't understand all this Dll calling so I don't knwo what I should be getting back.

Anyone have any ideas what's going on?

cheers

Chris

Share this post


Link to post
Share on other sites

Posted

OK, problem solved, script now working. The cause was a mixture of my lack of understanding of the DLLCall, DLLStructCreate etc commands and also me passng the wrong domanusername. For those reading this thread wanting to script the user profile 'tile' change, this is what I've learnt.

First, the Autoit script that works:

$sUserName = @LogonDomain & "" & @UserName
$sPicPath = EnvGet("LOGONSERVER") & "websiteshtdocs-damtppeoplephotosall" & @UserName & "-pr.jpg"

; call CoInitialize
$dllcl = DLLCall("ole32.dll","int","CoInitialize","ptr",0)
;~ ConsoleWrite ("$dllcl = " & $dllcl[1] & ", @error = " & @error &  @CRLF)

$hPicPath = DLLStructCreate("wchar[128]")
DllStructSetData($hPicPath, 1, $sPicPath)
;~ ConsoleWrite ("$hPicPath = " & DllStructGetData  ($hPicPath, 1) & @CRLF)

$hUserName = DLLStructCreate("wchar[128]")
DllStructSetData($hUserName, 1, $sUserName)
;~ ConsoleWrite ("$hUserName = " & DllStructGetData  ($hUserName, 1) & @CRLF)
;~ ConsoleWrite ("DllStructGetPtr($hUserName) = " & DllStructGetPtr($hUserName) & @CRLF)
;~ ConsoleWrite ("DllStructGetPtr($hPicPath) = " & DllStructGetPtr($hPicPath) & @CRLF)

$aRet = DllCall(@SystemDir & "shell32.dll", "long", 262, "ptr", DllStructGetPtr($hUserName), "int", 0, "ptr", DllStructGetPtr($hPicPath))
;~ ConsoleWrite ("$aRet = " & @error & @CRLF)
;~ MsgBox(4096, "SetUserTile", $aRet[0])

I use a samba server for our Win7 Pro clients. In the script above I was using the wrong domain name, I was using the samba servers netbios name. This isused so many times when authenticating to net shares etc, I just got the wrong on. Then is was my lack of understanding about DLL's. First you 'call' one, then you create its structure, then you probe it - DllStructGetPtr. All being well, when the script is run, you should get a '0' as a result. What this is done is to make a new/modified .dat file in C:Usersall usersMicrosoftUser Account Pictures. The name of tis dat file will be in the form [domain name]+[username].dat. This is all that needed to change the profile tile, the change is immediate.

I also created an exe as per http://www.networksteve.com/forum/topic....tart_Menu_&_Logon/?TopicId=175. In notepad, cut-n-paste:

using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("shell32.dll", EntryPoint = "#262", CharSet = CharSet.Unicode, PreserveSig = false)]
public static extern void SetUserTile(string username, int whatever, string picpath);
[STAThread]
static void Main(string[] args)
{
SetUserTile(args[0], 0, args[1]);
}
}
}

Save this file as something.cs, e.g. profiletile.cs. Then compile it with:

c:WINDOWSMicrosoft.NETFrameworkv2.0.50727csc.exe profiletile.cs

This should produce a file called profiletile.exe. The syntax of the file is:

profiletile.exe domainusername full_path_to_jpg

Again, all this program does to create/modify the domain+username.dat file

Hope this helps others looking for a way to script a user profile tile change, good luck :D

Share this post


Link to post
Share on other sites

Posted

Thanks everyone for your contributions and working solutions. I have re read this thread as before I was sticking to the .net compiled version as it is only 4KB and works. However I am now having to compile an all in one embedded new user type script so this comes in useful.. Now if only anyone knows how to change the windows XP user tile easily please share...

Share this post


Link to post
Share on other sites

Posted

To change windows xp tiles this is easy, suprised no one beat me to it

HKLMSoftwareMicrosoftWindowsCurrentVersionHints%USERNAME% - PictureSource - REG_SZ - C:Documents and SettingsAll UsersApplication DataMicrosoftUser Account PicturesDefault Picturespicture.bmp

also windows copies that picture.bmp to C:Documents and SettingsAll UsersApplication DataMicrosoftUser Account Pictures and names it as %USERNAME%.bmp

Share this post


Link to post
Share on other sites

Posted

Thanks for this, I've also been looking at this recently because I looking at making use of photos stored in AD and wanted to combine the c# and powerscript into one logon script.

<snip>

$LDAP = ObjGet ( "LDAP://" & $objRecordSet.fields (0).value )

<snip>

[/autoit]

Thanks for the code; it works great -- for a valid user, that is. If I supply a non-existent user to the code, I get the following error:

==> The requested action with this object has failed.

Which is OK and expected. However, the script stops executing! I would like the script to continue with the rest of the code. I have even tried using "if (isObj $LDAP) then ..." to catch the error, but the script just bombs out.

How can I ignore this error and carry on with the rest of the code?

Any help would be much appreciated!

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  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.