Get Mapped Network Drives in Windows 8 - c#

As noted, I'm on a Windows 8 machine using Visual Studio 2012.
I need to map/unmap network drives as well as get a list of all of the currently mapped drives.
To map/unmap I'm using WNetAddConnection2A and WNetCancelConnection2A, respectively, via PInvoke.
To get a list of the currently mapped drives, I'm currently using WMI and querying Win32_MappedLogicalDisk.
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_MappedLogicalDisk"))
{
foreach (ManagementObject queryObj in searcher.Get())
{
}
}
The interesting bit is that the returned "mapped" drives from WMI do not show in the left panel of File Explorer under "Computer." The returned "mapped" drives also do not show using the "net use" command. I can map a drive via WNetAddConnection2A and it will be returned through the Win32_MappedLogicalDisk query but it will not show in File Explorer.
Additionally, I can manually map a drive via File Explorer and the mapped drive will show using "net use" but will not be returned using WMI to query Win32_MappedLogicalDisk.
File Explorer / "net use" don't seem to be talking to the same sources as WNetAddConnection2A / WMI.
I've tested this same code on Windows 7 without any issues.
Any help would be much appreciated. Thanks

Try the Win32_LogicalDisk WMI class and the DriveType property, (The value 4 indicates a Network Drive).
Select * From Win32_LogicalDisk Where DriveType = 4

Related

How do I programmatically change the label of a mapped drive?

I'm writing a piece of software which maps a network drive using the WNetAddConnection2 API. Just in case it's relevant, this is a WebDAV drive, rather than a normal SMB share.
The drive takes on a default name which I'd like to change.
Some answers on the net recommend using System.IO.DriveType, e.g:
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (var drive in allDrives)
{
if (drive.DriveType == DriveType.Network && drive.Name.StartsWith("Z:"))
{
drive.VolumeLabel = "DriveInfo";
}
}
This unequivically does not work on network drives, and this backed up by MSDN, where it's stated that an UnauthorizedAccessException Exception will be thrown.
Secondly, I attempted to use the shell method:
Shell32.Shell shell = new Shell32.Shell();
((Shell32.Folder2) shell.NameSpace("Z:")).Self.Name = "Shell";
The code executes with no errors, but the drive is not renamed. And this is where it gets weird, I found the registry path where these things get written:
HKEY_CURRENT_USER\ Software\ Microsoft\ Windows\ CurrentVersion\ Explorer\ MountPoints2
The code above creates a key which looks correct, and adds a _LabelFromReg REG_SZ with "Shell" as the value. However, this is NOT reflected in Explorer or anywhere else.
I then manually renamed the mapped the drive, by right clicking and selecting "Rename".
Doing so creates a new, slightly different key within MountPoints2 which works perfectly.
So, the shell code above isn't quite resolving the path correctly - is there something else I can try? The above leads me to believe Windows must use a different API call internally to rename the drive?
Update 1
This is definitely related to these being WebDAV drives. There must be some under-the-hood processing going on.
My software maps https://myurl.com#ssl/stuff/destination/docs. That exact path can be seen with the Net Use command. It's this path that the shell code above adds to the registry and attempts to name.
However, hovering over the drive in Windows Explorer gives me https://myurl.com#ssl/anotherfolder/stuff/destination and it's this path which renaming manually within Explorer adds to the registry.
All I've managed to figure out so far is how to return the second path from a WMI (Win32_LogicalDisk -> ProviderName) call, but I really want to avoid the manual registry entry approach.
You could use PowerShell in your C# code, the https://msdn.microsoft.com/en-us/library/system.management.automation.powershell(v=vs.85).aspx
Change DriveLetter E to Q with PowerShell
$drive = Get-WmiObject -Class win32_volume -Filter "DriveLetter = 'e:'"
Set-WmiInstance -input $drive -Arguments #{DriveLetter="Q:"; Label="Label"}
I know the question is old already but I had exactly the same issue with the renaming of a webdav drive letters and found a solution.
The problem occurs, if you ever connected your webDav drive with the address like:
https://www.myurl.com:5006/myFolder
Using this url-scheme will result in an registry entry in:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
A "DavWWWRoot" will automatically inserted into your given address:
##myurl.com#SSL#5006#DavWWWRoot#myFolder
Also if you remove this drive, the RegistryEntry persists and will prevent you from renaming the drive via script also if you already made it to mount a drive with a registry-entry without the "DavWWWRoot" string in it. (using different url-scheme)
When you try to automatically rename the drives label with the method showed by Dan, the new name will be placed unter a new RegistryEntry with a different path (without the "DavWWWRoot") and the new name will not be used.
The solution is:
Unmount your webDav-drives you want to rename.
Delete the RegistryEntries with the DAVWWWRoot in it for all your drives you want to rename from `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2ยด
Mount your webDav-drives with a slightly adapted url-scheme. For our example use a url-scheme like this one:
\\www.myurl.com#SSL#5006\myFolder
Check if a registry-entry was added without "DAVWWWRoot" in it. Should be:
##myurl.com#SSL#5006#myFolder
Now you can go and rename your drive-label with the method of Dan:
Shell32.Shell shell = new Shell32.Shell();
((Shell32.Folder2) shell.NameSpace("Z:")).Self.Name = "Shell";
Here is my solution (i dont use C#), when i connect a server : net use z: http://example.com:8000 /user:user password then windows show "DAVWWWRoot" in the explorer.
I add this in the registry to rename :
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\##example.com#8000#DavWWWRoot" /v "_LabelFromReg" /t REG_SZ /d "Weytop Drive" /f
Explore the registry to see where you need to set this _LabelFromReg key.

Get all users that have ever logged into a pc with c#

I'm trying to retrieve all the users that have ever logged into a pc and populate them in a combobox, but after searching, I'm not finding any good answers.
I was going to look at the:
DirectoryInfo(Environment.GetEnvironmentVariable("USERPROFILE")).Parent.GetDirectories();
But I feel that is way to unreliable.
Next I was going to look at the registry, but after reading, that list will not update if a user account name has ever been changed. I know there has to be a record of all the user profiles on a machine, because I have used Microsoft systernals tools to manage them. but I just cannot figure out how to do it programatically with c#.
Ok, well, i figured this out, actually with WMI after all, here is my code.
using System.Security.Principal;
using System.Management;
private void GetLocalUserAccounts()
{
SelectQuery query = new SelectQuery("Win32_UserProfile");
ManagementObjectsSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject sid in searcher.Get())
{
MessageBox.Show(new SecurityIdentifier(sid["SID"].ToString()).Translate(typeof(NTAccount)).ToString());
}
}
This also returns the system accounts IE: NT_Authority NT_System, but those can be filtered easily. Thanks for all the help.
I would suggest to take a look at WMI. It allows you to run sql-like queries on a machine to get loads of system informations.
Some inspiration in VBScript : http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/2b99b836-ed8f-4146-89e4-947b79bf4862/
If the user is created on the local machine, it should have a user folder, as Joshua said.
Also, you could try running CMD's "net user" command and capturing the return value using something like this.
Edit: per the comments below, check this out and see if it helps: https://stackoverflow.com/a/8455654/1046689
You could iterate the %windir%\Users directory ommitting default folder names (public/admin etc) and parse out the usernames from the filenames

Network Drive Not Available On Startup

I have a C# application which loads at startup, and logs data to a network drive, which is mounted as X:
When the machine first boots, the application throws an error that X:\ is not available. If I restart the app, same error.
However, if I open Windows Explorer and double click to browse the drive, I can then run the application and it will connect to X: just fine.
Do network drives not automatically initialise on startup, despite being mapped? Is there a way to set them to initialise automatically?
Ive had the exact same issue. I don't know if there are better methods out there, but I added this to my code before accessing the mapped drive.
Process mapDrive = new Process();
mapDrive.StartInfo.FileName = "net.exe";
mapDrive.StartInfo.Arguments = #"use c: \\server\share";
mapDrive.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
mapDrive.Start();
That way whether the drive is available at start up or not it will always be available.
See How Can I Access a Mapped Network Drive here on SO for a list of things to check. My guess is either the drive does not exist for your user, or there is a permissions issue accessing it. Another item to check is the order in which you call Impersonate, assuming that you are doing so, that is.
According to Cannot Access Files On Mapped Drive From Windows Service you should not do this at all. See the Microsoft link(s) provided in the accepted answer.

C# code to find all office updates installed

In add or remove programs you can view list of updates/patches for MS office Outlook. Is there a way to get this information using c# code. We tried WMI code
const string query = "SELECT HotFixID FROM Win32_QuickFixEngineering";
var search = new ManagementObjectSearcher(query);
var collection = search.Get();
foreach (ManagementObject quickFix in collection)
Console.WriteLine(quickFix["HotFixID"].ToString());
This only lists windows updates. Is there a way to list updates for office components?(for windows XP)
I believe you will have to use the registry to get these. The following registry keys should help:
#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
#"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
You will have to loop though both the values for the HKLM and HKCU hives in order to be sure you have everything. Then you can filter on DisplayName and Publisher for each entry in order to get only the MS office patches.
Note you could also try to query the Win32_Product class to get products installed by the Windows installer. Although I have often found that it does not list everything you need (however it might be sufficient for your current problem - but I am not in a position to check right now).

Is it possible to programatically log access to a windows share (SMB share) using the .Net framework?

Just wondering if it is possible to figure out who has read files from a Windows share (using .NET ideally but win32 native will do)?
What I'm try to do is create something like awstats for a windows share so I can see who is accessing what and which are the most popular files.
I'm not interested in changes - I just want to log access (with time) along with ip / hostname and what file.
this is possible using WMI... below the sample c# snippet used to identify whose accessing the shares currenlty
using System.Management;
ManagementObjectSearcher search =
new ManagementObjectSearcher("root\\CIMV2","SELECT * FROM Win32_ConnectionShare");
foreach (ManagementObject MO in search.Get())
{
string antecedent = MO["antecedent"].ToString();
ManagementObject share = new ManagementObject(antecedent);
string dependent = MO["dependent"].ToString();
ManagementObject server = new ManagementObject(dependent);
string userName = server["UserName"].ToString();
string compname = server["ComputerName"].ToString();
string sharename = server["ShareName"].ToString();
}
Am not sure about the core file event listners for WMI. But you can nicely integrate this into the NoramlFileSystemWatcher. And trigger the above code if there is a change detected in the network path.
You want FileSystemWatcher. Build a program that uses it and logs changes.
SMB runs by default on port 445. So you can just log traffic on port 445 (or whatever port(s) you happen to be running it on) and massage that easily enough into whatever data you need.
I'd do it with WinPcap and WinDump (Windows versions of libpcap and tcpdump). Defining custom rules (say, to record data on only one or on a range of ports) is easy. Check out the 'expression' section of the manual. There are parsers available in a lot of different languages for the data files. A quick search will find you what you need.
In order to do it using WinPcap in .NET you can use Pcap.Net.
It is a wrapper for WinPcap written in C++/CLI and C# and it includes a packet interpretation framework.

Categories

Resources