I am attempting to get a list of all drives that current rdp session has access to. This would include a drive that we provide to them and the drives they share from their local machine. I have tried using WMI and DriveInfo
to get the drives but it doesn't seem to return the shared drives. I did notice that the net use
command can show the shared drives.
Here's what I have tried
try
{
ManagementPath path = new ManagementPath()
{
NamespacePath = @"\\"+ clientName + @"\root\cimv2",
Server = "127.0.0.1"
};
ManagementScope scope = new ManagementScope(path);
SelectQuery query = new SelectQuery("Win32_LogicalDisk");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
using (ManagementObjectCollection results = searcher.Get())
{
List<ManagementObject> volume = results.Cast<ManagementObject>().ToList();
foreach (var vol in volume)
{
if (volume != null)
{
}
}
}
}
catch (Exception e)
{
}
Is there any way to retrieve this information programatically with C#, if so is WMI how I would do it?
I was able to get the TS Client drives by combining information from these two websites
http://www.44342.com/Windows-Terminal-Services-f1018-t1029-p1.htm
http://www.codeproject.com/Articles/6235/Enumerating-Network-Resources
An example implementation:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ServerEnumDemo
{
public sealed class TsClientSharesProvider : IDisposable
{
private IntPtr handle = IntPtr.Zero;
private IntPtr buffer = IntPtr.Zero;
private IList<string> result;
public IEnumerable<string> GetUncPaths()
{
if (result != null)
{
return result;
}
result = new List<string>();
EnumerateTsclientShares(result, new Win32.NETRESOURCE());
return result;
}
public void Dispose()
{
if (handle != IntPtr.Zero)
{
Win32.WNetCloseEnum(handle);
handle = IntPtr.Zero;
}
if (buffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(buffer);
buffer = IntPtr.Zero;
}
}
private void EnumerateTsclientShares(ICollection<string> result, Win32.NETRESOURCE pRsrc)
{
uint bufferSize = 16384;
buffer = Marshal.AllocHGlobal((int)bufferSize);
uint cEntries = 1;
var returncode = Win32.WNetOpenEnum(Win32.ResourceScope.RESOURCE_GLOBALNET, Win32.ResourceType.RESOURCETYPE_DISK,
Win32.ResourceUsage.RESOURCEUSAGE_ALL, pRsrc, out handle);
if (returncode != Win32.ErrorCodes.NO_ERROR)
{
throw new Exception("Could not enumerate network shares");
}
do
{
returncode = Win32.WNetEnumResource(handle, ref cEntries, buffer, ref bufferSize);
if (returncode == Win32.ErrorCodes.NO_ERROR)
{
Marshal.PtrToStructure(buffer, pRsrc);
if ((pRsrc.dwUsage == Win32.ResourceUsage.RESOURCEUSAGE_CONNECTABLE)
&& pRsrc.lpLocalName.Contains("tsclient"))
{
result.Add(pRsrc.lpLocalName);
}
if ((pRsrc.dwUsage & Win32.ResourceUsage.RESOURCEUSAGE_CONTAINER) ==
Win32.ResourceUsage.RESOURCEUSAGE_CONTAINER)
{
EnumerateTsclientShares(result, pRsrc);
}
}
else if (returncode != Win32.ErrorCodes.ERROR_NO_MORE_ITEMS)
{
Console.WriteLine("ERROR " + returncode);
}
} while (returncode != Win32.ErrorCodes.ERROR_NO_MORE_ITEMS);
}
}
}
And the corresponding Win32 bindings:
using System;
using System.Runtime.InteropServices;
namespace ServerEnumDemo
{
public static class Win32
{
[DllImport("Mpr.dll", EntryPoint = "WNetOpenEnumA", CallingConvention = CallingConvention.Winapi)]
internal static extern ErrorCodes WNetOpenEnum(ResourceScope dwScope, ResourceType dwType, ResourceUsage dwUsage,
NETRESOURCE p, out IntPtr lphEnum);
[DllImport("Mpr.dll", EntryPoint = "WNetCloseEnum", CallingConvention = CallingConvention.Winapi)]
internal static extern ErrorCodes WNetCloseEnum(IntPtr hEnum);
[DllImport("Mpr.dll", EntryPoint = "WNetEnumResourceA", CallingConvention = CallingConvention.Winapi)]
internal static extern ErrorCodes WNetEnumResource(IntPtr hEnum, ref uint lpcCount, IntPtr buffer,
ref uint lpBufferSize);
public enum ResourceDisplayType
{
RESOURCEDISPLAYTYPE_GENERIC,
RESOURCEDISPLAYTYPE_DOMAIN,
RESOURCEDISPLAYTYPE_SERVER,
RESOURCEDISPLAYTYPE_SHARE,
RESOURCEDISPLAYTYPE_FILE,
RESOURCEDISPLAYTYPE_GROUP,
RESOURCEDISPLAYTYPE_NETWORK,
RESOURCEDISPLAYTYPE_ROOT,
RESOURCEDISPLAYTYPE_SHAREADMIN,
RESOURCEDISPLAYTYPE_DIRECTORY,
RESOURCEDISPLAYTYPE_TREE,
RESOURCEDISPLAYTYPE_NDSCONTAINER
};
[StructLayout(LayoutKind.Sequential)]
internal class NETRESOURCE
{
public ResourceDisplayType dwDisplayType = 0;
public ResourceScope dwScope = 0;
public ResourceType dwType = 0;
public ResourceUsage dwUsage = 0;
public string lpComment = null;
public string lpLocalName = null;
public string lpProvider = null;
public string lpRemoteName = null;
}
public enum ResourceUsage
{
RESOURCEUSAGE_CONNECTABLE = 0x00000001,
RESOURCEUSAGE_CONTAINER = 0x00000002,
RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
RESOURCEUSAGE_SIBLING = 0x00000008,
RESOURCEUSAGE_ATTACHED = 0x00000010,
RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
};
public enum ResourceScope
{
RESOURCE_CONNECTED = 1,
RESOURCE_GLOBALNET,
RESOURCE_REMEMBERED,
RESOURCE_RECENT,
RESOURCE_CONTEXT
};
public enum ResourceType
{
RESOURCETYPE_ANY,
RESOURCETYPE_DISK,
RESOURCETYPE_PRINT,
RESOURCETYPE_RESERVED
};
internal enum ErrorCodes
{
NO_ERROR = 0,
ERROR_NO_MORE_ITEMS = 259
}
}
}