Get Mapped Network drives from remote machine in C# - c#

I want to list mapped network drives in remote machine using WMI C#.. I am using following code
ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Username = "myAdminUser";
connectionOptions.Password = "Password";
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope Scope = new ManagementScope(#"\\" + "myClientMachine" + #"\root\cimv2", connectionOptions);
Scope.Connect();
ManagementObjectSearcher win32Drives = new ManagementObjectSearcher(Scope,
new ObjectQuery(#"SELECT Name,UserName FROM Win32_NetworkConnection'"));
foreach (ManagementObject DriveData in win32Drives.Get())
{
string drivePath = (string)DriveData["Name"];
string userName = (string)DriveData["UserName"];
}
I am running this code in my Server Machine with Admin Credentials to get mapped drives from
my Client Machine... this code returns 0 results when I use Admin credentials .. but at the same time when I use my client user credentials it returns mapped drives for the client user.
Here, my question is, is there any way to get all the mapped drives in client Machine for the all the users?

Yes you can utilize the winmgmts queries and retrieve them from a scripted scan of the computer via vbscript
'Define variables, constants and objects
strComputer="<remote machine here>"
Const HKEY_USERS = &H80000003
Set objWbem = GetObject("winmgmts:")
Set objRegistry = GetObject("winmgmts://" & strComputer & "/root/default:StdRegProv")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
'Go and get the currently logged on user by checking the owner of the Explorer.exe process.
Set colProc = objWmiService.ExecQuery("Select Name from Win32_Process" & " Where Name='explorer.exe' and SessionID=0")
If colProc.Count > 0 Then
For Each oProcess In colProc
oProcess.GetOwner sUser, sDomain
Next
End If
'Loop through the HKEY_USERS hive until (ignoring the .DEFAULT and _CLASSES trees) until we find the tree that
'corresponds to the currently logged on user.
lngRtn = objRegistry.EnumKey(HKEY_USERS, "", arrRegKeys)
For Each strKey In arrRegKeys
If UCase(strKey) = ".DEFAULT" Or UCase(Right(strKey, 8)) = "_CLASSES" Then
Else
Set objSID = objWbem.Get("Win32_SID.SID='" & strKey & "'")
'If the account name of the current sid we're checking matches the accountname we're looking for Then
'enumerate the Network subtree
If objSID.accountname = sUser Then
regpath2enumerate = strkey & "\Network" 'strkey is the SID
objRegistry.enumkey hkey_users, regpath2enumerate, arrkeynames
'If the array has elements, go and get the drives info from the registry
If Not (IsEmpty(arrkeynames)) Then
For Each subkey In arrkeynames
regpath = strkey & "\Network\" & subkey
regentry = "RemotePath"
objRegistry.getstringvalue hkey_users, regpath, regentry, dapath
wscript.echo subkey & ":" & vbTab & dapath
Next
End If
End If
End If
Next
http://gallery.technet.microsoft.com/scriptcenter/3dd6af3e-edfa-4581-bc35-805314f26bb8
Or you can utilize the C# version:
http://bytes.com/topic/net/answers/170583-list-mapped-drives-remote-machine

Related

Access is denied. 0x80070005 (E_ACCESSDENIED) when looking for COM Ports

We have run into a situation where some user accounts on a small number of PCs are getting:
Access is denied: 0x80070005 (E_ACCESSDENIED)
when trying to get to a portion of the application that is looking for the COM port that has a barcode scanner attached to it.
I'm thinking it's breaking in one of the following sections of code:
Public Shared Function ProcessConnectionOptions() As ConnectionOptions
Dim options As New ConnectionOptions()
options.Impersonation = ImpersonationLevel.Impersonate
options.Authentication = AuthenticationLevel.[Default]
options.EnablePrivileges = True
Return options
End Function
OR
Public Shared Function ConnectionScope(ByVal machineName As String, ByVal options As ConnectionOptions, ByVal path As String) As ManagementScope
Dim connectScope As New ManagementScope()
connectScope.Path = New ManagementPath("\\" & machineName & path)
connectScope.Options = options
connectScope.Connect()
Return connectScope
End Function
OR
Dim options As ConnectionOptions = ProcessConnection.ProcessConnectionOptions()
Dim connectionScope As ManagementScope = ProcessConnection.ConnectionScope(Environment.MachineName, options, "\root\CIMV2")
Dim objectQuery As New ObjectQuery("SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0")
Dim comPortSearcher As New ManagementObjectSearcher(connectionScope, objectQuery)
Is there a particular permission that a specific user account has to have in order to be able to access the COM ports on a PC?

Connecting to WMI Remotely with C# to a non-domain PC not working

I use the Microsoft.Management.Infrastructure namespace to connect to remote computers to get WMI information and it works. But when I try to connect to a non-domain PC it does not work. Can anyone pinpoint what I am doing wrong.
Here is the code:
string computer = "Computer_B";
string domain = "WORKGROUP";
string username = ".\\LocalAdminUserName";
string plaintextpassword;
Console.WriteLine("Enter password:");
plaintextpassword = Console.ReadLine();
SecureString securepassword = new SecureString();
foreach (char c in plaintextpassword)
{
securepassword.AppendChar(c);
}
CimCredential Credentials = new
CimCredential(PasswordAuthenticationMechanism.Default, domain,
username,securepassword);
WSManSessionOptions SessionOptions = new WSManSessionOptions();
SessionOptions.AddDestinationCredentials(Credentials);
CimSession Session = CimSession.Create(computer, SessionOptions);
var allVolumes = Session.QueryInstances(#"root\cimv2", "WQL", "SELECT * FROM Win32_LogicalDisk");
// Loop through all volumes
foreach (CimInstance oneVolume in allVolumes)
{
Console.Writeline(oneVolume.CimInstanceProperties["SystemName"].Value.ToString());
}
I am not sure what to take as paramaters for domain and username for a local computer. I have already done/tryed the following:
run winrm quickconfig on the remote local computer
use PasswordAuthenticationMechanism.Negotiate cause I have read Kerberos only
works for domain users and password
added the computer I run the code on to the TrustedHosts on the local computer with winrm config. Also tryed adding * to the TrustedHosts
Used for username="computer_B\LocalAdminUserName". I have also tryed with domain=""
Any suggestions what I am doing wrong?
The error I keep getting is: WinRM cannot process the request. The following error with error code 0x8009030e occurred while using Negotiate authentication: A specified logon session does not exist. It may already have been terminated.
This can occur if the provided credentials are not valid on the target server, or if the server identity could not be verified. If you trust the server identity, add the server name to the TrustedHosts list, and then retry the request. Use winrm.cmd to view or edit the TrustedHosts list. Note that computers in the TrustedHosts list might not be authenticated. For more information about how to edit the TrustedHosts list, run the following command: winrm help config.
Try out the code below, this is working on impersonation logic.
ConnectionOptions cOption = new ConnectionOptions();
ManagementScope scope = null;
Boolean isLocalConnection = isLocalhost(machine);
if (isLocalConnection)
{
scope = new ManagementScope(nameSpaceRoot + "\\" + managementScope, cOption);
}
else
{
scope = new ManagementScope("\\\\" + machine + "\\" + nameSpaceRoot + "\\" + managementScope, cOption);
}
if (!String.IsNullOrEmpty(ACTIVE_DIRECTORY_USERNAME) && !String.IsNullOrEmpty(ACTIVE_DIRECTORY_PASSWORD) && !isLocalConnection)
{
scope.Options.Username = ACTIVE_DIRECTORY_USERNAME;
scope.Options.Password = ACTIVE_DIRECTORY_PASSWORD;
}
scope.Options.EnablePrivileges = true;
scope.Options.Authentication = AuthenticationLevel.PacketPrivacy;
scope.Options.Impersonation = ImpersonationLevel.Impersonate;
scope.Connect();

Invoke RenamePrinter as a non-administrator user

I'm trying to rename a printer using WMI in C#. I can run queries to select printers, but when I try to invoke the RenamePrinter method, I get an Access Denied result. I've tried running this application as administrator and creating a manifest, but I can't seem to invoke this method unless I'm actually running under the administrator account.
var oSearcher = new ManagementObjectSearcher(oMs, oQuery);
ManagementObjectCollection oReturnCollection = oSearcher.Get();
foreach (ManagementObject oReturn in oReturnCollection)
{
var objectClass = new ManagementClass("Win32_Printer");
var inParams = objectClass.GetMethodParameters("RenamePrinter");
inParams["NewPrinterName"] = "..."; // something
ManagementBaseObject oResult = oReturn.InvokeMethod("RenamePrinter", inParams, null);
var result = oResult["returnValue"]; // 5 = Access Denied
Is there some way I can invoke RenamePrinter under a normal user's account -- even if it means running as administrator?
I've been trying to do this, and I've found that I can't do this with certain network printers, but with local printers it works.
What I did was launch PowerShell as local admin and run it from there:
public void RenamePrinter(string strCurrentName, string strNewPrinterName)
{
var newProcessInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = #"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe",
Verb = "runas",
CreateNoWindow = true,
Arguments = "-Command \"$printer = get-wmiobject win32_printer | where { $_.Name -eq '" + strCurrentName + "' }; $printer.RenamePrinter('" + strNewPrinterName + "')\""
};
System.Diagnostics.Process.Start(newProcessInfo);
}
I receive the same "Access Denied" error when I attempt this with network printers (maybe it's a driver thing? I don't know) but this works for local printers.

wmi c#. copy file from remote machine

I use mgmtclassgen.exe and get wrapper(DataFile.cs) class for CIM_DataFile wmi class. Code below works perfect on localhost (without filling credentionals), but when I connect to remote machine variable returnResult=9 (Invalid object). But size of variable dataFileCollection=1
var _connectionOptions = new ConnectionOptions();
_connectionOptions.Username = "username";
_connectionOptions.Password = "password";
_connectionOptions.Authority = String.Format("ntlmdomain:{0}", "DOMAIN");
var _managementScope = new ManagementScope(String.Format("\\\\{0}\\root\\cimv2",
"RemotePCName"), _connectionOptions);
var dataFileCollection = DataFile.GetInstances(_managementScope,
#"Name = 'C:\\Windows\\System32\\mapisvc.inf'";
var tempFilePath = "c:\\temp.txt");
if (dataFileCollection.Count > 0)
{
foreach (var dataFile in dataFileCollection.Cast<DataFile>())
{
var returnResult = dataFile.Copy(tempFilePath);
if (File.Exists(tempFilePath))
{
List<string> lines = File.ReadAllLines(tempFilePath).ToList();
File.Delete(tempFilePath);
}
}
}
try adjusting your management scope differently
Maybe you could try it like:
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(
"\\\\" + strComputer + "\\root\\CIMV2",
"SELECT * FROM Win32_PerfFormattedData_MSSQLSERVER_SQLServerDatabases");
where strComputer is the name of the remote pc and Win32_Perf... the class you're trying to query. This works for me, as it is in a local network, though I am not certain where your remote machine is located.
You could as well to go http://www.microsoft.com/en-us/download/details.aspx?id=8572 which is a WMI-query generator by Microsoft. This allows you to generate query's in either C#, VB, and VB scripts. While setting the connection properties.
Might be worth a shot.

Find Terminal Services user's document folder

I'm trying to allow users to use their local scanners with a Terminal Server via an IIS aspx page containing a browser plugin. The plugin can scan files and pass the data to an aspx page which uploads files to the server.
I'm using HttpContext.Current.User.Identity.Name to get a string containing the name of the remote user. How can I find the user's documents folder on the terminal server?
Made a bit of progress. Here's a way to find a the path for a known username using Powershell:
$user = Get-WmiObject Win32_UserAccount | Where-Object { $_.Name -eq 'known_username' }
cd 'HKLM:\software\Microsoft\Windows NT\CurrentVersion\ProfileList'
$key = Get-Item $user.SID
$saveLocation = $key.GetValue("ProfileImagePath")
Here's the C# version:
string loginName = HttpContext.Current.User.Identity.Name;
Regex r = new Regex(#"\w+[\\]");
string userName = r.Replace(loginName, "");
throw new System.ArgumentException("Debug: '" + HttpContext.Current.User.Identity.IsAuthenticated.ToString() +"'", "userName");
SelectQuery sQuery = new SelectQuery("Win32_UserAccount", "name='" + userName + "'");
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
string sid = "";
foreach (ManagementObject mObject in mSearcher.Get())
{
sid = mObject["SID"].ToString();
break; //mSearcher.Get() is not indexable. Behold the hackyness!
}
string saveLocation = Microsoft.Win32.Registry.GetValue(
"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + sid,
"ProfileImagePath", null).ToString();
C# is not my native tongue; there are probably methods of accomplishing this that are less blunt. But it does work.

Categories