Linq statement to retrieve printers with EnableBIDI = true
This should be an easy one for Linq guru's.
I wanna retrieve all the physical printers that are available to a user. As far as I can tell there is no property/setting that you can query whi开发者_如何学运维ch tells you whether a printer is a physical of a virtual one. But there's already a question about that topic : Is there a possibility to differ virtual printer from physical one?
I'm using a reliable-ish way to see if it's a virtual one, and I check whether the "EnableBIDI" property is set to true.
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection coll = searcher.Get();
var installedPhysicalPrinters = new List<string>();
var scratch = from ...
The result should be that the installedPhysicalPrinters contains a list of installedprinter names.
I got this far
foreach (ManagementObject printer in coll)
{
var validPrinter = (from PropertyData p in printer.Properties
from ManagementObject pr in coll
where p.Name == "EnableBIDI" && (bool) p.Value == true
select p).FirstOrDefault();
if (validPrinter != null)
{
installedPrinters.Add(validPrinter.Value.ToString());
// this is just to see the properties
foreach (PropertyData property in printer.Properties)
{
lstMessages.Items.Add(string.Format("{0}: {1}", property.Name, property.Value));
}
}
}
Obviously this is wrong, and I end up with a list of "true" values in the list, instead of the printer names.
Using nested for eaches it's easy to solve, but that's sooo 2004...
The issue with combining LINQ and System.Management is that the latter uses older non-generic containers (like ManagementObjectCollection) that you can't use directly with LINQ because it uses the non-generic IEnumerable interface.
Luckily you can work around that, as in the following example:
static void Main(string[] args)
{
Func<PropertyData, bool> indicatesPhysical = property => property.Name == "EnableBIDI"; // && (bool) property.Value;
Func<ManagementBaseObject, bool> isPhysicalPrinter = obj => obj.Properties.OfType<PropertyData>().Any(indicatesPhysical);
var searcher = new ManagementObjectSearcher("Select * from Win32_Printer");
var collection = searcher.Get();
var physicalPrinters = collection.OfType<ManagementBaseObject>().Where(isPhysicalPrinter);
foreach (var item in physicalPrinters)
{
Console.WriteLine(item.Properties["DeviceID"].Value);
Console.WriteLine(item.Properties["EnableBIDI"].Value);
}
}
You can use the Enumerable.OfType<>()
extension method to transform the specified IEnumerable
interface into an IEnumerable<ManagementBaaseObject>
. That will help in getting those queries along.
Your example on how to differentiate between physical and virtual printers didn't work on my end, but it's irrelevant to what the main problem is that you're dealing with, namely trying to make code more readable by using LINQ expressions.
精彩评论