Saturday, October 3, 2009

Doing Some Stuff on Another Computer

It is fairly easy to restart a service running on a remote computer. You only need to know two things - the name of a remote computer and the name of the service itself. No surprises.

private void RestartService(string MachineName, string ServiceName)
{
using (ServiceController controller = new ServiceController())
{
controller.MachineName = MachineName;
controller.ServiceName = ServiceName;
controller.Stop();
controller.Start();
}
}

Almost as easy is to monitor the printers on the remote computer using WMI. This time, only the remote computer name is required. Here's a small function that returns the list of CustomPrinterObjects. CustomPrinterObject can be defined like this, for example:

public class CustomPrinterObject
{
private string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}

//many other properties
....

private string _status;

public string Status
{
get { return _status; }
set { _status = value; }
}
}

Here's how I get the information about the printers on the remote computer:

public List GetLocalPrinters(string serverName)
{
string[] pStatus = {"Other","Unknown","Idle","Printing","WarmUp","Stopped Printing",
"Offline"};

string[] pState = {"Paused","Error","Pending Deletion","Paper Jam","Paper Out",
"Manual Feed","Paper Problem", "Offline","IO Active","Busy",
"Printing","Output Bin Full","Not Available","Waiting",
"Processing","Initialization","Warming Up","Toner Low",
"No Toner","Page Punt", "User Intervention Required",
"Out of Memory","Door Open","Server_Unknown","Power Save"};

List printers = new List();

string query = string.Format("SELECT * from Win32_Printer");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
searcher.Scope = new ManagementScope("\\\\" + serverName + "\\root\\CIMV2");
ManagementObjectCollection coll = searcher.Get();

System.Windows.Forms.MessageBox.Show(coll.Count.ToString());

foreach (ManagementObject printer in coll)
{
CustomPrinterObject prn = new CustomPrinterObject();

foreach (PropertyData property in printer.Properties)
{
if (property.Value != null)
{
switch (property.Name)
{
case "Name":
prn.Name = property.Value.ToString();
break;
case "Comment":
prn.Comment = property.Value.ToString();
break;
case "PrinterState":
prn.PrinterState = pState[Convert.ToInt32(property.Value)];
break;
case "PrinterStatus":
prn.PrinterStatus = pStatus[Convert.ToInt32(property.Value)];
break;
case "Location":
prn.Location = property.Value.ToString();
break;
case "Type":
prn.Type = property.Value.ToString();
break;
case "DriverName":
prn.Model = property.Value.ToString();
break;
case "WorkOffline":
prn.Status = property.Value.ToString().Equals("True") ? "Offline" : "Online";
break;
default:
break;
}
}
}
printers.Add(prn);
}
return printers;
}

Reading the registry contents on the remote machine is very easy again.

On the local computer I would open the key like this

RegistryKey rk = Registry.LocalMachine.OpenSubKey(subKey);

And on the remote I would do it like this

RegistryKey hklm = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "MyRemoteServer");
RegistryKey rk = hklm.OpenSubKey(subKey);

Obviously, all of the samples will work subject to permissions of the account that runs them. Errors will happen if the account does not have enough privileges to access the printers or services on the remote computer.

by . Also posted on my website

No comments: