c# RPC server error when query for active username - c#

I have a function that connect to a remote computer using WMI. When I launch it with administrator privileges, the system says RPC server error.
I have the same kind of script in Powershell, it works correctly, no RPC server error (so WMI is working on the network, firewall isn't blocking it. I only found that kind of answer on the internet), and other softwares written in c# in the company are working correctly with those computers (the developer is no longer working for the company and I can't get my hand on the source code )
The same issue occurs whether I use the name of the computer or its IP adress.
static public string GetUsername(string computer)
{
string username = string.Empty;
ManagementScope scope = new ManagementScope("\\\\computer\\root\\cimv2");
//scope.Connect(); If I activate this line, the error occurs on this line
string queryString = "select LogonId from win32_logonsession where logontype = 2";
ManagementObjectSearcher query = new ManagementObjectSearcher(scope, new SelectQuery(queryString));
foreach (ManagementObject mo in query.Get()) //if scope.connect(); is not activated, it's blocking on this line
{
username = mo["LogonId"].ToString();
}
return username;
}
I tried to run my software from the Visual Studio or directly from the .exe (using administrator). I also tried an impersonation as a workstation admin programatically, but the problem is still there.
Thank you in advance for your kind help.
EDIT :
I already tried the solution with connectionOptions like this :
options.Username = "YOUR USERNAME";
options.Password = "YOUR PASSWORD";
options.Authority = "ntlmdomain:YOURDOMAIN";
and like this :
options.Username = "YOUR USERNAME";
options.Password = "YOUR PASSWORD";
options.Authority = "Kerberos:YOURDOMAIN";
and added the impersionation options
options.Impersonation = ImpersonationLevel.Impersonate;
options.EnablePrivileges = true;
Still not working.

Have you tried setting a username and password for the managmentscope like this?
static public string GetUsername(string computer)
{
string username = string.Empty;
ConnectionOptions options = new ConnectionOptions();
options.Username = "YOUR USERNAME";
options.Password = "YOUR PASSWORD";
options.Authority = "ntlmdomain:YOURDOMAIN";
ManagementScope scope = new ManagementScope("\\\\computer\\root\\cimv2",options);
//scope.Connect(); If I activate this line, the error occurs on this line
string queryString = "select LogonId from win32_logonsession where logontype = 2";
ManagementObjectSearcher query = new ManagementObjectSearcher(scope, new SelectQuery(queryString));
foreach (ManagementObject mo in query.Get()) //if scope.connect(); is not activated, it's blocking on this line
{
username = mo["LogonId"].ToString();
}
return username;
}
For more information have a look at the MSDN page for ManagementScope here
And for the ConnectionOptions here.

Ok, I got this... My mistake was in the line
ManagementScope scope = new ManagementScope("\\\\computer\\root\\cimv2",options);
It should have been
ManagementScope scope = new ManagementScope("\\\\" + computer + "\\root\\cimv2",options);
The variable computer is not recognised in a string as it is in Powershell... My bad!
Thanks to everybody who tried to help... I'll try to be more careful next time!

Related

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();

Can't access hardware info of remote computer with WMI: Access is denied

I am trying to create an application that uses WMI to retrieve information about a computer on my local network. When I run it, I get an access denied error. Here is the code:
private void GetHDDdetails()
{
ConnectionOptions options = new ConnectionOptions();
options.Username = "username";
options.Password = "password";
options.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope oMs = new ManagementScope("\\\\remoteHostName\\root\\cimv2", options);
ObjectQuery oQuery = new ObjectQuery("SELECT Size FROM Win32_DiskDrive");
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs, oQuery);
ManagementObjectCollection oCollection = oSearcher.Get();
foreach (ManagementObject obj in oCollection)
{
hddBox.Text = obj["Size"].ToString();
}
}
I have replaced some of the info above, such as user name and password, with placeholders for this post.
Some of the things I have tried is this: Disabling firewall on both machines, making sure TCP NetBIOS service and RCP and WMI services are running on both. The account I am using is an administrator on the local computer. Everything I have found online tells me to check these, but it is obviously something else.
If someone can point me in the right direction, that would be great.
Please check using wbemtest that you can access the information from remote machine. And i hope you are replacing remoteHostName properly.
And make changes to authentication level, if you can.
scope.Options.EnablePrivileges = true;
scope.Options.Authentication = AuthenticationLevel.PacketPrivacy;

Execute a process in a remote machine using WMI

I want to open process pon remote machine, this remote machine is inside local network.
I try this command and in the remote machine nothing happen, this user that i connect with have administrators rights.
Both machines running Windows 7
static void Main(string[] args)
{
try
{
//Assign the name of the process you want to kill on the remote machine
string processName = "notepad.exe";
//Assign the user name and password of the account to ConnectionOptions object
//which have administrative privilege on the remote machine.
ConnectionOptions connectoptions = new ConnectionOptions();
connectoptions.Username = #"MyDomain\MyUser";
connectoptions.Password = "12345678";
//IP Address of the remote machine
string ipAddress = "192.168.0.100";
ManagementScope scope = new ManagementScope(#"\\" + ipAddress + #"\root\cimv2", connectoptions);
//Define the WMI query to be executed on the remote machine
SelectQuery query = new SelectQuery("select * from Win32_process where name = '" + processName + "'");
object[] methodArgs = { "notepad.exe", null, null, 0 };
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject process in searcher.Get())
{
//process.InvokeMethod("Terminate", null);
process.InvokeMethod("Create", methodArgs);
}
}
Console.ReadLine();
}
catch (Exception ex)
{
//Log exception in exception log.
//Logger.WriteEntry(ex.StackTrace);
Console.WriteLine(ex.StackTrace);
}
}
you are not opening a process with that code but you are enumerating all the running process named "iexplore.exe" and close them.
I think an easier, better way is to use SysInternals PsExec or the Task Scheduler API
If you want to use WMI your code should look like this:
object theProcessToRun = { "YourFileHere" };
ManagementClass theClass = new ManagementClass(#"\\server\root\cimv2:Win32_Process");
theClass.InvokeMethod("Create", theProcessToRun);
----------In reply to your comment------------------
First of all you need to change your attitude and approach to coding and read the code that your are copy/pasting.
Then you should study a little more about programming languages.
No I will not write the code for you. I gave you an hint to point to the right direction. now it is your turn to develop it. Have fun!!
This is script that i did for my company before this using vbs script. can search the net to convert it to C# or etc. Fundamental of the steps and how to start a service using WMI. Have a nice coding and have fun.
sUser = "TESTDomain\T-CL-S"
sPass = "Temp1234"
Set ServiceSet = GetObject("winmgmts:").ExecQuery("Select * from Win32_Service where Name = 'netlogon'")
For Each Service In ServiceSet
Service.StopService
Service.Change "netlogon",Service.PathName, , ,"Automatic",false,sUser,sPass
Service.StartService
Next
Set Service = Nothing
Set ServiceSet = Nothing

How to Connect to computer on the workgroup?

I am trying to connect to a computer over the workgroup. My code is below:
ConnectionOptions options = new ConnectionOptions();
options.Impersonation = ImpersonationLevel.Impersonate;
options.Username = "testusername";
options.Password = "testpwd";
ManagementScope scope = new ManagementScope(#"\\19x.16x.x.xx\C$\TestFolder", options);
scope.Connect();
if (scope.IsConnected == true)
{
MessageBox.Show("Connection Succeeded", "Alert");
}
else
{
MessageBox.Show("Connection Failed", "Alert");
}
When I run this, I get the exception : "Invalid parameter"
How to sort this out?
edit:
The error is in this line below:
ManagementScope scope = new ManagementScope(#"\\19x.16x.x.xx\C$\TestFolder", options);
How do we specify the drive? I think the $ is causing the problem
Update
Per user's comments, OP is trying to do something entirely different than the question implies. To copy a file from one location to another programmatically one can use File.Copy:
File.Copy(sourcePath, destinationPath)
Where destinationPath is a valid network path. Over a network, I recommend using a machineName instead of an IP address. Especially over a VPN where the potential for an IP address to change is high.
\\machineName\path\filename.csv

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.

Categories