How to remove a "zombie" network printer connection in c#? - c#

I'm trying to delete a network printer that was removed from the printserver.
I'm using this code for deleting installed printers:
public void unmapPrinter()
{
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
ManagementScope scope = new ManagementScope(ManagementPath.DefaultPath, options);
scope.Connect();
ManagementClass win32Printer = new ManagementClass("Win32_Printer");
ManagementObjectCollection printers = win32Printer.GetInstances();
foreach (ManagementObject printer in printers)
{
printer.Delete();
}
}
This works well with normal printers, but there is one that was removed from the printerserver that return me "Access Denied". Some one know this problem?
Even windows can uninstal that printer, when i try to delete that from "Printers and Hardware" it tell me that the printer is in warning.

Related

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;

Network printers cannot access after publishing website (application) locally

Here is the sample code I used:
System.Management.ManagementScope objMS =
new System.Management.ManagementScope(ManagementPath.DefaultPath);
objMS.Connect();
SelectQuery objQuery = new SelectQuery("SELECT * FROM Win32_Printer");
ManagementObjectSearcher objMOS = new ManagementObjectSearcher(objMS, objQuery);
System.Management.ManagementObjectCollection objMOC = objMOS.Get();
foreach (ManagementObject Printers in objMOC)
{
if (Convert.ToBoolean(Printers["Local"])) // LOCAL PRINTERS.
{
cmbLocalPrinters.Items.Add(new ListItem(Printers["Name"].ToString()));
}
if (Convert.ToBoolean(Printers["Network"])) // ALL NETWORK PRINTERS.
{
cmbNetworkPrinters.Items.Add(new ListItem(Printers["Name"].ToString()));
}
}
When I run my application through Visual Studio IDE, I can see all the printers(including Network printer) using my code.But when I published this application (using Build--> Publish Websites) on my local machine (same on which I am developing my application), I get only local printers which are installed on my PC (not getting Network printer)
If you need to avoid "identity impersonate", you can still do it with this nifty trick. You have to add the printer on your server as a Local Printer and point the Port to the printer's IP address (or domain).
On the Windows Server 2003:
run the "Add New Printer" wizard
select the new printer as "Local Printer Attached to this Computer"
when selecting the port, select the option to "Create a New Port"
for the Type of Port, select "Local Port"
in the "Enter Port Name" box, enter the IP address of the printer or the full domain name and printer name (Example: \\myDomain\HP LaserJet 2800xh)
if prompted to share the printer, make sure you don't share it
That's it!
Then run your code like you normally would and, Bham! You got your Network printer available to you!
System.Management.ObjectQuery oquery = new System.Management.ObjectQuery("SELECT * FROM Win32_Printer");
System.Management.ManagementObjectSearcher mosearcher = new System.Management.ManagementObjectSearcher(oquery);
System.Management.ManagementObjectCollection moc = mosearcher.Get();
foreach (ManagementObject mo in moc)
{
System.Management.PropertyDataCollection pdc = mo.Properties;
foreach (System.Management.PropertyData pd in pdc)
{
if ((bool)mo["Network"])
{
cmbNetworkPrinters.Items.Add(mo[pd.Name].ToString());
}
if ((bool)mo["Local"])
{
cmbLocalPrinters.Items.Add(mo[pd.Name].ToString());
}
}
}

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

Uninstall application on remote computer silently

I am developing a C# program to remotely uninstall an application. It works fine but the problem is that it does not list all of the installed products on a particular selected computer.
The code for listing the installed product using WMI is :
void ListAllProducts()
{
try
{
ConnectionOptions connection = new ConnectionOptions();
connection.Username = Connect.UserName;
connection.Password = Connect.Password;
connection.Authority = "ntlmdomain:MSHOME";
ManagementScope scope = new ManagementScope("\\\\"+ Connect.MachineName +"\\root\\CIMV2", connection);
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Product");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
System.Threading.Thread.Sleep(5000);
foreach (ManagementObject queryObj in searcher.Get())
{
listBox4.Items.Add(queryObj["Name"].ToString());
listBox2.Items.Add (queryObj["Name"].ToString ());
listBox1.Items.Add(queryObj["IdentifyingNumber"].ToString());
listBox3.Items.Add(queryObj["Version"].ToString());
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
The code for uninstalling all product is :
void UninstallProduct()
{
try
{
ConnectionOptions connection = new ConnectionOptions();
connection.Username = Connect.UserName;
connection.Password = Connect.Password;
connection.Authority = "ntlmdomain:MSHOME";
ManagementScope scope = new ManagementScope("\\\\"+Connect.MachineName +"\\root\\CIMV2", connection);
scope.Connect();
ManagementObject classInstance = new ManagementObject(scope, new ManagementPath ("Win32_Product.IdentifyingNumber='"+listBox1.Text +"',Name='"+listBox2.Text+"',Version='"+ listBox3.Text+"'"),null);
// no method in-parameters to define
// Execute the method and obtain the return values.
ManagementBaseObject outParams =
classInstance.InvokeMethod("Uninstall", null, null);
// List outParams
MessageBox.Show ("Uninstallation Starts");
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message);
}
}
Please help me out to list all the products installed on the selected machine and to uninstall it without the consent of the user of that selected machine.
I believe your question relates to knowing which applications are installed on a remote machine. Once you know that, you can use your code to uninstall them. With that being the case, here is a link to an article on how to list all of the applications (with their uninstall information) on a remote computer:
http://mdb-blog.blogspot.com/2010/12/c-check-if-programapplication-is.html
The WMI Win32_Product only represents products that are installed by Windows Installer. To get a list of all installed products, you need to enumerate the subkeys of the SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall registry key. To do this remotely, you can use the WMI registry class StdRegProv class. TechNet includes sample scripts that show how this can be done, and which you can adapt to your particular needs:
How do I list all the installed applications on a given machine?
List Installed Software

Problem retrieving Hostaddress from Win32_TCPIPPrinterPort

I'm running into an odd issue retrieving printer port addresses.
When I get all the entries in Win32_TCPIPPrinterPort, the HostAddress field (which should have the IP address) is usually blank/null, only the port name has a value. To make it a bit stranger, if a particular port is not in use by any printer, THEN the HostAddress will have the the proper value.
The C# code is simple, and results in something like this;
IP_192.168.1.100,
printerportxyz,
richTextBox1.Clear();
ManagementObjectSearcher portSearcher = new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_TCPIPPrinterPort");
foreach (ManagementObject port in portSearcher.Get())
{
richTextBox1.AppendText(
String.Format("Name: {0} HostAddress: {1}",
port["Name"],
port["HostAddress"])
);
}
I also tried the same thing in WSH/VBS, and saw the same behavior.
I ended up having to re-visit this, and making another attempt. I found that the built-in prnport.vbs managment script had no issues - looking into it I saw that while establishing its WMI connection it had oService.Security_.Priveleges.AddAsString "SeLoadDriverPrivilege"
the solution in C# ended up specifying the WMI ConnectionOptions and setting EnablePrivileges to true. Then the HostAdress was no longer null for unused or in-use ports.
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.EnablePrivileges = true;
ManagementScope mgmtScope = new ManagementScope("root\\CIMV2", connOptions);
mgmtScope.Connect();
ObjectQuery objQuery = new ObjectQuery("SELECT * FROM Win32_TCPIPPrinterPort");
ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(mgmtScope, objQuery);
foreach (ManagementObject mo in moSearcher.Get())
{
Console.WriteLine(String.Format("PortName={0} HostAddress={1}", mo["Name"], mo["HostAddress"]));
}

Categories