I'm trying to change the printer properties, SpoolEnabled & KeepPrintedJobs, using C#. I tried using the win32_printer but the SpoolEnabled value didn't change. I'm using .NET windows forms (4.6) & Windows 10.
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Printer Where Default = True");
ManagementObjectCollection printerCollection = new ManagementObjectSearcher(query).Get();
if (printerCollection.Count > 0)
{
foreach (ManagementObject printer in printerCollection)
{
PropertyDataCollection printerProperties = printer.Properties;
if ((bool)printerProperties["Default"].Value)
{
printerProperties["SpoolEnabled"].Value = true;
printer.Put();
}
}
}
Also, I tried using the following code with no success:
ManagementPath mPath = new ManagementPath("//./root/cimv2");
mPath.RelativePath = "Win32_Printer.DeviceID=\"" + PrinterName + "\"";
ManagementObject Printer = new ManagementObject(mPath);
string oldname = Printer.Properties["SpoolEnabled"].Value.ToString();
Printer.Properties["SpoolEnabled"].Value = true;
Printer.Put();
What library should I use, using c#, to change the SpoolEnabled & KeepPrintedJobs properties?
Related
I am not a C# programer but I need to format drive with 32KB cluster using C#. I found "Format method of the Win32_Volume class" but when I am trying to format drive I always get an error 15 (Cluster size is too small). This is my code:
public static int DriveFormatting(string driveLetter)
{
string FileSystem = "FAT32", Label = "";
Boolean QuickFormat = true, EnableCompression = false;
UInt32 ClusterSize = 32;
int result = -1;
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Volume WHERE DriveLetter = '"+ driveLetter +"'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach(ManagementObject management in searcher.Get())
{
Console.WriteLine("Formating disk " + driveLetter + "...");
result = Convert.ToInt32(management.InvokeMethod("Format", new object[] { FileSystem, QuickFormat, ClusterSize, Label, EnableCompression }));
}
return result;
}
How can I do this? Thanks in advance.
I have this code to enable parental control in windows:
System.Security.Principal.NTAccount myNTAccount = new System.Security.Principal.NTAccount("username");
System.Security.Principal.SecurityIdentifier mySecurityIdentifier = (System.Security.Principal.SecurityIdentifier)myNTAccount.Translate(typeof(System.Security.Principal.SecurityIdentifier));
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2\\Applications\\WindowsParentalControls", "SELECT * FROM WpcUserSettings where SID='" + mySecurityIdentifier.ToString() + "'");
foreach (ManagementObject queryObj in searcher.Get())
{
queryObj["AppRestrictions"] = true;
queryObj["HourlyRestrictions"] = true;
queryObj["LoggingRequired"] = false;
//queryObj["LogonHours"] = ;
//queryObj["OverrideRequests"] = ;
queryObj["WpcEnabled"] = true;
queryObj.Put();
}
By this, parental control enabled, but how can i set Program limits to define allowed programs?
I found that it is related to RestrictRun registry key:
SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer
it explaned in this address:
https://www.howtogeek.com/howto/8739/restrict-users-to-run-only-specified-programs-in-windows-7/
I'm trying to terminate a process on a remote machine with WMI / C# on .NET 4.5. In the code below, when the Get method is called on the ManagementObjectSearcher instance nothing is returned, so the line inside the foreach is not reached. The ManagementScope is connected and the query variable contains the name of the process for termination.
Thx for any help.
try
{
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", NetworkName), connOptions);
manScope.Connect();
var query = new SelectQuery("select * from Win32_process where name = '" + ProcessName + "'");
using (var searcher = new ManagementObjectSearcher(manScope, query))
{
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
}
}
}
catch (ManagementException err)
{
//Do something with error message here
}
As outlined in my comment above, for completeness here's the code with my changes that are as follows.
try
{
ConnectionOptions connOptions = new ConnectionOptions();
connOptions.Impersonation = ImpersonationLevel.Impersonate;
connOptions.EnablePrivileges = true;
ManagementScope manScope = new ManagementScope(String.Format(#"\\{0}\ROOT\CIMV2", NetworkName), connOptions);
manScope.Connect();
ProcessName = ProcessName + ".exe";
using (var searcher = new ManagementObjectSearcher(manScope, new SelectQuery("select * from Win32_Process where Name = '" + ProcessName + "'")))
{
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
}
}
}
catch (ManagementException err)
{
//Do something with error message here
}
In my case i was unable to receive CPU utilization value remotely using WMI query:
SELECT PercentProcessorTime FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name='_Total'
I changed project build platform target from Any CPU to x64 to match my system bitness, and problem was solved. Another way is uncheck Prefer 32-bit checkbox when Any CPU is selected.
Use the Count property to check, whether it contains any record. That is, if(searcher.Get().count == 0) returns true, means no record is present.
public ManagementScope GetScope()
{
try
{
//string classScope="winmgmts:" + "{impersonationLevel=impersonate}!\\" + strComputer + "\\root\\cimv2";
string serverString = #"root\cimv2";
ManagementScope scope = new ManagementScope(serverString);
ConnectionOptions options = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.Connect,
EnablePrivileges = true
};
scope.Options = options;
return scope;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
public void InvokeMethodsFunctions1()
{
ManagementScope mScope = GetScope();
mScope.Connect();
if (mScope.IsConnected)
{
ManagementClass processClass =
new ManagementClass(mScope.Path);
ManagementObjectSearcher mos = new ManagementObjectSearcher(mScope, new ObjectQuery("SELECT * FROM Win32_Product"));
//get collection of WMI objects
ManagementObjectCollection queryCollection = mos.Get();
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"Result.txt"))
{
textBox1.Text = "";
//enumerate the collection.
foreach (ManagementObject m in queryCollection)
{
// access properties of the WMI object
string line = " " + m["Name"] + " , InstallDate : " + m["InstallDate"] + " LocalPackage : " + m["LocalPackage"];
Console.WriteLine(line);
file.WriteLine(line);
textBox1.Text += line + "\n";
}
}
}
}
So whats wrong in my Code ?
There is nothing wrong , the Win32_Product WMI class only list the products installed by the Windows Installer (MSI).
I just tested the following, simplified version of your code and I see everything installed on my pc, even services I wrote and installed myself:
var products = new ManagementObjectSearcher(new ObjectQuery("SELECT * FROM Win32_Product"));
var result = products.Get();
foreach (var product in result)
{
Console.WriteLine(product.GetPropertyValue("Name").ToString());
}
Console.ReadLine();
It looks like you are narrowing your query by scope, which is possibly why you aren't seeing everything, try the above and see if you have more luck.
I would like to determine the IP address of a printer, using C# (.NET 2.0). I have only the printer share name as set up on the Windows OS, in the format \\PC Name\Printer Name. The printer is a network printer, and has a different IP address to the PC. Does anyone have any pointers?
Thanks in advance for your help.
Regards, Andy.
Just adding an another solution here using .Net Framework 4.0 or higher
Using System.Printing
var server = new PrintServer();
var queues = server.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });
foreach (var queue in queues)
{
string printerName = queue.Name;
string printerPort = queue.QueuePort.Name;
}
Check this question: How to get Printer Info in C#.NET?. I think that you have to get the property PortName from the WMI properties.
I know this is an old post, but I had the same issue where I was able to get the Printer Port name, but not the IP. In my case I couldn't rely on the Port Name being IP_[IP Address] but found how to get hold of the actual IP from the port name.
Windows stores the information about ports in the registry under
HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\[port name]
This key contains the values set up in the port configuration page, including IP address and port number.
A quick C# example to get the IP address
using Microsoft.Win32;
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"System\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\" + printerPortName, RegistryKeyPermissionCheck.Default, System.Security.AccessControl.RegistryRights.QueryValues);
if (key != null)
{
String IP = (String)key.GetValue("IPAddress", String.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
}
Using WIN32_Printer class is not enough here. It should be combined with Win32_TCPIPPrinterPort class.
Below is the code which should help:
static void Main(string[] args)
{
var scope = new ManagementScope(#"\root\cimv2");
scope.Connect();
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Printer");
var results = searcher.Get();
Console.WriteLine("Network printers list:");
foreach (var printer in results)
{
var portName = printer.Properties["PortName"].Value;
var searcher2 = new ManagementObjectSearcher("SELECT * FROM Win32_TCPIPPrinterPort where Name LIKE '" + portName + "'");
var results2 = searcher2.Get();
foreach (var printer2 in results2)
{
Console.WriteLine("Name:" + printer.Properties["Name"].Value);
//Console.WriteLine("PortName:" + portName);
Console.WriteLine("PortNumber:" + printer2.Properties["PortNumber"].Value);
Console.WriteLine("HostAddress:" + printer2.Properties["HostAddress"].Value);
}
Console.WriteLine();
}
Console.ReadLine();
}
string printerName = "POS-80C";
LocalPrintServer server = new LocalPrintServer();
PrintQueue printQueue = server.GetPrintQueue(printerName);
string portName = printQueue.QueuePort.Name;
string portNumber = "";
string hostAddress = "";
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_TCPIPPrinterPort where Name LIKE '" + portName + "'");
var results = searcher.Get();
foreach (var printer in results)
{
portNumber = (printer.Properties["PortNumber"].Value).ToString();
hostAddress = (printer.Properties["HostAddress"].Value).ToString();
}
Is this printer set up in a network which has Active Directory?
Or is this on your own local network with just a switch and your printer plugged into it?
If it is the former, then you should be able to query for it based on the "printer name". This article show how to get c# .net to connect to the AD. But this does require some knowledge of AD servers in your network.
This solution seems a bit long to me, but may be a good starting point?
Based on the link How to get Printer Info in .NET? (Thanks, Panos, I was already looking at the link!), I have the following solution from Panos's answer:
using System.Management;
...
string printerName = "YourPrinterName";
string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}'", printerName);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection coll = searcher.Get();
foreach (ManagementObject printer in coll)
{
string portName = printer["PortName"].ToString();
if(portName.StartsWith("IP_"))
{
Console.WriteLine(string.Format("Printer IP Address: {0}", portName.Substring(3)));
}
}
Obviously, this only works if the port name for the printer is given in the format "IP_IPAddress", which is I believe is the default.