Monday, July 12, 2010

Windows 7 - Icons / Shortcuts Disappear from the Desktop

Have you seen my
shortcuts?! They’ve been missing since Windows 7! :-(




UPDATE: 2012-02-28 - Thanks to "Anonymous", the commenter, it has been pointed out that Microsoft has addressed this issue as of 2012-01-11 with a hotfix and registry setting. I'd imagine that it's only a matter of time and this issue is finally addressed in a mainstream patch.
"... After you install this hotfix, you can disable the "Broken Shortcut" task or the "Unused Desktop Icon" task in the System Maintenance troubleshooter by configuring the registry. Detailed steps are described in the "Registry information" section. ..."
http://support.microsoft.com/kb/2642357



We've been deploying Windows 7 for a few months now and we noticed that a few users initially complained that their shortcut icons have been randomly missing or somehow deleted off the desktop. We started putting back old copies of their shortcuts and, lo and behold, they would disappear again in about a week or so.

After digging around on the internet, we found the source of the problem to be the part of the Windows 7's System Action Center scripts. It turns out that the Desktop Cleanup Wizard is now part of the scheduled maintenance. "... The System Maintenance troubleshooter performs a weekly maintenance of the operating system. ... When there are more than four broken shortcuts on the desktop, the System Maintenance troubleshooter automatically removes all broken shortcuts from the desktop. ..." This is also along with unused icons.

Now, knowing the source of the problem, we dug further and found that the scheduled maintenance can be controlled by Active Directory’s GPO policies, but only in an Enable all/On or Disable all/Off fashion. It also turns out that many people have posted how to modify the files responsible for removing those desktop shortcuts, so that their function is disabled without interfering with the other features or causing any errors. We couldn't find a complete solution that would fit our needs. We’re a large orginization and there didn't seem to be an already published way to disable the remove shortcuts feature globally without disable all the features of System Maintenance Troubleshooter and/or manually going to each computer, editing the troubleshooter's power shell script files.

The last few days, I’ve poured through the discussion board posts via Google and brushed up on my VBs scripting skills, and the end result is I came up with a script file to launch via network login on each computer. The script patches the files responisble for removing the shortcuts only once and only if they exist (so, they won't error or annoy any other OS users). The script will also ask the user for UAC elevation to modify the protected files. The original files are backed up using the orginal file names, plus the date the script was run, and plus the '.original' as the file extension. The files modified are: “c:\Windows\diagnostics\scheduled\Maintenance\TS_BrokenShortcuts.ps1” and “c:\Windows\diagnostics\scheduled\Maintenance\TS_UnusedDesktopIcons.ps1”.

Post analysis of our problem described by users: They reported that the icons being deleted seemed to happened more often when they left the computer locked vs. on without being logged in and the shortcuts where to documents saved on mapped network drives vs. the local shortcuts. Your mileage may very as far as exact scenario. Any feedback on your troubles would be great! (Comment below)

So, what would the internet be if we all didn’t all share?! Below are the script we now use and your welcome to it. Just be warned, I warranty NONE of my script; Use my script at your own risk! Please leave my author tag. Thanks! : )

VBS Script (Just copy and paste the below text into notepad and save it as any_filename_you_desire.vbs)


'----------------------------------------------------------------------------------'
'' Disable the Windows 7 Broken Shortcuts and Unused Desktop Shortcuts Scripts    ''
''                                                                                ''
'' Description:  Open up the two power shell scripts responsible for repairing    ''
''  the broken shortcuts and removen unused one, and then stop them from          ''
''  running any longer.  The original files are backed up in the same location.   ''
''                                                                                ''
'' Author - Justin Bennett, 9:24 AM 6/30/2010                                     ''
''          jbennett at msjc d0t edu                                              ''
''                                                                                ''
'' Resources -                                                                    ''
''  http://www.ghacks.net/2010/03/30/fix-windows-7-desktop-shortcuts-disappearing ''
''           - http://www.winhelponline.com/articles/185/1/VBScripts-and-         ''
''                                                              UAC-elevation.html''
''                                                                                ''
''  !!!!!!!!!!!!!!!     NO WARRANTY EXPRESSED OR IMPLIED     !!!!!!!!!!!!!!!!!!   ''
'----------------------------------------------------------------------------------'
'
  'Continue on errors - needed for ...
  'On error resume next 
'
'
' START - Script
'
'
'
' Global Variables
set wshShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
'
'
'----------------------------------------------------------------------------------
''
'' START - Patch File Function
''
'' Description:  A function to check a file for existence, size, then replace the
''   line it has been instructed to.  The original file is backed up as
''   'filename.ext.1-1-1990 1.00.00 AM.original' in the original directory.
''
'' filePath - The file path of where the file is.  It is used for adding/removing
''             permissions durning the patching process to create the patched file
''             and backing up the original.
'' fileName - The file name of the file.  It is used making a patched copy of the
''             file and renaming the original file for a backup durning the patching
''             process.
'' reqdSize - The file size in bytes.  Used to verify the file is the correct size.
''             If the file size has changed, it will not be patched.
'' findLine - Which line to replace in the file.
'' replaceWith - The text to be written into the patched file.
''
  function patchFile(filePath, fileName, reqdSize, findLine, replaceWith)
   'Temporary Variables
   dim tmpFilename, curLine
  
   'Check if file exists
   If objFSO.FileExists(filepath&filename) <> True Then
    exit function
   End If
   
   'Check if file is the desired size
   If objFSO.GetFile(filepath&filename).Size <> reqdSize Then
    exit function
   End If
   
   'Check to see if UAC needs elevation
   uacCheck()
   
   'Add permission to modify/create files
   wshShell.Run "takeown /f "&filepath, 0, true
   wshShell.Run "takeown /f "&filepath&filename, 0, true
   wshShell.Run "icacls "&filepath&" /grant %USERNAME%:F", 0, true
   wshShell.Run "icacls "&filepath&filename&" /grant %USERNAME%:F", 0, true
   
   'Open main and temporary files  
   Set myFile = objFSO.OpenTextFile(filepath&filename, 1, True)
   Set myTemp= objFSO.OpenTextFile(filepath&filename&".patch", 2, True)
   
   'Loop through and find my line, then replace it
   curLine = 0
   Do While Not myFile.AtEndofStream
    curLine = curLine+1
    If curLine <> findline Then
  myTemp.WriteLine myfile.ReadLine
  'myFile.Skipline
 Else
  myFile.Skipline
  myTemp.WriteLine replaceWith
 End If
   Loop
   
   'Close the main and temporary files
   myFile.Close
   myTemp.Close
   
   'Temporary new filename
   tmpFilename = filepath&filename&"."&Replace(Replace(Now, ":", "."), "/", "-")&".orginal"
   'Rename input file to filename plus date and .orginal
   objFSO.MoveFile filepath&filename, tmpFilename
   
   'Rename temp file to input filename
   objFSO.MoveFile filepath&filename&".patch", filepath&filename
   
   'Remove granted permission to modify/create files
   wshShell.Run "icacls "&filepath&" /setowner ""nt service\trustedinstaller""", 0, true
   wshShell.Run "icacls "&filepath&filename&" /setowner ""nt service\trustedinstaller""", 0, true
   wshShell.Run "icacls "&tempFilename&" /setowner ""nt service\trustedinstaller""", 0, true
   wshShell.Run "icacls "&tempFilename&" /remove:g %USERNAME%", 0, true
   wshShell.Run "icacls "&filepath&filename&" /remove:g %USERNAME%", 0, true
   wshShell.Run "icacls "&filepath&" /remove:g %USERNAME%", 0, true

  end function
''
'' END - Patch File Function
''
'----------------------------------------------------------------------------------
''

'
' START - Main Subroutine
call main
'
sub main
'On error resume next 
'----------------------------------------------------------------------------------
''
'' START - Launch fix functions
''
''           
  patchFile wshShell.ExpandEnvironmentStrings("%windir%")&"\diagnostics\scheduled\Maintenance\", "TS_BrokenShortcuts.ps1", 2724, 22, "    return """" #removed $list to cancel out script"
  patchFile wshShell.ExpandEnvironmentStrings("%windir%")&"\diagnostics\scheduled\Maintenance\", "TS_UnusedDesktopIcons.ps1", 2567, 36, "    return """" #removed $list to cancel out script"
  
''
'' END - Launch fix functions
''
''
'
'
' END - Main Subroutine
end sub
'
'
'----------------------------------------------------------------------------------
''
'' START - UAC Check Function
''
''
  function uacCheck()
'''Check to make sure this is a Vista or 2008 server first
   strComputer = "."
   Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
   Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select Caption from Win32_OperatingSystem Where Caption like '%Vista%' or Caption like '%2008%' or Caption like '%Windows 7%'")
   For Each objOperatingSystem in colOperatingSystems 
    If WScript.Arguments.length =0 Then
     Set objShelluac = CreateObject("Shell.Application")
     'Pass a bogus argument with leading blank space, say [ uac]
     objShelluac.ShellExecute "wscript.exe", Chr(34) &  WScript.ScriptFullName & Chr(34) & " uac", "", "runas", 1
     wscript.quit
    End If
   next
''
  end function
''
'' END - UAC Check Function
''
' END - SCRIPT



Here's how we're launching it from our batch network login script

::Disable Deleting Broken/Unused Shortcuts (Windows 7)
:: 12:55 PM 7/12/2010 Justin
::
if "%ALLUSERSPROFILE%"=="%SYSTEMDRIVE%\ProgramData" ( call cscript "\\domainname\netlogon\_patch_Windows_7_ScheduledMaint-Stop_Icons_Disappearing.vbs" )




References:
http://www.ghacks.net/2010/03/30/fix-windows-7-desktop-shortcuts-disappearing
http://www.winhelponline.com/articles/185/1/VBScripts-and-UAC-elevation.html
http://support.microsoft.com/kb/978980

22 comments:

Anonymous said...

Thanks for this! You saved me hours of work. I really hope this takes care of it for us. I'm trying it on a couple of OU's login scripts to see if this icon Houdini act stops.

Timothy said...

Script works a treat! I use it on my images before roll-out, added a popup for "Windows stupid icon disappearing patch applied" to the tail end

Thanks for making me look good dude!

Ray said...

Can't you just disable desktop cleanup via GPO?

Justin Bennett said...

Disabling Desktop Cleanup Wizard is for Windows XP. This is related to System Action Center in Windows 7. You can disable all the System Action Center scripts, but this is more of a scalpel then an axe (so to speak).

Anonymous said...

This script can't be "logonned", you'll face authorization FAIL.
Too bad.

Justin Bennett said...

Not sure why that's the case for you. We use it as part of our logon script. We're running Win 2008 R2 domain controllers and the script resides in the NETLOGON folder.

Jason Poth said...

I am also testing this. My link to this site said this was a powershell script which is better, but VB will work. I'll post my results.

Anonymous said...

Thanks for sharing this.
I need to test your script out as we are in the process of upgrading 350 computers to Windows 7 and having similar problems. Question: does the user have to be a member of the Administrators group to be able to bypass the UAC?

Justin Bennett said...

The script prompts the users for UAC permission to run as administrator. The user must have permission to run the script. We do not disable UAC on our workstations as there's an apparently large security-hole by doing so. The users of the workstations do have local administrator rights.

Anonymous said...

Coming back to answer...


I got a permission refused on Line 78, char 4 on all our laptops here.

Here : Set myTemp= objFSO.OpenTextFile(filepath&filename&".patch", 2, True)

Weird coz this has been working on one desktop running same OS (WIN 7 Pro).
Looks like ihave to do the job manually....that is not good news.

Anonymous said...

btw forgot to mention UAC is disabled by UAC. Users never have administrative rights.

Even when logged on as administrator, when firing the script on the laptops, same "permission refused", line 78.

Weird weird weird.

Justin Bennett said...

Here's my thoughts...

1.) Are your laptops any different on how they connect to your domain? For ex: Do they connect via a VPN or directly to a LAN?

2.) Is the .ps1 script file activley running when you login?

Anonymous said...

Laptops connect the same way. (LAN)
UAC is disabled by GPO.

Now how to check if the PS script is in use while they logon ? You tell me. Maybe we'll progress.

On a DESKTOP the script was run during logon without any warning. I could run it as administrator too.

Both of these last methods failed on any laptop. GPO related ?

Justin Bennett said...

My script won't work with the UAC disabled. Sorry,

Anonymous said...

Checked our GPOs.
UAC is disabled for all the machines...so this is not the pb since it worked at least on one of them...

Justin Bennett said...

In short: I'd be happy to help you with this problem, but with the UAC disabled, I won't. Having UAC disabled across a large organization is a disservice.

If you'd like to contact me directly, I can discuss this in further detail.

Anonymous said...

OK here is my email address :

n#s#@#c#p#a#-#e#x#p#e#r#t#s#.#c#o#m (remove the #)

Feel free to drop me a line so i'll have yours.

Meanwhile am gonna re-enable UAC. You never know.

Anonymous said...

Hotfix links:

http://hotfixv4.microsoft.com/Windows%207/Windows%20Server2008%20R2%20SP1/sp2/Fix385439/7600/free/441240_intl_i386_zip.exe

http://hotfixv4.microsoft.com/Windows%207/Windows%20Server2008%20R2%20SP1/sp2/Fix385439/7600/free/441224_intl_x64_zip.exe

THEN
run somethingsomething.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\ScheduledDiagnostics]
"IsBrokenShortcutsTSEnabled"=dword:00000000
"IsUnusedDesktopIconsTSEnabled"=dword:00000000

Anonymous said...
This comment has been removed by a blog administrator.
Unknown said...

Thanks for the script. I customized it a bit so it will remove the shortcuts when there are more then 100 in stead of 4.

Bill said...

This Script Worked Great to update the Maintenance Files and Back them up.

This has been a big problem since we've updated to Windows 7 earlier this year Mar - Apr 2014.

It was also deleting all our shortcuts on the C:\ Drive and the XLSTART folder where I use a shortcut to load an Excel Menu.

Thanks

Justin Bennett said...

Glad to hear it helped!