2015-12-08 35 views
6

Windowsユニバーサルアプリケーションでシリアルポートを使用しようとしています。私はテンプレートとしてマイクロソフトのシリアルサンプルアプリケーションを使用していますが、私はかなり奇妙な問題にぶつかりました。Windowsユニバーサルアプリケーションのシリアルポートが開かない、SerialDevice.FromIdAsyncが常にヌル

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

これは失敗しているスニペットです。特定のベンダーの最初のデバイスに接続するとき、元のサンプルからわずかに変更されます。今私はこのスニペットを取って、マイクロソフトが作成したサンプルアプリケーションに入れれば、シリアルポートが開き、すべてがうまくいきます。しかし、このコードを自分のプロジェクトに移すと、メソッドから常にnullが返されます。

ここでは、私の警告でMicrosoftサンプルのMainPage.xaml.csが完全にあります。 この作品は!!

// 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()の最初の2行は、テスト前と同じですが、SerialDevice.FromIdAsync(dis[0].id);は常にnullです。 これは動作しません!

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のバージョンのようなものをチェックし、すべてが同じに見えてきました。また、管理者としてVSを実行しているようなものをチェックして、私は両方のアプリケーションを同時に開くことができませんでしたので、ポートが開いているか何かを保持する必要がありません...

誰にもアイデアはありますか?

答えて

17

マイクロソフトでは、シリアル通信のためのアプリケーションマニフェストに何かを追加する必要はなく、シリアル通信のためのアプリケーションマニフェストGUIにもチェックボックスがあります。

以下のニーズがアプリのマニフェストに追加する(それが存在しない場合は<Capabilities>セクションを作成):2016分の10

マイクロソフトがに自分のドキュメントを更新しました

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

UPDATEこの要件を反映しています。

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

+1

おかげで - 私はまた、これに多くの時間を無駄にし、あなたの答えは私を救いました。 –

+3

私はもっと駄目だと信じています:) –

+0

あなたは[このドキュメント](https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.aspx) SerialDevice msdn documentation](https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.serialdevice.aspx) –

関連する問題