Jaa


Don’t trust your TCP/IP printer’s status

I recently ran into an issue with a customer who was experiencing an unstable experience querying for the System.Devices.Connected property of a printer from a Windows Store app. The printer was configured using a Standard TCP/IP port (For information on how to configure a printer via a Standard TCP/IP port, see the Note below).

This behavior explained below is by design and a long standing limitation issue of a printer that has been configured using a Standard TCP port.

Typically a Windows Store app would use the approach to enumerate devices (especially the Printer scenario) as mentioned here: https://msdn.microsoft.com/library/windows/apps/hh872189.aspx and then modify the code in the try{…} block of EnumerateDeviceInterfaces function of that sample with the following C# code to check for the “liveness” information.

 var selector = "System.Devices.InterfaceClassGuid:=\"" + InterfaceClassGuid.Text + "\"";
                 // + " AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True";
 var interfaces = await DeviceInformation.FindAllAsync(selector, /*null*/ new string[] { "System.Devices.ContainerId", "System.Devices.InterfaceEnabled" });
 var item = "";
 foreach (DeviceInformation deviceInterface in interfaces)
 {
     PnpObject containerInfo = await PnpObject.CreateFromIdAsync(
                                 PnpObjectType.DeviceContainer,
                                 "{" + deviceInterface.Properties["System.Devices.ContainerId"].ToString() + "}",
                                 new string[] { "System.Devices.Connected" });
     item = deviceInterface.Name + " and IsEnabled:\n" + deviceInterface.IsEnabled;
     item += string.Format("\nSystem.Devices.InterfaceEnabled:{0}", deviceInterface.Properties["System.Devices.InterfaceEnabled"]);
     item += string.Format("\nSystem.Devices.Connected:{0}", containerInfo.Properties["System.Devices.Connected"]);
 }

 

The approach used in the above code is to:

1. Find two additional properties called System.Devices.ContainerId and System.Devices.InterfaceEnabled.

2. Once the DeviceInformation is found, there is a call to PnpObject.CreateFromIdAsync(…)

3. With the retrieved PnpObject, the System.Devices.Connected property is used to find whether the printer is “Connected” or “Disconnected”

The issue is that if a TCP/IP printer is disconnected from the network, and the spooler service is restarted, initially the Windows Store app shows the status of the printer: System.Devices.Connected property as false – which is correct.

But if the same property is checked after a short while again, the property returns back the value of IsConnected to be “true” even though the printer is disconnected.

The expected result should be that if the printer is disconnected, the System.Devices.Connected property should return false and so should the System.Devices.InterfaceEnabled.

This happens to be a problem only with a printer that has been added using “Standard TCP/IP Port” and the “SNMP status enabled” is checked for the port.

Note: To add a Printer using a Standard TCP/IP port, you would go to Control Panel --> Devices and Printers --> Add a printer --> The printer that I want isn’t listed –> Add a printer using a TCP/IP address or hostname.

The cause of the issue is because the MSDN documentation for PnpObject.CreateFromIdAsync: https://msdn.microsoft.com/en-us/library/windows/apps/br225506 clearly states that it creates a PnpObject asynchronously from a previously saved DeviceInformation ID.

However, printers connected to TCP ports do not have liveness information, because TCP/IP port devices do not update any properties with regards to liveness and information is returned from old/ previously saved state.

Comments are welcome, both below and on twitter: #WSDevSol