locked
Save Desktop Icon State RRS feed

  • Question

  • Hi and thanks for reading;

    I need to store the state of the icons on the desktop and so far, haven't been able to determine where/how their state is stored.  By state I mean the position and particular icons, the desktop theme, etc.  Once I know how the icons and their respective locations are stored, I can proceed with my final goal but have yet to determine where and how this is stored.  

    Thanks for all help and reading my question.

    Glenn


    Glenn T. Kitchen αβθ-Coding™†

    Wednesday, February 1, 2017 9:34 PM

Answers

  • I don't understand your fault.  My original concern was knowing where and how to obtain the DT icons' location and name; the means by which this information is stored doesn't have to adhere to, or override Windows means of storage for my project.  Further, storing the screen parameters as well allows restore, yes?

    Please let me know if I'm missing something from your indicated fault-point.  

    I sincerely thank you for your criticisms, as that's how the best code is written - have it ultimately scrutinized! 


    Glenn T. Kitchen VB.NET Forums

    As noted above.  The locations are not documented and change from OS to OS.  They cannot be reliable saved and restored.  Many have tried and all have failed or you would see a solution posted in the Gallery with a high download number.

    You can use the  MS export wizard to save the settings and restore them but even that fails if the target system is not identical.  A restore failure causes all icons to their leftmost position.  Even a roamed profile cannot resolve differences as most who have used one on multiple machines will know.  Sometimes it works and sometimes it doesn't.

    I have one site with supposedly identical workstations.  One doesn't get the positions correctly the first time the account logs in.  After some time I realized the graphics card was different.  Funny it will retain settings after the icons are repositioned but it is not copied from other machines.

    The only good way to save a desktop configuration is with the USMT tool or wizard and even that does not work between different OSs when it comes to desktop icon placement.


    \_(ツ)_/

    Friday, February 3, 2017 8:02 PM

All replies

  • Which icons, and why?

    -- Bill Stewart [Bill_Stewart]

    Wednesday, February 1, 2017 10:01 PM
  • The desktop icons and positions are stored in a set of binary keys in the registry.  This is not documented by Microsoft and each version of Windows does it somewhat differently.


    \_(ツ)_/

    Wednesday, February 1, 2017 10:36 PM
  • All icons and because it is an integral part of the project I'm working on.  Thanks for your input.

    Glenn T. Kitchen αβθ-Coding™†


    • Edited by piCircles Thursday, February 2, 2017 5:52 PM Misspelled words
    Thursday, February 2, 2017 5:50 PM
  • As jrv said, specific icon locations are stored as binary data in the registry, and there are no public APIs for reading and setting this information.


    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Bill_Stewart Saturday, February 4, 2017 8:54 PM
    Thursday, February 2, 2017 6:00 PM
  • How about this, though this is C++:

    ================================================================================ Saving and Restoring Desktop Icons C++ Steps ================================================================================ I'm stepping through the required code: We'll call IFolder­View::Get­Item­Position and IFolder­View::Select­And­Position­Items. First, I'll extract the IFolder­View from a window. =================]-->> CODE PEICE 1 <<--[============================================== void FindDesktopFolderView(REFIID riid, void **ppv) { CComPtr<IShellWindows> spShellWindows; spShellWindows.CoCreateInstance(CLSID_ShellWindows); CComVariant vtLoc(CSIDL_DESKTOP); CComVariant vtEmpty; long lhwnd; CComPtr<IDispatch> spdisp; spShellWindows->FindWindowSW( &vtLoc, &vtEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp); CComPtr<IShellBrowser> spBrowser; CComQIPtr<IServiceProvider>(spdisp)-> QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser)); CComPtr<IShellView> spView; spBrowser->QueryActiveShellView(&spView); spView->QueryInterface(riid, ppv); } =================]-->> END CODE PEICE 1 <<--[============================================== The Find­Desktop­Folder­View function obtains the shell view for the desktop. The call to Find­Window­SW gets a specific window by location. -The first parameter to Find­Window­SW. is the folder we are looking for. In our case, we are looking for the desktop. -The second parameter is reserved and must be VT_EMPTY. -The third parameter describes the type of windows we are looking for. We use the special SWC_DESKTOP flag to specify my desire for this unordinary (not Explorer) window. -The fourth parameter receives the window handle, which is of no interest to us, but the parameter is mandatory, so we have to give it something. -The fifth parameter specifies the search options. We use SWFO_NEED­DISPATCH to say, "Please return the IDispatch in the sixth parameter." And the sixth parameter is where we want the IDispatch to be returned. I can now enumerate all desktop icons and print their names and locations. =================]-->> CODE PEICE 2 <<--[============================================== #define UNICODE #define _UNICODE #include <windows.h> #include <shlobj.h> #include <exdisp.h> #include <shlwapi.h> #include <atlbase.h> #include <atlalloc.h> #include <stdio.h> // CCoInitialize incorporated by reference int __cdecl wmain(int argc, wchar_t **argv) { CCoInitialize init; CComPtr<IFolderView> spView; FindDesktopFolderView(IID_PPV_ARGS(&spView)); CComPtr<IShellFolder> spFolder; spView->GetFolder(IID_PPV_ARGS(&spFolder)); CComPtr<IEnumIDList> spEnum; spView->Items(SVGIO_ALLVIEW, IID_PPV_ARGS(&spEnum)); for (CComHeapPtr<ITEMID_CHILD> spidl; spEnum->Next(1, &spidl, nullptr) == S_OK; spidl.Free()) { STRRET str; spFolder->GetDisplayNameOf(spidl, SHGDN_NORMAL, &str); CComHeapPtr<wchar_t> spszName; StrRetToStr(&str, spidl, &spszName); POINT pt; spView->GetItemPosition(spidl, &pt); wprintf(L"At %4d,%4d is %ls\n", pt.x, pt.y, spszName); } return 0; } =================]-->> END CODE PEICE 2 <<--[============================================== After getting the IFolder­View, we can then print the icons' names. We ask the view for its Items enumeration, then proceed to enumerate each of the items. For each item, we ask the IShell­Folder for its name, and we ask the IFolder­View for its position. Then we print the results. We can also modify the icon names =================]-->> CODE PEICE 3 <<--[============================================== int __cdecl wmain(int argc, wchar_t **argv) { CCoInitialize init; CComPtr<IFolderView> spView; FindDesktopFolderView(IID_PPV_ARGS(&spView)); CComPtr<IEnumIDList> spEnum; spView->Items(SVGIO_ALLVIEW, IID_PPV_ARGS(&spEnum)); for (CComHeapPtr<ITEMID_CHILD> spidl; spEnum->Next(1, &spidl, nullptr) == S_OK; spidl.Free()) { POINT pt; spView->GetItemPosition(spidl, &pt); pt.x += (rand() % 5) - 2; pt.y += (rand() % 5) - 2; PCITEMID_CHILD apidl[1] = { spidl }; spView->SelectAndPositionItems( 1, apidl, &pt, SVSI_POSITIONITEM); } return 0; } =================]-->> END CODE PEICE 3 <<--[============================================== This time, instead of printing the item's name and position, we jiggle the icon position by a few pixels randomly, then set the jiggled coordinates as the new position. Turn off Auto arrange icons and Align icons to grid on the desktop, and then run this program. Hey, look, your icons shifted randomly by a few pixels. For extra hijinx, drop a call to spView->Set­Current­Folder­Flags(FWF_AUTO­ARRANGE | FWF_SNAP­TO­GRID, 0) before you enter the loop (to programmatically turn off auto-arrange and snap-to-grid), then put this program in a loop, and slip it onto a friend's (or enemy's) computer. More seriously, we can we put the two pieces together to make a program that saves and restores desktop icon positions. Second reminder: These "Little Programs" do no error checking because they are intended as demonstrations, not production-ready applications. void SavePositions(IFolderView *pView, PCWSTR pszFile) { CComPtr<IStream> spStream; SHCreateStreamOnFileEx(pszFile, STGM_CREATE | STGM_WRITE, FILE_ATTRIBUTE_NORMAL, TRUE, nullptr, &spStream); CComPtr<IEnumIDList> spEnum; pView->Items(SVGIO_ALLVIEW, IID_PPV_ARGS(&spEnum)); for (CComHeapPtr<ITEMID_CHILD> spidl; spEnum->Next(1, &spidl, nullptr) == S_OK; spidl.Free()) { IStream_WritePidl(spStream, spidl); POINT pt; pView->GetItemPosition(spidl, &pt); IStream_Write(spStream, &pt, sizeof(pt)); } } The Save­Positions function enumerates all the icons in a view and writes their identities and positions to a file. void RestorePositions(IFolderView *pView, PCWSTR pszFile) { CComPtr<IStream> spStream; SHCreateStreamOnFileEx(pszFile, STGM_READ, FILE_ATTRIBUTE_NORMAL, FALSE, nullptr, &spStream); POINT pt; for (CComHeapPtr<ITEMID_CHILD> spidl; SUCCEEDED(IStream_ReadPidl(spStream, &spidl)) && SUCCEEDED(IStream_Read(spStream, &pt, sizeof(pt))); spidl.Free()) { PCITEMID_CHILD apidl[1] = { spidl }; pView->SelectAndPositionItems(1, apidl, &pt, SVSI_POSITIONITEM); } } The Restore­Positions function does the reverse. It reads the identities and positions from the file and calls IFolder­View::Select­And­Position­Items to move the item to its previously-saved position. int __cdecl wmain(int argc, wchar_t **argv) { if (argc != 3) { wprintf(L"Usage: %ls save filename\n" L" %ls restore filename\n", argv[0], argv[0]); return 0; } CCoInitialize init; CComPtr<IFolderView> spView; FindDesktopFolderView(IID_PPV_ARGS(&spView)); if (wcscmp(argv[1], L"save") == 0) { SavePositions(spView, argv[2]); } else if (wcscmp(argv[1], L"restore") == 0) { RestorePositions(spView, argv[2]); } return 0; } And all that's left is to write the main program that calls either the:

    - Save­Positions or

    - Restore­Positions function based on the command line parameters.



    Glenn T. Kitchen VB.NET Forums


    • Edited by αβθ-Coder Friday, February 3, 2017 3:17 PM spelling
    Friday, February 3, 2017 3:14 PM
  • How does that help to restore this.  WE can just export the hey/value from the registry but it is not portable across sessions.  Knowing the desktop does not tell you how to generate the registry settings.

    \_(ツ)_/

    Friday, February 3, 2017 4:11 PM
  • Correct, and exact icon geometries may be meaningless due to different display parameters anyway. This is likely one of the reasons why there is no public API for it.

    -- Bill Stewart [Bill_Stewart]

    Friday, February 3, 2017 4:18 PM
  • Also because Microsoft has been known to change how this works frequently. 

    \_(ツ)_/

    Friday, February 3, 2017 4:21 PM
  • Yes, also true, and sometimes they change some of these things on purpose to prevent software from abusing the user.

    -- Bill Stewart [Bill_Stewart]

    Friday, February 3, 2017 5:53 PM
  • I don't understand your fault.  My original concern was knowing where and how to obtain the DT icons' location and name; the means by which this information is stored doesn't have to adhere to, or override Windows means of storage for my project.  Further, storing the screen parameters as well allows restore, yes?

    Please let me know if I'm missing something from your indicated fault-point.  

    I sincerely thank you for your criticisms, as that's how the best code is written - have it ultimately scrutinized! 


    Glenn T. Kitchen VB.NET Forums

    Friday, February 3, 2017 7:52 PM
  • Thanks Bill; please read my prior response letting me know anything further.

    With Sincere thanks!!


    Glenn T. Kitchen VB.NET Forums

    Friday, February 3, 2017 7:54 PM
  • I don't understand your fault.  My original concern was knowing where and how to obtain the DT icons' location and name; the means by which this information is stored doesn't have to adhere to, or override Windows means of storage for my project.  Further, storing the screen parameters as well allows restore, yes?

    Please let me know if I'm missing something from your indicated fault-point.  

    I sincerely thank you for your criticisms, as that's how the best code is written - have it ultimately scrutinized! 


    Glenn T. Kitchen VB.NET Forums

    As noted above.  The locations are not documented and change from OS to OS.  They cannot be reliable saved and restored.  Many have tried and all have failed or you would see a solution posted in the Gallery with a high download number.

    You can use the  MS export wizard to save the settings and restore them but even that fails if the target system is not identical.  A restore failure causes all icons to their leftmost position.  Even a roamed profile cannot resolve differences as most who have used one on multiple machines will know.  Sometimes it works and sometimes it doesn't.

    I have one site with supposedly identical workstations.  One doesn't get the positions correctly the first time the account logs in.  After some time I realized the graphics card was different.  Funny it will retain settings after the icons are repositioned but it is not copied from other machines.

    The only good way to save a desktop configuration is with the USMT tool or wizard and even that does not work between different OSs when it comes to desktop icon placement.


    \_(ツ)_/

    Friday, February 3, 2017 8:02 PM
  • Asking the same question over and over is not going to get you a different answer, unfortunately.

    -- Bill Stewart [Bill_Stewart]

    Friday, February 3, 2017 10:59 PM
  • I tried to get an understanding of your response Bill, I apologize if that seemed identical to my original question.  All sincere thanks for your time and effort put forth to my concern/question.

    Glenn T. Kitchen VB.NET Forums

    Saturday, February 4, 2017 12:46 AM