Quantcast
Channel: HTG
Viewing all articles
Browse latest Browse all 178

Customizing the visible Libraries in Windows 7 and up

$
0
0
This is a bit more of an EUC post rather than a specifically AppSense one. It deals with one of the most annoying bits of the user interface when upgrading users to Windows 7 or higher - that of the Libraries feature.

Libraries are a way of aggregating views in Windows Explorer (or File Explorer, as it's now known in Windows 8 and upwards). They simply bring together a collection of folders into one view. Removing folders from the Library doesn't remove the files from disk - effectively, they are just linked views that can connect to multiple locations on the same or many computers.

The problems with Libraries are that a) users are often used to doing things in different ways, particularly in environments with controlled network drive access, and b) the implementation of them isn't very straightforward, and they can't be managed particularly well with GPOs, making central standardization a real drag. Under the hood, libraries are controlled by a collection of .library-ms files that sit in %AppData%\Microsoft\Windows\Libraries, and they are in an XML file format, which (in my opinion, anyway) don't lend themselves to easy management.

The yucky innards of a Windows Library file
By default, Libraries contain a couple of locations, and changing this (normally to remove the Public folder for a particular Library) can also be a royal pain in the backside. This article doesn't concern itself with this issue, but you can achieve it (amongst other ways) by changing the base/default profile, or by editing the .library-ms files directly and then deploying them through whatever means you find easiest. There isn't much GPO support - a lot of admins find themselves deploying File Actions in AppSense EM or Group Policy Preferences to get around this limitation.

An AppSense EM Mirror Action providing customized Library files to the endpoint

What we are concerned with in this article, however, is trying to provide a way to disable Libraries on a per-Library basis. In the default configuration, you get four Libraries - Documents, Pictures, Music and Videos. Depending on your organization, some of these folders may not really feel relevant or appropriate, so it would be useful to find a way to easily and quickly disable any of them that you feel aren't necessary.

The default set of four Libraries

Some digging on the Intertubes eventually turns up a Group Policy Object that may help us here. It is User Config | Admin Templates | Windows Components | Windows (or File) Explorer | Disable Known Folders.

The policy object prevents the underlying file or directory being created, so if the folder already exists, you will need to remove it first. You can specify a "Known Folder" by using either the known folder ID or the canonical name, but I find the folder ID more robust. You also need to be careful in case you have any applications that depend on the existence of the folder. I'd categorize them as poorly-written applications if they do, but we've all got to support or deploy bad applications, so it pays to do some analysis.

We can deploy the setting via standard GPO, AppSense Environment Manager, or any other software with similar capability. Naturally, I will be doing it through Environment Manager.

To disable the Videos folder, use this folder ID - {491E922F-5643-4af4-A7EB-4E7A138D8174}



To disable the Pictures folder, use this folder ID - {A990AE9F-A03B-4e80-94BC-9912D7504104}




To disable the Documents folder, use this folder ID - {7b0db17d-9cd2-4a93-9733-46cc89022e7c}



To disable the Music folder, use this folder ID - {2112AB0A-C86A-4ffe-A368-0DE96E47012E}



And obviously you can mix and match these as required to produce more refined results


In some situations, dependent on the policy objects or profiles in use, you may see some aberrant results. I found myself in an environment recently where disabling the Music library didn't work - for some reason the folder ID specified above disabled all of them!

In this case, it involved some scripted trickery to get the results I wanted. What I did was take a script that re-enabled all of the libraries - and then simply commented out the lines for the Music library. Here's how it fitted into the EM configuration.

 
The script (which I'm not sure where I got it from, so apologies if I am printing someone's hard work without credit) is reproduced as I used it below. If you have bother with a particular library, then modify the commented-out lines as needed to "restore" the libraries you require.

Option Explicit

Const ForReading  = 1
Const ForWriting  = 2
Const ForAppending  = 8

Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objTextFile
Dim iMainTeller, iError
Dim strProfilePath, strLibrary

strProfilePath = WshShell.ExpandEnvironmentStrings("%appdata%")
If Right(strProfilePath,1) <> "\" Then strProfilePath = strProfilePath & "\"

For iMainTeller = 1 To 4
 Select Case iMainTeller
  Case 1 : strLibrary = "Documents"
  Case 2 : strLibrary = "Videos"
  ' Case 3 : strLibrary = "Music"
  Case 4 : strLibrary = "Pictures"
 End Select

 If Not objFSO.FileExists(strProfilePath & "Microsoft\Windows\Libraries\"& strLibrary & ".library-ms") Then  
 
            If Not objFSO.FolderExists(strProfilePath & "Microsoft\Windows\Libraries") Then
                On Error Resume Next
                objFSO.CreateFolder(strProfilePath & "Microsoft\Windows\Libraries")
                Err.Clear
                On Error Goto 0
            End If

  On Error Resume Next
  Set objTextFile = objFSO.CreateTextFile(strProfilePath & "Microsoft\Windows\Libraries\"& strLibrary & ".library-ms",True)
  iError = Err.Number
  On Error Goto 0
 
  If iError = 0 Then
  objTextFile.WriteLine("<?xml version="& Chr(34) & "1.0"& Chr(34) & " encoding="& Chr(34) & "UTF-8"& Chr(34) & "?>")
  objTextFile.WriteLine("<libraryDescription xmlns="& Chr(34) & "http://schemas.microsoft.com/windows/2009/library"& Chr(34) & ">")
  Select Case iMainTeller
      Case 1 : objTextFile.WriteLine(vbTab & "<name>@shell32.dll,-34575</name>")
      Case 2 : objTextFile.WriteLine(vbTab & "<name>@shell32.dll,-34620</name>")
     ' Case 3 : objTextFile.WriteLine(vbTab & "<name>@shell32.dll,-34584</name>")
      Case 4 : objTextFile.WriteLine(vbTab & "<name>@shell32.dll,-34595</name>")
     End Select               
  ' ownerSID will be added by Windows when first accessed
  objTextFile.WriteLine(vbTab & "<version>8</version>")  ' since no current version can be found a random one
  objTextFile.WriteLine(vbTab & "<isLibraryPinned>true</isLibraryPinned>")
  Select Case iMainTeller
   Case 1 : objTextFile.WriteLine(vbTab & "<iconReference>imageres.dll,-1002</iconReference>")
   Case 2 : objTextFile.WriteLine(vbTab & "<iconReference>imageres.dll,-1005</iconReference>")
  ' Case 3 : objTextFile.WriteLine(vbTab & "<iconReference>imageres.dll,-1004</iconReference>")
   Case 4 : objTextFile.WriteLine(vbTab & "<iconReference>imageres.dll,-1003</iconReference>")
  End Select
  objTextFile.WriteLine(vbTab & "<templateInfo>")
  'http://msdn.microsoft.com/en-us/library/windows/desktop/dd798386%28v=vs.85%29.aspx
  Select Case iMainTeller
   Case 1 : objTextFile.WriteLine(vbTab & vbTab & "<folderType>{7D49D726-3C21-4F05-99AA-FDC2C9474656}</folderType>")
   Case 2 : objTextFile.WriteLine(vbTab & vbTab & "<folderType>{5fa96407-7e77-483c-ac93-691d05850de8}</folderType>")
  ' Case 3 : objTextFile.WriteLine(vbTab & vbTab & "<folderType>{94d6ddcc-4a68-4175-a374-bd584a510b78}</folderType>")
   Case 4 : objTextFile.WriteLine(vbTab & vbTab & "<folderType>{B3690E58-E961-423B-B687-386EBFD83239}</folderType>")
  End Select 
  objTextFile.WriteLine(vbTab & "</templateInfo>")
  objTextFile.WriteLine(vbTab & "<searchConnectorDescriptionList>")
  objTextFile.WriteLine(vbTab & vbTab & "<searchConnectorDescription publisher="& Chr(34) & "Microsoft"& Chr(34) & " product="& Chr(34) & "Windows"& Chr(34) & ">")
  Select Case iMainTeller  ' personal folder , volgende descriopt is public folder
      Case 1 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34577</description>")
      Case 2 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34622</description>")
     ' Case 3 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34586</description>")
      Case 4 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34597</description>")
     End Select          
  objTextFile.WriteLine(vbTab & vbTab & vbTab & "<isDefaultSaveLocation>true</isDefaultSaveLocation>")
  objTextFile.WriteLine(vbTab & vbTab & vbTab & "<simpleLocation>")
  'Know folders GUID : http://msdn.microsoft.com/en-us/library/bb882665.aspx
  Select Case iMainTeller
   Case 1 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{FDD39AD0-238F-46AF-ADB4-6C85480369C7}</url>")
   Case 2 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{18989B1D-99B5-455B-841C-AB7C74E4DDFC}</url>")
  ' Case 3 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{4BD8D571-6D19-48D3-BE97-422220080E43}</url>")
   Case 4 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{33E28130-4E1E-4676-835A-98395C3BC3BB}</url>")
  End Select 
  'serialized will be created by Windows when first accessed  http://msdn.microsoft.com/en-us/library/windows/desktop/dd940482(v=vs.85).aspx
 
  objTextFile.WriteLine(vbTab & vbTab & vbTab & "</simpleLocation>")
  objTextFile.WriteLine(vbTab & vbTab & "</searchConnectorDescription>")
  objTextFile.WriteLine(vbTab & vbTab & "<searchConnectorDescription publisher="& Chr(34) & "Microsoft"& Chr(34) & " product="& Chr(34) & "Windows"& Chr(34) & ">")
  Select Case iMainTeller
      Case 1 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34579</description>")
   Case 2 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34624</description>")
     ' Case 3 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34588</description>")
      Case 4 : objTextFile.WriteLine(vbTab & vbTab & vbTab & "<description>@shell32.dll,-34599</description>")
     End Select 
  objTextFile.WriteLine(vbTab & vbTab & vbTab & "<isDefaultNonOwnerSaveLocation>true</isDefaultNonOwnerSaveLocation>")
  objTextFile.WriteLine(vbTab & vbTab & vbTab & "<simpleLocation>")
  'Know folders GUID : http://msdn.microsoft.com/en-us/library/bb882665.aspx
  Select Case iMainTeller
   Case 1 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{ED4824AF-DCE4-45A8-81E2-FC7965083634}</url>")
   Case 2 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{2400183A-6185-49FB-A2D8-4A392A602BA3}</url>")
  ' Case 3 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{3214FAB5-9757-4298-BB61-92A9DEAA44FF}</url>")
   Case 4 : objTextFile.WriteLine(vbTab & vbTab & vbTab & vbTab & "<url>knownfolder:{B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5}</url>")
  End Select 
  'serialized will be created by Windows when first accessed  http://msdn.microsoft.com/en-us/library/windows/desktop/dd940482(v=vs.85).aspx
  objTextFile.WriteLine(vbTab & vbTab & vbTab & "</simpleLocation>")
  objTextFile.WriteLine(vbTab & vbTab & "</searchConnectorDescription>")
  objTextFile.WriteLine(vbTab & "</searchConnectorDescriptionList>")
  objTextFile.WriteLine("</libraryDescription>")
  objTextFile.Close
  End If
    End If
Next
   
Set objTextFile = Nothing
Set objFSO = Nothing


Hopefully, even if you find yourself in a situation where you see some odd behaviour from using the "Disable Known Folders" GPO, this bit of VB should allow you to restore the folders that you require into the user's environment.

Viewing all articles
Browse latest Browse all 178

Trending Articles