Форум программистов, компьютерный форум, киберфорум
Avazart
Войти
Регистрация
Восстановить пароль
Темы блога относятся к программированию на языке С++

В основном для C++Qt (Qt5.1) и C++ Builder (RAD 2009 и RAD XE3)

Велосипеды (C++,WinApi)

Запись от Avazart размещена 01.10.2016 в 19:25
Показов 9414 Комментарии 5


Название: index.jpg
Просмотров: 8932

Размер: 10.6 Кб

Ссылка на исходники https://github.com/Avazart/Bicycle

Решил поделиться некоторыми своими велосипедами, подумал что возможно кому-то будет интересно взглянуть, а кто-то может еще и укажет на баги/недочеты.

Основа- классы:
  • Process
  • SerialPort
  • TcpClient
являющие собой обвертки над WinApi и Winsoсks.

Для этих классов есть специальный класс-поток TextStream позволяющий читать из объектов этих классов строки до разделителя(с буферизацией).

В нагрузку:
  • в паке Algorithm расположены алгоритмы для работы со строками split() и trim() (аналогичные boost/string/algorithm)
  • классы TcpServer и Console
  • вспомогательные классы для исключений, классы-обвертки над потоком, классы Any, Format, Library, пространство Path и прочие.

Process

Для работы класса Process в проект должны быть добавлены все файлы из папок Win/Common, Win/Process, Win/TextStream и файл Algorithm/Mismatch.h

Пример запуска системного калькулятора

C++
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
#include <iostream>
 
#include "Win/Process/Process.h"
 
int main()
{
    using namespace std;
    using namespace Bicycle;
    try
    {
        Process process;
        process.start(L"",L"calc"); // Запускаем калькулятор
        process.waitForInputIdle(); // Ждем готовности калькулятора
        cout<<"Process ready."<<endl;
 
        // Ждем 5 сек и закрываем программу
        Sleep(5000);
        process.closeWindows(); // Шлем WM_CLOSE окну
        process.waitForFinished(); // Ждем завершения калькулятора
        cout<<"Process finished with exit code #"<< process.exitCode() <<endl;
    }
    catch(const Exception& e)
    {
        SetConsoleCP(1251);
        SetConsoleOutputCP(1251);
        cerr<< e.message()<<endl;
    }
    getchar();
    return 0;
}


Пример чтения вывода утилиты ping


C++
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
#include <iostream>
 
#include "Win/Process/Process.h"
#include "Win/Process/Pipe.h"
 
int main()
{
  using namespace std;
  using namespace Bicycle;
  try
  {
    Process process;
    process.setInheritHandle(true);
    process.setSecurityInheritHandle(true);
    process.usePipes(true);
    process.start(L"",L"ping google.com");
 
    ServerPipe& pipe= process.stdOut();
    pipe.setTimeOut(30000);
 
    const size_t bufferSize= 256;
    char buffer[bufferSize]={'\0'};
    ulong length= 0;
    do
    {
      length= pipe.read(buffer,bufferSize);
      if(length)
        cout<< string(buffer,length);
    }
    while(length);
  }
  catch(const Exception& e)
  {
      SetConsoleCP(1251);
      SetConsoleOutputCP(1251);
      cerr<< e.message()<<endl;
  }
 
  getchar();
  return 0;
}


Пример с чтением и записью в пайп
C++
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
#include <iostream>
#include <algorithm>
 
#include "Win/Process/Process.h"
#include "Win/TextStream/TextStream.h"
 
int main(int argc, char *argv[])
{
  using namespace std;
  using namespace Bicycle;
 
  if(argc>1 && strcmp(argv[1],"-echo")==0) // эхо режим для дочернего.процесса
  {
    string line;
    while(getline(cin,line))
    {
      if(line=="quit")
        break;
 
      reverse(line.begin(),line.end()); // переворачиваем строку
      cout<<line<<endl;
    }
  }
  else// главный процесс
  {
    try
    {
      Process process;
 
      process.setInheritHandle(true);
      process.setSecurityInheritHandle(true);
      process.usePipes(true);
      // Запускаем себя с эхо режиме
      process.setCmdLine(appModuleFileName()+ L" -echo");
      process.start();
 
      TextStream inStream(&process.stdIn());
      TextStream outStream(&process.stdOut());
 
      string line;
      while(getline(cin,line))
      {
        inStream.writeLine(line);
        line= outStream.readLine();
        cout<<"""<< line<<""" << endl;
      }
    }
    catch(const Exception& e)
    {
        SetConsoleCP(1251);
        SetConsoleOutputCP(1251);
        cerr<< e.message()<<endl;
    }
    getchar();
  }
  return 0;
}


Пример работы с окружением(переменными среды)
C++
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
#include <iostream>
 
#include "Win/Process/Process.h"
#include "Win/Process/Environment.h"
#include "Win/TextStream/TextStream.h"
 
using namespace std;
using namespace Bicycle;
 
// --------------------------------------------------------------------------
void print(const Environment& env)
{
  for (size_t i= 0; i< env.strings().size(); ++i)
    wcout<< env.strings()[i]<< std::endl;
}
// --------------------------------------------------------------------------
int main(int argc, char* [])
{
  setlocale(LC_ALL, "");
  try
  {
    if(argc==1)
       ProcessEnvironment::setVariable(L"MyVAR3",L"MyValue3.1");
 
    Environment env= ProcessEnvironment::environment();
 
    print(env);
 
    if(argc==1)
    {
      Process process;
      env.appendVariable(L"MyVAR1", L"MyValue1");
      env.appendVariable(L"MyVAR2", L"MyValue2");
      env.setVariable(L"MyVar3",env.variable(L"MyVaR3")+L";MyValue3.2");
 
      process.setEnvironment(env);
      process.setShowWindow(SW_NORMAL);
      process.setCreationFlags(process.creationFlags()|CREATE_NEW_CONSOLE);
      process.setCmdLine(appModuleFileName()+ L" -arg");
      process.start();
 
      wcout<< endl<< L"Create children process..."<< endl;
      process.waitForFinished();
      wcout<<"Children process finished with exit code: "<< process.exitCode()<<endl;
    }
  }
  catch (const SystemException& e)
  {
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    cerr<< e.message()<< endl;
  }
 
  getchar();
  return 0;
}
// --------------------------------------------------------------------------


SerialPort

Для работы класса Process в проект должны быть добавлены все файлы из папок Win/Common, Win/Serial, , Win/TextStream и файлы Algorithm/Trim.h и Algorithm/IsAnyOf.h

Пример построчного чтения из COM-порта
C++
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
#include <iostream>
 
#include "Win/Serial/SerialPort.h"
#include "Win/TextStream/TextStream.h"
 
int main()
{
  using namespace std;
  using namespace Bicycle;
  try
  {
    SerialPort serial;
    serial.setPortName(L"COM9");
    serial.setTimeOut(60000);
    serial.setBaudRate(CBR_9600);
    serial.open();
    serial.waitEvent();
 
    TextStream stream(&serial);
    while(true)
    {
      string line= stream.readLine();
      cout<<"""<<line<<"""<<endl;
    }
  }
  catch(const Exception& e)
  {
      SetConsoleCP(1251);
      SetConsoleOutputCP(1251);
      cerr<< e.message()<<endl;
  }
 
  getchar();
  return 0;
}


Получение списка доступных COM-портов и информации о них
C++
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
#include <iostream>
#include <vector>
 
#include "Win/Serial/SerialPortInfo.h"
#include "Win/Common/Exception.h"
 
int main()
{
  using namespace std;
  using namespace Bicycle;
 
  setlocale(0,""); // Обязательно иначе будут проблемы
                   // с описанием устройств в кириллице
  try
  {
    // Перечисляем доступные COM-порты и выводим информацию о них:
    vector<SerialPortInfo> ports;
    if(SerialPortInfo::availablePorts(ports))
    {
        for(size_t i=0; i<ports.size(); ++i)
        {
          wcout<< L"port name: " << ports[i].portName() << endl;
          wcout<< L"hardware ids: "<< ports[i].hardwareIds()<< endl;
          wcout<< L"vid: "<<hex << ports[i].parseId(L"vid_")<< endl;
          wcout<< L"pid: "<<hex << ports[i].parseId(L"pid_")<< endl;
          wcout<< L"manufacturer:" <<ports[i].manufacturer()<< endl;
          wcout<< L"description: "<< ports[i].description() << endl;
          wcout<< L"friendly name: "<<ports[i].friendlyName()<< endl;
          wcout<< L"class guid: "<<ports[i].classGuid()<< endl;
          wcout<<endl;
        }
    }
  }
  catch(const Exception& e)
  {
      SetConsoleCP(1251);
      SetConsoleOutputCP(1251);
      cerr<< e.message()<<endl;
  }
 
  getchar();
  return 0;
}


Console

Кликните здесь для просмотра всего текста
C++
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
#include <iostream>
 
#include "Win/Console/Console.h"
 
using namespace std;
using namespace Bicycle;
 
 
void progress(int line,int maxCount);
 
int main()
{
  try
  {
    // Меняем кодировку
    Console::changeCp(1251);
 
    // Меняем цвет текста и фона.
    Console::setTextAttr(ConsoleColor::blue,ConsoleColor::red);
    cout<<"Hello";
    Console::setTextAttr(ConsoleColor::lime,ConsoleColor::yellow);
    cout<<"world!"<<endl;
    Console::setTextAttr(ConsoleColor::lime);
 
    // Получаем/изменяем заголовок окна консоли.
    wcout <<L"Title: "<<Console::title() << endl;
    Console::setTitle(Console::originalTitle()+L" - Hello world!");
 
    // Пример изменение шрифта
    ConsoleFont font = Console::font();
    cout <<"Font Size: "<<font.size().X<<"*"<< font.size().Y<<endl;
    wcout<<"Font Name: "<<font.faceName()<<endl;
    font.setSize(8,13);
    font.setFaceName(L"Lucida Console");
    Console::setFont(font);
 
    // Консольный прогресс бар - пример использование передвижение курсора
    Console::setTextAttr(ConsoleColor::blue);
    progress(4,50);
 
    // Очистка консоли  
    Console::clear();
  }
  catch(const SystemException& e)
  {
    cout<< e.message() << endl;
  }
  return 0;
}
 
void progress(int line, int maxCount)
{
  cout<< "[";
  Console::setCursorPos(maxCount+1,line);
  cout<< "]";
  Console::setCursorPos(1,line);
 
  int a= 1;
  int b= maxCount;
  int k= +1;
  int i= a;
 
  for(int s=3; s>0; --s)
  {
    for(; i>=a && i<=b; i+=k)
    {
      Console::setCursorPos(i,line);
      cout<< (k>0?"#":" ");
      Sleep(s*100);
    }
    k*= -1;
    i+= k;
    Sleep(100);
  }
}



Темы:
  1. Окно DOS (cmd) в окне программы
  2. E2199 QUESTIONABLE!!! Template friend function must be previously declared
  3. Получение переменных окружения
  4. Перенаправление вывода при запуске процесса
  5. Консольное приложение и GUI C++
  6. Нужно-ли таскать драйверы при переносе программы?
Размещено в C++
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 5
Комментарии
  1. Старый комментарий
    Аватар для keltor
    Спасибо за велосипеды. А то лень изобретать. Украду пару строчек кода
    Запись от keltor размещена 12.05.2017 в 17:19 keltor вне форума
  2. Старый комментарий
    Аватар для Avazart
    Не за что.
    Украду пару строчек кода
    А что именно если не секрет?
    Запись от Avazart размещена 13.05.2017 в 13:18 Avazart вне форума
  3. Старый комментарий
    Аватар для keltor
    Если честно, то украл всё. На всякий случай. Часто изобретаю велосипеды, а потом оказывается всё давно придумано и красиво написано.
    Запись от keltor размещена 15.05.2017 в 16:11 keltor вне форума
  4. Старый комментарий
    Аватар для Avazart
    Да я бы советовал использовать другие либы, но иногда от велосипедописания не уйти.
    К примеру если используешь Qt там есть классы и QProcess и QSerialPort и не нужно ничего изобретать. Но не всегда допустимо тянуть кучу длл от Qt иногда необходим компактный экзешник чисто под винду.

    Если используешь С++Builder или MSVC то там нет ничего для работы с процессами...

    Для работы с COM-портом для C++Builder лучше использовать сторонний компонент BComPort (правда там нет построчного чтения, но это мелочи)

    Все остальные мои велосипеды писались скорее для теста, а не практического использования.
    (и находятся в худшем состоянии)
    Запись от Avazart размещена 15.05.2017 в 18:36 Avazart вне форума
  5. Старый комментарий
    Аватар для Avazart
    Добавил пример с консолью.
    Запись от Avazart размещена 17.05.2017 в 22:51 Avazart вне форума
 
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru