How to execute debug view on remote computer using wmi - c#

I am looking to run Debugview on a remote machine (I have the username,password and the ip adress of that machine). I have developed this code
object[] theProcessToRun = { "C:\\Dbgview.exe /t /l C:\\debugview1.log" };
ConnectionOptions theConnection = new ConnectionOptions();
theConnection.Username = "Username";
theConnection.Password = "Password";
ManagementScope theScope = new ManagementScope("\\\\ipaddress\\root\\cimv2", theConnection);
ManagementClass theClass = new ManagementClass(theScope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
theClass.InvokeMethod("Create", theProcessToRun);
This code starts the debugview on the remote computer in background(which can be viewed in taskmanager by selecting processes run by all users option) but the problem is, it does not connect the localhost.
so can anyone suggest me the changes or any other way to achieve what i am doing.
EDIT : GOT THE ANSWER
You need to have administrative rights to logon the remote computer so debug view gets connected automatically (to local host)

Related

Access denied when reading / writing to network location as a remote process

I'm currently trying to launch a process on a remote machine using WMI in C#. The process reads and writes to a file that is stored on a separate server.
When I manually login to the remote machine, I can run the process and it all works fine.
However, when I try to launch the process on the remote from my local machine using WMI, I get the following error:
System.UnauthorizedAccessException: Access to the path '\\server\path\input.txt' is denied.
I've tried multiple connection options, but I'm not sure how to re-create the permissions that I seem to have when I login manually... What do I need to do?
Local machine code
static void LaunchRemoteProcess(string remoteMachine, string command)
{
ConnectionOptions connectionOptions = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
EnablePrivileges = true
};
var managementScope = new ManagementScope(string.Format(#"\\{0}\root\cimv2", remoteMachine), connectionOptions);
managementScope.Connect();
var managementPath = new ManagementPath("Win32_Process");
var objectGetOptions = new ObjectGetOptions();
var managementClass = new ManagementClass(managementScope, managementPath, objectGetOptions);
// Launch the command asynchronously
var inParams = managementClass.GetMethodParameters("Create");
inParams["CommandLine"] = command;
var outParams = managementClass.InvokeMethod("Create", inParams, null);
}
Remote machine code
string networkPath = #"\\server\path";
string inputFile = "input.txt";
string inputText = File.ReadAllText(Path.Combine(networkPath, inputFile));
string outputFile = "output.txt";
File.WriteAllText(Path.Combine(networkPath, outputFile), inputText);
Edit 1
I have already tried using the credentials of the user for which the process works if I log on to the remote machine manually and the process still fails with the same error:
ConnectionOptions connectionOptions = new ConnectionOptions
{
Username = "username",
Password = "password",
Authority = "ntlmdomain:COMPANYNAME.CO.UK,
EnablePrivileges = true
};
Am I missing something with regards to the Authority, Authentication, or Impersonation attributes?
Impersonation vs Delegation
Your WMI code uses impersonation, so the server side runs in the security context of the user who calls the code on the client. But this is only valid on the server itself, not for accessing e.g. a remote CIFS share (as in your case).
You have to use delegation.
First, change
Impersonation = ImpersonationLevel.Impersonate,
to
Impersonation = ImpersonationLevel.Delegate,
If you get an exception then, delegation does not yet work in your environment.
Check:
Calling user account: "Account is sensitive and cannot be delegated" must not be checked in the user properties (Active Directory Users and Computers)
server machine account: "Trust this computer for delegation to any service..." must be checked
local security policy on the server: "Enable computer and user accounts to be trusted for delegation" must include the calling user.
See
https://msdn.microsoft.com/en-us/library/aa389288%28VS.85%29.aspx
for further information on this topic.
Added: (see the comments below):
If Delegate is not an option in your environment (e.g. group policies do not allow for this, and you do not have the rights to change them), you may check some alternative ways.
You probably heard of psexec.
Or, what I did some years ago, and which runs in production in a enterprise environment on a few servers for many years very successfull:
I created a scheduled task which starts a program and set the technical user + password for this task. The task was configured for "run once in year 2200 :-)".
Then I wrote commands in a queue (I used a simple command file) and started the task from a remote machine.
Doing it this way, delegation is not required, since the scheduled task itself logs on as the technical user account ("logon as batch" privs are required).
As the reason states, the user id you are using on your PC does not seem to have access for to another computer's location (though it is a server, it is some other computer).
You may get access for your user id or use Impersonation to use an user id that already has access to the location.
Find more details here: https://msdn.microsoft.com/en-us/library/w070t6ka%28v=vs.110%29.aspx
Edited: Add user name password too. That may help.

Running remote exe on remote device

I'm stuck with an issue that may not be easily solvable, but I'm hoping someone will be able to help. I am attempting to run an exe to install some software (SCCM client) on a remote device.
So what is happening is that I am running the program from my PC (Host1) to connect to a remote device (Host2) and instruct that device to run an exe from a server.
I have been using standard remote execution WMI code with no luck:
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", Host2), connOptions);
manScope.Connect();
if(manScope.IsConnected)
{
ObjectGetOptions objectGetOptions = new ObjectGetOptions();
ManagementPath managementPath = new ManagementPath("Win32_Process");
ManagementClass processClass = new ManagementClass(manScope, managementPath, objectGetOptions);
ManagementBaseObject inParams = processClass.GetMethodParameters("Create");
inParams["CommandLine"] = #sCommand;
ManagementBaseObject outParams = processClass.InvokeMethod("Create", inParams, null);
}
else
{
MessageBox.Show("An error occurerd while attempting to connect to WMI.");
}
The problem I'm running into is executing sCommand when the exe is on a server. So when the parameter is "\\server\share\program.exe" nothing happens. When the parameter is "c:\Folder\program.exe" it works great. These devices we are targeting unfortunately have Admin$ and C$ disabled, and do not have the exe on their hard drive.
I am at a loss unfortunately - is it possible to use the Win32_Process.Create method to run a UNC exe, or is it possible to copy the exe or even the folder it is in to the Host device when Admin$ and C$ are disabled? I am trying to avoid psexec, and I'm honestly wondering if I'd run into the same issue using it anyways.
Can't you deploy a custom Windows Service application on the remote machine? This way you'll just have to communicate with the service using whatever channel you want and run the executable from there.

Trying to remotely access through wmi using C#

I have this piece of code:
private ManagementScope CreateNewManagementScope(string server)
{
string serverString = "\\\\" + server + "\\root\\cimv2";
ConnectionOptions options = new ConnectionOptions();
options.Username = "name";
options.Password = "password";
ManagementScope scope = new ManagementScope(serverString, options);
scope.Connect();
return scope;
}
With that code I am trying to remotely access another PC though WMI. The password and the username are 100% correct (I tested them with wmic /node:pc /username:name /password:pwd and this worked) but I am getting access denied
(Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Any Ideas what I am doing wrong? I am working with Win 7/C#/.NET 4.0
Thanks for any Help!
you can try with admin credential :
string serverString = #"\\" + strIPAddress + #"\root\cimv2"
Check what is logged on the other machines Security eventlog since it will provide you with a clue on what's wrong with access permissions.
I'm quite sure that you can solve the issue after checking the TechNet article "Connecting to WMI Remotely Starting with Windows Vista" and the related one. Specifically this part:
"Setting DCOM Security to Allow a User to Access a Computer Remotely".
Check the code of Services+ (Advanced Windows Service Manager) contains all what you need about WMI Win32_Service.
To Troubleshoot or debug:
Make sure the computer and server are on the same domain
Remove your code credential and make an EXE form your code then Run
the EXE as privileged user.
Use Services+ (mentioned above) or Services.msc to connect to the
server.
Make sure RPC service is running on Remote Server.
Try to trun off the firewall temporary on the server.

How to get permissions for using System.Diagnostics.Process.GetProcess(string)?

I'm using Microsoft Visual Studio to make a simple remote task manager for experience purposes.
I want to use Process.GetProcesses(string); but there is an access denied exception that won't allow me to get the remote computer process. In fact it is normal because we should authenticate using a user name and password, but how?
You may try to use WMI for this purpose
/// using System.Management;
// don't forget! in VS you may have to add a new reference to this DLL
ConnectionOptions op = new ConnectionOptions();
op.Username = "REMOTE_USER";
op.Password = "REMOTE_PASSWORD";
ManagementScope sc = new ManagementScope(#"\\REMOTE_COMPUTER_NAME\root\cimv2", op);
ObjectQuery query = new ObjectQuery("Select * from Win32_Process");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(sc, query);
ManagementObjectCollection result = searcher.Get();
foreach (ManagementObject obj in result)
{
if (obj["Caption"] != null) Console.Write(obj["Caption"].ToString() + "\t");
if (obj["CommandLine"] != null) Console.WriteLine(obj["CommandLine"].ToString());
}
For further details on Win32_Process class see MSDN.
hth
EDIT: Just read your post again, the steps described in my post only apply in a domain, I assume you work inside a workgroup. I'm sorry.
I recently ran into a similar issue when running Visual Studio as Administrator on Windows 7. It seems like permissions on remote machines and network shares are dropped (even in a domain!) if you elevate your program to run as local administrator, which will be the case if you run a program out of VS when VS is run as admin. This even happens if you have domain wide admin accounts.
Try the following:
Build the solution
Run it manually with your account which has hopefully
privileges on the remote computer from windows explorer, without elevation
If this helps, you could stop running VS as administrator. It worked out for me.
I'm pretty sure you need elevation to do this, or at least use a stronger user by impersonation

How to verify a remote DSN entry?

I am creating a verification utility that check various parts of an application to ensure they are configured correctly. One of the things I need to check is that the DSN entry in a Web.config file is a functional DSN, and that the DSN is pointing to the correct SQL server and database.
Currently you can run the utility in one of two modes, local or remote. My problem occurs when I am trying to verify a remote systems DSN on my local computer. I know why it doesnt work, I don't have the same DSN on my local computer. So what I need to figure out is how to either retrieve the DSN connection information from a remote machine to which I have administrative access, or to get the remote machine to verify it for me.
Any suggestions? Thanks!
EDIT
So apparenty the DSN info is stored in the registry too!
oRegConn = new ConnectionOptions();
oRegConn.Username = username;
oRegConn.Password = password;
scope = new ManagementScope(#"//" + servername + #"/root/default", oRegConn);
registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
inParams = registry.GetMethodParameters("GetStringValue");
inParams["sSubKeyName"] = "SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources\\" +
dsnName;
inParams["sValueName"] = "Server";
outParams = registry.InvokeMethod("GetStringValue", inParams, null);
server = outParams["sValue"].ToString();
Well I would say that its not really a valid check if you run it on another system (yours). The firewall rules could be different, the driver versions might be off, and a million more things. The first thing I would say is if this is a web application, build in a page that can run these checks, like a status page. If this is an application that you cant do that, you can use WMI to run a remote process and gather the results. Other than that your last option might be to do a self hosting WCF service or a windows service that you connect to for querying info. This isnt too uncommon, and I have done it many times using WMI.
In that case, you may want to investigate PSExec (by Sysinternals). You can run your utility on a remote machine in "local" mode, as long as you have Administrative access to that machine.
Your "DSN Verification" part would have to be a separate executable/command, which can be executed by your main utility using syntax similar to the following:
psexec \\REMOTE-Machine <DSN Verification Utility>.exe
The output can be captured within C# by redirecting stdout/stderr.
Forgive me if I'm mistaken, but wouldn't just opening a connection to remote database server let you know if your connection string/DSN is okay?
So the DSN conn values are stored in the registry as plaintext, which is what I needed.
oRegConn = new ConnectionOptions();
oRegConn.Username = username;
oRegConn.Password = password;
scope = new ManagementScope(#"//" + servername + #"/root/default", oRegConn);
registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
inParams = registry.GetMethodParameters("GetStringValue");
inParams["sSubKeyName"] = "SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources\\" +
dsnName;
inParams["sValueName"] = "Server";
outParams = registry.InvokeMethod("GetStringValue", inParams, null);
server = outParams["sValue"].ToString();

Categories