LoginSignup
0
0

com0comで作成したポートがCOM10以上であることを失念していた

Posted at

前置き

kernel32.dllのCreateFileでシリアル接続しているコードがあったので、勉強ついでにSystem.IO.Ports.SerialPortに置き換えようとしていた
COMポートはcom0comで用意したCOM11,COM12の2ポートを用いる
SerialPortでは難なくテストができたのにCreateFileではなぜかポートが見つからない、という初歩的な問題が発生していた

結論

上記に則ってprefixを与えるだけ。初歩的ですね…

ポート名
 portName = "\\\\.\\COM11";

com0comのReadMeにもそんなようなことが書いてあるという

Q. The HyperTerminal test succeeds, but I get a failure when trying to open the port with CreateFile("CNCA0", ...). GetLastError() returns ERROR_FILE_NOT_FOUND.
A. You must prefix the port name with the special characters "\\.\". Try to open the port with CreateFile("\\\\.\\CNCA0", ...).

SerialPortの実装

特に上記のようなprefixなしにSerialPortは接続できていたので多分内部的につけてくれているのだろうと思って確認すると、付けてくれている
ただしポート番号のみで判断しているのでCOM**という名前のポートしか扱えなくなっている模様
ポート名を自由に定義してる場合は面倒ですね

// SerialStream.Windows.cs
internal SerialStream(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits, int readTimeout, int writeTimeout, Handshake handshake,
            bool dtrEnable, bool rtsEnable, bool discardNull, byte parityReplace)
        {
            ArgumentNullException.ThrowIfNull(portName);

            if (!portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase) ||
                !uint.TryParse(
#if NETCOREAPP
                    portName.AsSpan(3),
#else
                    portName.Substring(3),
#endif
                    out uint portNumber))
            {
                throw new ArgumentException(SR.Format(SR.Arg_InvalidSerialPort, portName), nameof(portName));
            }

            // Error checking done in SerialPort.

            SafeFileHandle tempHandle = OpenPort(portNumber);
        // 以下略
        }

// SerialStream.Win32.cs
namespace System.IO.Ports
{
    internal sealed partial class SerialStream
    {
        private static SafeFileHandle OpenPort(uint portNumber)
        {
            return Interop.Kernel32.CreateFile(
                @"\\?\COM" + portNumber.ToString(CultureInfo.InvariantCulture),
                Interop.Kernel32.GenericOperations.GENERIC_READ | Interop.Kernel32.GenericOperations.GENERIC_WRITE,
                FileShare.None, // comm devices must be opened w/exclusive-access
                FileMode.Open,  // comm devices must use OPEN_EXISTING
                Interop.Kernel32.FileOperations.FILE_FLAG_OVERLAPPED);
        }
    }
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0