Search code examples
c#serial-portwin-universal-appclass-librarywindows-10-iot-core

Using Windows UWP Windows.Devices.SerialCommunication.SerialDevice from Universal Class library


I'm making a Modbus library (again...). This time it is meant to run on Windows 10 IoT Core.

I've encountered an interesting problem. This chunk of code:

string aqs = SerialDevice.GetDeviceSelector();
var dis = await DeviceInformation.FindAllAsync(aqs);

var port = await SerialDevice.FromIdAsync(dis[0].Id);

if (port != null) {
    port.BaudRate = 9600;
    port.DataBits = 8;
    port.StopBits = SerialStopBitCount.One;
    port.Parity = SerialParity.None;
    port.Handshake = SerialHandshake.None;
    port.ReadTimeout = TimeSpan.FromMilliseconds(1000);
    port.WriteTimeout = TimeSpan.FromMilliseconds(1000);
}
  1. Used from within a Universal App works perfectly. Of course if you add following code to Package.appxmanifest:

    <Capabilities>
         <DeviceCapability Name="serialcommunication">
             <Device Id="any">
                 <Function Type="name:serialPort" />
             </Device>
         </DeviceCapability>
     </Capabilities>
    
  2. Used from within Universal Class Library (File -> New Project -> ... -> Windows -> Universal -> Class Library (Universal Windows) in VS2015) creates Null Reference Exception from mscorlib.dll, which is same as if you remove DeviceCapability from Universal app's Package.appxmanifest.

I suspect that this behaviour has something to do with Class Library not having manifest file and therefore not having appropriate permissions.

Can I use Windows.Devices.SerialCommunication from within class libraries?

Is Microsoft making me tell the users 'Hey! I made for you a useless library for which you have to implement transport layer by yourself in any of your applications separately.' ?


Solution

  • I created a Universal app project and a Universal Class Library using Visual Studio 2015 Update 1 on Windows 10 10586. I setup the app manifest, put the SerialDevice code in the librairie and call it from the app.

    It works.

    Be careful if your code is called twice, you might get a null reference exception as port2 will be null.

    var aqs = SerialDevice.GetDeviceSelector();
    var dis = await DeviceInformation.FindAllAsync(aqs);
    var port = await SerialDevice.FromIdAsync(dis[0].Id);
    Debug.WriteLIne(port?.PortName);
    var aqs2 = SerialDevice.GetDeviceSelector();
    var dis2 = await DeviceInformation.FindAllAsync(aqs);
    var port2 = await SerialDevice.FromIdAsync(dis[0].Id);
    //port2 will be null
    Debug.WriteLine(port2?.PortName);