Windows通用应用程序串行端口将不会打开,SerialDevice.FromIdAsync始终为空

我正在尝试使用Windows通用应用程序中的串行端口。 我一直在使用微软的Serial Sample应用程序作为模板,但是我遇到了一个相当奇怪的问题。

var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A)); var sp = await SerialDevice.FromIdAsync(dis[0].Id); 

这是一个失败的片段。 它与原始样本稍有不同,因为它与特定供应商连接到第一个设备。 现在,如果我把这个代码片段放到Microsoft生成的示例应用程序中,串口就会打开,并且一切都很好。 但是,当我把这个代码移到我自​​己的项目中时,它总是从方法中返回null

这里是从微软示例完整的MainPage.xaml.cs与我的aleures: 这工程!

 // Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.Devices.Enumeration; using Windows.Devices.SerialCommunication; using Windows.Storage.Streams; using System.Threading; using System.Threading.Tasks; namespace SerialSample { public sealed partial class MainPage : Page { /// <summary> /// Private variables /// </summary> private SerialDevice serialPort = null; DataWriter dataWriteObject = null; DataReader dataReaderObject = null; private ObservableCollection<DeviceInformation> listOfDevices; private CancellationTokenSource ReadCancellationTokenSource; public MainPage() { this.InitializeComponent(); comPortInput.IsEnabled = false; sendTextButton.IsEnabled = false; listOfDevices = new ObservableCollection<DeviceInformation>(); ListAvailablePorts(); } /// <summary> /// ListAvailablePorts /// - Use SerialDevice.GetDeviceSelector to enumerate all serial devices /// - Attaches the DeviceInformation to the ListBox source so that DeviceIds are displayed /// </summary> private async void ListAvailablePorts() { try { string aqs = SerialDevice.GetDeviceSelector(); var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A)); serialPort = await SerialDevice.FromIdAsync(dis[0].Id); status.Text = "Select a device and connect"; for (int i = 0; i < dis.Count; i++) { listOfDevices.Add(dis[i]); } DeviceListSource.Source = listOfDevices; comPortInput.IsEnabled = true; ConnectDevices.SelectedIndex = -1; try { // Disable the 'Connect' button comPortInput.IsEnabled = false; // Configure serial settings serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000); serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 9600; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None; // Display configured settings status.Text = "Serial port configured successfully: "; status.Text += serialPort.BaudRate + "-"; status.Text += serialPort.DataBits + "-"; status.Text += serialPort.Parity.ToString() + "-"; status.Text += serialPort.StopBits; // Set the RcvdText field to invoke the TextChanged callback // The callback launches an async Read task to wait for data rcvdText.Text = "Waiting for data..."; // Create cancellation token object to close I/O operations when closing the device ReadCancellationTokenSource = new CancellationTokenSource(); // Enable 'WRITE' button to allow sending data sendTextButton.IsEnabled = true; Listen(); } catch (Exception ex) { status.Text = ex.Message; comPortInput.IsEnabled = true; sendTextButton.IsEnabled = false; } } catch (Exception ex) { status.Text = ex.Message; } } /// <summary> /// comPortInput_Click: Action to take when 'Connect' button is clicked /// - Get the selected device index and use Id to create the SerialDevice object /// - Configure default settings for the serial port /// - Create the ReadCancellationTokenSource token /// - Start listening on the serial port input /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void comPortInput_Click(object sender, RoutedEventArgs e) { var selection = ConnectDevices.SelectedItems; if (selection.Count <= 0) { status.Text = "Select a device and connect"; return; } DeviceInformation entry = (DeviceInformation)selection[0]; try { serialPort = await SerialDevice.FromIdAsync(entry.Id); // Disable the 'Connect' button comPortInput.IsEnabled = false; // Configure serial settings serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000); serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 9600; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None; // Display configured settings status.Text = "Serial port configured successfully: "; status.Text += serialPort.BaudRate + "-"; status.Text += serialPort.DataBits + "-"; status.Text += serialPort.Parity.ToString() + "-"; status.Text += serialPort.StopBits; // Set the RcvdText field to invoke the TextChanged callback // The callback launches an async Read task to wait for data rcvdText.Text = "Waiting for data..."; // Create cancellation token object to close I/O operations when closing the device ReadCancellationTokenSource = new CancellationTokenSource(); // Enable 'WRITE' button to allow sending data sendTextButton.IsEnabled = true; Listen(); } catch (Exception ex) { status.Text = ex.Message; comPortInput.IsEnabled = true; sendTextButton.IsEnabled = false; } } /// <summary> /// sendTextButton_Click: Action to take when 'WRITE' button is clicked /// - Create a DataWriter object with the OutputStream of the SerialDevice /// - Create an async task that performs the write operation /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void sendTextButton_Click(object sender, RoutedEventArgs e) { try { if (serialPort != null) { // Create the DataWriter object and attach to OutputStream dataWriteObject = new DataWriter(serialPort.OutputStream); //Launch the WriteAsync task to perform the write await WriteAsync(); } else { status.Text = "Select a device and connect"; } } catch (Exception ex) { status.Text = "sendTextButton_Click: " + ex.Message; } finally { // Cleanup once complete if (dataWriteObject != null) { dataWriteObject.DetachStream(); dataWriteObject = null; } } } /// <summary> /// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream /// </summary> /// <returns></returns> private async Task WriteAsync() { Task<UInt32> storeAsyncTask; if (sendText.Text.Length != 0) { // Load the text from the sendText input text box to the dataWriter object dataWriteObject.WriteString(sendText.Text); // Launch an async task to complete the write operation storeAsyncTask = dataWriteObject.StoreAsync().AsTask(); UInt32 bytesWritten = await storeAsyncTask; if (bytesWritten > 0) { status.Text = sendText.Text + ", "; status.Text += "bytes written successfully!"; } sendText.Text = ""; } else { status.Text = "Enter the text you want to write and then click on 'WRITE'"; } } /// <summary> /// - Create a DataReader object /// - Create an async task to read from the SerialDevice InputStream /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void Listen() { try { if (serialPort != null) { dataReaderObject = new DataReader(serialPort.InputStream); // keep reading the serial input while (true) { await ReadAsync(ReadCancellationTokenSource.Token); } } } catch (Exception ex) { if (ex.GetType().Name == "TaskCanceledException") { status.Text = "Reading task was cancelled, closing device and cleaning up"; CloseDevice(); } else { status.Text = ex.Message; } } finally { // Cleanup once complete if (dataReaderObject != null) { dataReaderObject.DetachStream(); dataReaderObject = null; } } } /// <summary> /// ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task ReadAsync(CancellationToken cancellationToken) { Task<UInt32> loadAsyncTask; uint ReadBufferLength = 1024; // If task cancellation was requested, comply cancellationToken.ThrowIfCancellationRequested(); // Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available dataReaderObject.InputStreamOptions = InputStreamOptions.Partial; // Create a task object to wait for data on the serialPort.InputStream loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken); // Launch the task and wait UInt32 bytesRead = await loadAsyncTask; if (bytesRead > 0) { rcvdText.Text = dataReaderObject.ReadString(bytesRead); status.Text = "bytes read successfully!"; } } /// <summary> /// CancelReadTask: /// - Uses the ReadCancellationTokenSource to cancel read operations /// </summary> private void CancelReadTask() { if (ReadCancellationTokenSource != null) { if (!ReadCancellationTokenSource.IsCancellationRequested) { ReadCancellationTokenSource.Cancel(); } } } /// <summary> /// CloseDevice: /// - Disposes SerialDevice object /// - Clears the enumerated device Id list /// </summary> private void CloseDevice() { if (serialPort != null) { serialPort.Dispose(); } serialPort = null; comPortInput.IsEnabled = true; sendTextButton.IsEnabled = false; rcvdText.Text = ""; listOfDevices.Clear(); } /// <summary> /// closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on /// - Cancel all read operations /// - Close and dispose the SerialDevice object /// - Enumerate connected devices /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void closeDevice_Click(object sender, RoutedEventArgs e) { try { status.Text = ""; CancelReadTask(); CloseDevice(); ListAvailablePorts(); } catch (Exception ex) { status.Text = ex.Message; } } } } 

这下一个块如果从我的代码。 ConnectToSerialPort()中的前两行与之前的testing相同,但SerialDevice.FromIdAsync(dis[0].id); 始终为空。 这不行!

 using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using Windows.Devices.Enumeration; using Windows.Devices.SerialCommunication; using Windows.Storage.Streams; using Windows.UI.Xaml.Controls; namespace OpenLab.Kitchen.Receiver { public sealed partial class MainPage : Page { private List<byte> Bytes { get; set; } public MainPage() { this.InitializeComponent(); Bytes = new List<byte>(); ConnectToSerialPort(); } private async void ConnectToSerialPort() { var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A)); var sp = await SerialDevice.FromIdAsync(dis[0].Id); Debug.WriteLine(sp.UsbVendorId); DeviceInformationCollection serialDevices; while ((serialDevices = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A))).Count < 1) { Debug.WriteLine("Unable to locate..."); } SerialDevice serialPort; while ((serialPort = await SerialDevice.FromIdAsync(serialDevices[0].Id)) == null) { Debug.WriteLine("Failed to open serial port..."); } serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000); serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 9600; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None; var dataReader = new DataReader(serialPort.InputStream); var buffer = new byte[1024]; while (true) { var bytesRead = await dataReader.LoadAsync((uint)buffer.Length); dataReader.ReadBytes(buffer); Bytes.AddRange(buffer.Take((int)bytesRead)); byte[] slipPacket; while ((slipPacket = Slip.ExtractSlipPacket(Bytes)) != null) { var waxPacket = WaxPacketConverter.FromBinary(slipPacket, DateTime.Now); if (waxPacket != null) { Debug.WriteLine(waxPacket); } } } } } } 

我已经检查了所有的清单权限来匹配它们,并检查像引用的DLL版本的东西,一切看起来都是一样的。 还检查像pipe理员的VS运行的东西,我没有同时打开这两个应用程序,所以它不应该保持端口打开或任何东西…

有没有人有任何想法?

所以微软并没有提到你需要为应用程序清单添加一些东西来进行串行通信,也没有在应用程序清单GUI中用于串行通信的勾选框。

需要将以下内容添加到应用清单(如果不存在,请创建<Capabilities>部分):

 <Capabilities> <DeviceCapability Name="serialcommunication"> <Device Id="any"> <Function Type="name:serialPort" /> </Device> </DeviceCapability> </Capabilities> 

更新10/2016

微软已经更新了他们的文档来反映这个要求。

https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.aspx