Jump to content

Create a Portable Desktop by updating location of user's desktop folder on the fly (like TweakUI)


sinistlor
 Share

Recommended Posts

I am attempting to create a portable desktop. I want the script to replace the user's desktop suddenly with a custom folder they can carry around on a thumb drive. The reason being that I know my users are going to be lazy and I want them to be able to just store files on the desktop but be able to carry those files around with them.

The Microsoft powertoy TweakUI changes where the special folder location of the desktop points to (once you make the change in TweakUI, one simply has to send a refresh to the desktop to have the change go live). My question is specifically how can I make AutoIt do exactly the same thing?

I am totally new to scripting and especially new to using DLL's so I know very little about the windows shell or structures or pointers so please help me out! I know I can accomplish what I want to do by simply changing the registry values indicating the desktop location and then restart explorer.exe but this is crude and ungraceful. I think I have a general framework for what must happen. I think I am using the shell32.dll functions ILCreateFromPath and SHParseDisplayName to create the thing I need to pass to the 0x00020000 eventID of the SHChangeNotify function. I'm not sure if I need to add some registry changing function as well?

This is what I have so far. As far as I can tell, the only part of this that works is the part that sends a simple refresh to the desktop. Please be careful running the following code as it is dysfunctional and may cause explorer to hang!

#include-once
#include <Constants.au3>

DllOpen("shell32.dll")

;Create pidl for old desktop
$OldDesktop = "C:\Documents and Settings\Administrator\Desktop"
$oldppidl = DllCall("shell32.dll", "ptr", "ILCreateFromPath", "wstr", $OldDesktop)
$structureToMake = "int_ptr pbc;int_ptr ppidl;uint sfgaoIn;uint psfgaoOut"
$oldpdn = DllStructCreate($structureToMake)
DllStructSetData($oldpdn,"pbc",0)
DllStructSetData($oldpdn,"ppidl",$oldppidl)
DllStructSetData($oldpdn,"sfgaoIn",0)
DllStructSetData($oldpdn,"psfgaoOut",0)
$oldret = DllCall("shell32.dll", "int", "SHParseDisplayname", "wstr",  $OldDesktop, "ptr", DllStructGetData($oldpdn,"pbc"), "ptr", DllStructGetData($oldpdn,"ppidl"), "int", DllStructGetData($oldpdn,"sfgaoIn"), "ptr", DllStructGetData($oldpdn,"psfgaoOut"))

;Create pidl for new desktop
$NewDesktop = "E:\PortableDesktop"
$newppidl = DllCall("shell32.dll", "ptr", "ILCreateFromPath", "wstr", $NewDesktop)
$newpdn = DllStructCreate($structureToMake)
DllStructSetData($newpdn,"pbc",0)
DllStructSetData($newpdn,"ppidl",$newppidl)
DllStructSetData($newpdn,"sfgaoIn",0)
DllStructSetData($newpdn,"psfgaoOut",0)
$newret = DllCall("shell32.dll", "int", "SHParseDisplayname", "wstr",  $NewDesktop, "ptr", DllStructGetData($newpdn,"pbc"), "ptr", DllStructGetData($newpdn,"ppidl"), "int", DllStructGetData($newpdn,"sfgaoIn"), "ptr", DllStructGetData($newpdn,"psfgaoOut"))

;Notify the shell to change the desktop folder. This is attempting to do what TweakUI does
DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x00020000, "uint", 0x1000, "ptr", $oldret, "ptr", $newret)

;Send simple refresh to desktop. (Like hitting F5)
DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x8000000, "uint", 0x1000, "ptr", 0, "ptr", 0)

DllClose("shell32.dll")

Ok as a clue, I believe this C# code does what I want. I am not familiar with C# and so this is like hieroglyphics to me. I did not write this, I found it on the web elsewhere:

SHChangeNotify with SHCNE_RENAMEFOLDER doing this.

1) Define Pinvoke functions:
[DllImport("shell32.dll")]
public static extern Int32 SHParseDisplayName( [MarshalAs(UnmanagedType.LPWStr)] String pszName, IntPtr pbc, out IntPtr ppidl, UInt32 sfgaoIn,  out UInt32 psfgaoOut);

[DllImport("Shell32.dll")]
public static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
2) Method to notify system about new desktop folder path:
public static void ApplyNewDesktopPath(string OldDesktop, string NewDesktop)
{
     uint iAttribute;
     IntPtr oldPidl;
     IntPtr newPidl;
     SHParseDisplayName(OldDesktop, IntPtr.Zero, out oldPidl, 0, out iAttribute);
     SHParseDisplayName(NewDesktop, IntPtr.Zero, out newPidl, 0, out iAttribute);
     SHChangeNotify(0x00020000, 0x1000, oldPidl, newPidl);
}
3) Refresh desktop to show new content:
public static void RefreshDesktop()
{
    SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
}
Edited by sinistlor
Link to comment
Share on other sites

There has been posted something like this before:

http://www.autoitscript.com/forum/index.php?showtopic=84641

http://www.autoitscript.com/forum/index.php?showtopic=8781

http://www.autoitscript.com/forum/index.php?showtopic=51122

http://www.autoitscript.com/forum/index.php?showtopic=49635&mode=threaded&pid=374329

Link to comment
Share on other sites

Thank you for the response! I checked out all those links and they all seem to have the same issue. F5-style refresh is not enough! I've already figured out how to send the F5-style refresh, which from reading those posts above seems to still be an unsolved issue for some people so I'll include how to do that right here:

;Send simple refresh to desktop (Like hitting F5 on desktop)
DllOpen("shell32.dll")
DllCall("shell32.dll", "none", "SHChangeNotify", "long", 0x8000000, "uint", 0x1000, "ptr", 0, "ptr", 0)
DllClose("shell32.dll")

Let's solve this once and for all, for all those people who wanna change the user's desktop environment and don't wanna kill explorer.exe! I know we can figure this out.

Link to comment
Share on other sites

Doing a F5 style refresh is not all that the pages describe. Especially the first topic described a whole range of methods to refresh the desktop.

The first post appears as though it never was solved. That poster had the same issue where it seemed like restarting explorer was the only answer. But I know it is possible to change the desktop folder easily because TweakUI does it perfectly (only requiring an additional F5-style send, which again is not a problem). Though the poster said none of the solutions worked for them, I will go ahead and try them myself just to make sure.

Link to comment
Share on other sites

That's a very smart thing to do. You're not trying the same thing as the OP, so one of the posted solutions that have not worked for him may work for you. Good luck.

So I gave up. I am just going to kill explorer to refresh the desktop location. I guess what I want to do is beyond the scope of AutoIt. Thanks anyway. Edited by sinistlor
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...