Bonjour,

Je suis à la recherche d'un moyen de connaître la totalité des ports COM présents sur un ordinateur.

J'ai trouvé un code me permettant d'ouvrir un port COM et de pouvoir écrire dessus, de là, j'ai élaboré le début d'une classe me permettant de gérer plus facilement ces différents ports.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef HEADER_SERIALPORT
#define HEADER_SERIALPORT
#include <Windows.h>
#include <string>
#include <sstream>
 
class SerialPort
{
public:
	SerialPort();
	~SerialPort();
	/* Exception possible de type std::string*/
	void Open(std::string port="COM3",unsigned int baudrate=9600,int timeout=-1);
	/* Exception possible de type std::string*/
	void Close();
	std::string getPortName() const;
	unsigned int getBaudrate() const;
	void setBaudrate(unsigned int baudrate);
	int getTimeout() const;
	void setTimeout(int timeout);
	void WriteComFile(std::string File);
	std::string ReadComFile();
	std::string WriteAndReadComFile(std::string File);
    static bool CheckForPort(int i);
protected:
	std::string portName;
	unsigned int baudrate;
	int timeout;
	char szBuffer[80];
	DCB dcb;
	DWORD dwRead, dwWritten;
	HANDLE hComm;
	OVERLAPPED ovlr, ovlw;
	COMMTIMEOUTS cto;
	#define intimeout 1000//ms (attente entre chaque caratère --> attente a la fin de transmission)
	//pour une application à 9600 bauds, 2ms sont suffisantes pour détécter la fin (1,04 ms entre chaque octet).
    //10bits par octet (stop + start)
};
#endif
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "SerialPort.h"
using namespace std;
 
/* Constructeur
 * Initialise les paramètres
 */
SerialPort::SerialPort(): dcb(),ovlr(),ovlw(),cto(),portName(""),baudrate(0),timeout(0){
}
 
/* Destructeur
 * referme le port si nécéssaire
 */
SerialPort::~SerialPort(){
	if(GetCommState(hComm,&dcb))CloseHandle(hComm);
}
 
/* Ouvre le port voulu
 * Defaut :
 * COM3 (modem)
 * 9600 bauds
 * pas de timeout
 * Exception possible de type std::string
 */
void SerialPort::Open(string portName,unsigned int baudrate, int timeout){
	if(!GetCommState(hComm, &dcb)){ //si pas deja ouvert
		this->portName=portName;
		this->baudrate=baudrate;
		this->timeout=timeout;
		ovlr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		ovlw.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		hComm = CreateFileA(this->portName.c_str(), GENERIC_READ | GENERIC_WRITE,
		0, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
		if(!GetCommState(hComm, &dcb)){
		throw string("Error : Unable to open "+this->portName);
		}
		dcb.BaudRate = this->baudrate;
		SetCommState(hComm, &dcb);
		// Set the timeout parameters nonsensically
		cto.ReadIntervalTimeout = intimeout; //entre chaque caract
		cto.ReadTotalTimeoutConstant =this->timeout;
		cto.ReadTotalTimeoutMultiplier = 1;
		cto.WriteTotalTimeoutConstant = -1; //pas de tm pour le moment
		cto.WriteTotalTimeoutMultiplier = -1;
		SetCommTimeouts(hComm, &cto);
	}
	else throw string("Warning : "+this->portName+" is already opened");
}
 
/* Ferme le port
 * Exception possible de type std::string
 */
void SerialPort::Close(){
	if(GetCommState(hComm, &dcb)){ //si pas deja ouvert
	CloseHandle(hComm);
	}
	else throw string("Warning : "+this->portName+" is already closed"); //port deja fermé
}
 
/*
 *Getter & setter
 */
std::string SerialPort::getPortName() const{
	return this->portName;
	}
 
unsigned int SerialPort::getBaudrate()const{
	return this->baudrate;
	}
 
void SerialPort::setBaudrate(unsigned int baudrate){
	this->baudrate=baudrate;
	dcb.BaudRate=this->baudrate;
	SetCommState(hComm, &dcb);
}
 
int SerialPort::getTimeout() const{
	return this->timeout;
}
 
/* Modifie le timeout [ms] (en lecture uniquement)
 * -1 = pas de timeout général (mais tjs le interval timeout des la reception d'un char)
 */
void SerialPort::setTimeout(int timeout){
	this->timeout=timeout;
	cto.ReadTotalTimeoutConstant = this->timeout;
	SetCommTimeouts(hComm, &cto);
}
 
/*
 * Ecriture sur le port
 */
void SerialPort::WriteComFile(string File){
	WriteFile(hComm, File.c_str(), strlen(File.c_str()), &dwWritten, &ovlw);
}
 
/*
 * Lecture sur le port
 */
string SerialPort::ReadComFile(){
	ReadFile (hComm, szBuffer, sizeof(szBuffer), &dwRead, &ovlr);
	GetOverlappedResult(hComm, &ovlr, &dwRead, true);
	szBuffer[dwRead] = 0;
	return szBuffer;
}
 
/*
 * Ecrire et attendre une lecture juste après
 */
string SerialPort::WriteAndReadComFile(string File){
	WriteComFile(File);
	return ReadComFile();
}
 
/*
 * Vérifier les ports disponnibles non ouverts
 */
bool SerialPort::CheckForPort(int i){
    bool state(false);
SerialPort S;
std::ostringstream oss;
oss << i;
std::string ComNumber = oss.str();
try{
    S.Open("COM"+ComNumber);
    S.Close();
    state=true;
    }
   catch(...){ //nothing to do ..
    }
    return state;
}
Dernièrement, pour une application que l'on m'a demandée de réaliser, je dois pouvoir déterminer les différents ports COM présents sur la machine même si ceux-ci sont déjà ouverts !

Or, dans la classe ci-dessus, la méthode que j'ai essayé d'implémenter pour faire cela (la dernière fonction) ne me renvoi que les ports disponibles fermés.

Par expérience, je sais qu'avec les windows form on à accès à la fonction static array<String^>^ GetPortNames() présente dans la classe SerialPort du namespace System::IO::Ports qui réalise exactement ce que je cherche et que donc cette opération est possible.

Néanmoins, dans mon application je n'utilise pas les windows form ni visual studio et je n'ai donc visiblement pas accès à cette classe.

Est-ce que vous auriez une solution simple à implémenter pour faire ce que je souhaite ?
Je précise que je ne suis pas informaticien et que je maîtrise assez mal l'API windows (notamment au niveau des HANDLE). Mais mon but premier n'est pas la compréhension de chaque ligne de code non plus.
Je vous remercie !!