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

В основном для C++Qt (Qt5.1) и C++ Builder (RAD 2009 и RAD XE3)
Рейтинг: 3.00. Голосов: 2.

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

Запись от Avazart размещена 01.10.2016 в 19:25
Обновил(-а) Avazart 04.03.2018 в 16:35


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

Размер: 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. Friend и Шаблоны: найти причины возникновения ошибок в коде и исправить эти ошибки
  3. Получение переменных окружения
  4. Перенаправление вывода при запуске процесса
  5. Консольное приложение и GUI C++
  6. Нужно-ли таскать драйверы при переносе программы?
Размещено в C++
Просмотров 1803 Комментарии 5
Всего комментариев 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 на форуме
    Обновил(-а) Avazart 16.05.2017 в 14:32
  5. Старый комментарий
    Аватар для Avazart
    Добавил пример с консолью.
    Запись от Avazart размещена 17.05.2017 в 22:51 Avazart на форуме
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru