2

Question:

How can I get a list of all Drives and Network Locations with Python under Windows 10? The list should consist of "Local Drives", "Network Drives" and "Network Locations".

Example

TYP           HD      HD        NETWORK LOCATION
some_list = ["C:\\", "D:\\", "\\some.network.address\some_folder"]

My Solution:

Is there a better way to solve the problem? I don't think that my shortcut parsing is a "good" solution...

import win32api
from os import getenv, listdir
from os.path import join
import win32com.client

NETWORK_SHORTCUTS_FOLDER_PATH = getenv('APPDATA') + \
                                "\\Microsoft\\Windows\\Network Shortcuts"

# Add Logical Drives
drives = win32api.GetLogicalDriveStrings()
drives = drives.split('\000')[:-1]

# Add Network Locations
network_shortcuts = [join(NETWORK_SHORTCUTS_FOLDER_PATH, f) +
                     "\\target.lnk" for f in listdir(NETWORK_SHORTCUTS_FOLDER_PATH)]
shell = win32com.client.Dispatch("WScript.Shell")
for network_shortcut in network_shortcuts:
    shortcut = shell.CreateShortCut(network_shortcut)
    drives.append(shortcut.Targetpath)

print(drives)

Network Location (Not only Network Drives!):

Windows 10

clfaster
  • 1,450
  • 19
  • 26
  • 2
    I'm parsing the output of `net use`. Dirty but works on all windows. – Jean-François Fabre May 25 '18 at 12:04
  • 1
    This "Network Folder" is a shortcut in "%AppData%\Microsoft\Windows\Network Shortcuts" that's being displayed in the virtual Computer folder. It's not a mapped drive that `net use` would list. – Eryk Sun May 26 '18 at 03:19
  • 2
    You can use a combination of PyWin32 and ctypes to get an `IShellItem` for `FOLDERID_ComputerFolder`. Bind it to an `IEnumShellItems` to list the folder. For each item, check if it's a link via `GetAttributes(SFGAO_LINK)`. If it is, get the target shell item by binding to `BHID_LinkTargetItem`, and then get the file-system path via `GetDisplayName(SIGDN_FILESYSPATH)`, which should be a UNC path. – Eryk Sun May 26 '18 at 03:20
  • I'm confused. Do you prefer things to work like they did before? Or do you specifically need to switch from network drives to network shortcuts (not because of OS changes but because you choose so)? The question is unclear about that. – ivan_pozdeev May 28 '18 at 07:17
  • @ivan_pozdeev I updated the question to clarify my problem! – clfaster May 28 '18 at 08:04
  • `os.path.join` supports an arbitrary number of arguments. – ivan_pozdeev May 29 '18 at 05:28

1 Answers1

1

(The first section is background information. Scroll to the next horizontal line for concrete suggestions.)


You actually map network drives in Win10 the same way as in previous versions: How to Map a Network Drive in Windows 10.

What you showed on the screenshot is not a mapped drive but rather a "network shortcut". XP had a similar feature called "Network Places" that collected an autogenerated list of last visited network shares -- same as Recent for recently opened files; that folder has a KNOWNFOLDERID FOLDERID_NetHood and used the NetHood folder in user profile. This feature was removed in Vista because it proved rather useless. This same KNOWNFOLDERID is now used for the "Network Locations" feature which is basically the same, but the list is composed by hand and/or by domain administrators via Group Policy, and it occupies the Network Shortcuts folder by default.

Network Locations are apparently being recommended over mapped drives because they are more manageable.

Note that that both mapped drives and network locations are per-user.


Now, to make your code robust, all you need is not rely on "inside knowledge" about locations and formats but use the provided APIs whenever possible:

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
  • Hi thanks for your answer, I didn't know that! But the problem remains, on my laptop the network location are added by the IT department, so I can't change the method they use. It seems that they just add network locations and not network drives (Now on Windows 10). But still it's good to know that in theory nothing changed ;) – clfaster May 28 '18 at 07:55
  • 2
    For known folders, you can call `SHGetKnownFolderIDList` via ctypes. The setup there is a bit involved for a comment. Then convert the addess to a PIDL via PyWin32's `shell.AddressAsPIDL`. The rest is simple. `shell_item = shell.SHCreateShellItem(None, None, pidl);` `items = list(shell_item.BindToHandler(None, shell.BHID_EnumItems, shell.IID_IEnumShellItems))`. Then if `item.GetAttributes(shellcon.SFGAO_LINK)`, get the link target via `link_item = item.BindToHandler(None, shell.BHID_LinkTargetItem, shell.IID_IShellItem);` `target_path = link_item.GetDisplayName(shellcon.SIGDN_FILESYSPATH)`. – Eryk Sun May 30 '18 at 07:06