С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64

Функции DeviceIoControl: вытащить серийник с флешки, диска

20.02.2020, 11:53. Показов 2467. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Помогите пожалуйста с помощью функции DeviceIoControl и CreateFile вытащить серийник с флэшки, диска и тд.
Не понимаю как надо прописывать и как заставить работать между собой. Уже кучу информации изучил, а так ничего и не понял.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.02.2020, 11:53
Ответы с готовыми решениями:

Количество секторов, кластеров и серийник диска
необходимо определить кол-во секторов, кластеров, байт в кластере и серийник диска перерыл функции из серии " DriveInfo HardDisk =...

Модель и серийник жёсткого диска (WMI)
Всем привет. Помогите пожалуйста . Нужно "как-то" получить модель и серийник(но он не обязателен) харда. Как я понял единственный способ...

Копирование папки с флешки на компьютер при неизвестной букве диска у флешки
Здравствуйте, а подскажите пожалуйста, хочу скопировать папку с флешки на компьютер, как задать параметр копирования, если на разных...

19
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
20.02.2020, 12:28
Тут вроде рабочее решение
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
20.02.2020, 16:42  [ТС]
Там программа на борланде работает,а я работаю на dev c++ и поэтому мне тяжело найти примеры и код из борланда тяжело адаптировать собственно поэтому я и обращаюсь за помощью
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
20.02.2020, 17:01
Лучший ответ Сообщение было отмечено Crash7x как решение

Решение

Что там такого специфичного для борланда? Memo? Выкиньте его и всех делов.
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
#include <iostream>
#include <Winioctl.h>
 
void main(void)
{
    DWORD dwBytesReturned;
    STORAGE_PROPERTY_QUERY query;
    STORAGE_DEVICE_DESCRIPTOR *buffer;
 
    buffer = new STORAGE_DEVICE_DESCRIPTOR[5];
 
    HANDLE hDrive = CreateFile(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, 0, NULL);
 
    memset((void *)&query, 0, sizeof (query));
    memset((void *)buffer, 0, sizeof (buffer));
 
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyExistsQuery;
 
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyStandardQuery;
 
    DeviceIoControl(hDrive, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
        buffer, 500, &dwBytesReturned, NULL);
 
    if (buffer->VendorIdOffset != 0) {
        char *str = (char*)((char*)buffer + buffer->VendorIdOffset);
        cout << "VendorId: " << str << endl;
    }
    if (buffer->ProductIdOffset != 0) {
        char *str = (char*)((char*)buffer + buffer->ProductIdOffset);
        cout << "ProductId: " << str << endl;
    }
    if (buffer->ProductRevisionOffset != 0) {
        char *str = (char*)((char*)buffer + buffer->ProductRevisionOffset);
        cout << "ProductRevision: " << str << endl;
    }
    if (buffer->SerialNumberOffset != 0) {
        char *str = (char*)((char*)buffer + buffer->SerialNumberOffset);
        cout << "SerialNumber: " << str << endl;
    }
 
    CloseHandle(hDrive);
    delete[] buffer;
    
    system("pause");
}
1
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
20.02.2020, 17:13  [ТС]
почему то постоянно ругается на winioctl.h
In file included from
[Error] 'DWORD' does not name a type
[Error] 'BOOLEAN' does not name a type
и тд.
уже не раз сталкиваюсь и не могу понять что за ошибка
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
20.02.2020, 17:23
перед #include<winioctl.h> добавте #include <windows.h>
1
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
20.02.2020, 17:25  [ТС]
Спасибо большое, решил проблему включив #include <windows.h>. Совсем забыл про эту библиотеку.всё работает.
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
26.02.2020, 15:50  [ТС]
Ещё вопросик, а можно ли код выше заставить работать постоянно? А то оно сразу закрывается и не проверяет систему постоянно.
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
26.02.2020, 16:24
оберните код программы в while(!kbhit())
C++
1
2
3
4
5
6
7
8
9
10
#include <conio.h>
 
int main()
{
 while(!kbhit())
 {
   //... код программы
  }
 return 0;
}
Теперь программа будет завершаться по нажатию любой клавиши. Или так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <conio.h>
 
int main()
{
 while(true) // или for(;;) - кому что нравится
 {
   //... код программы
 
   if (kbhit())
   {
     char c = getch();
     if (c == 13)
      return 0;
  }
}
Так программа будет завершаться по нажатию Enter.
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
26.02.2020, 18:25  [ТС]
Annemesski, Так почему то у меня тоже самое не работало ,а ваш код заработал. Спасибо за код. И еще есть вопрос я добавил проверку на подключение флэшки:
C++
1
2
3
4
5
6
7
8
9
for (charRootPath[0] = 67; charRootPath[0] <= 90; charRootPath[0]++)
    {
        
      
        charRootPath[1] = 58;
        charRootPath[2] = 47;
       
        dt = GetDriveType(charRootPath);
        if ((dt == DRIVE_REMOVABLE) || (dt==DRIVE_FIXED))
но при запуске программы и во время ее работы есои подключить флэшку то он не обновляет информацию,почему? Извините за ранее за глупые вопросы просто пытаюсь разобраться что к чему и не понимаю.
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
27.02.2020, 11:37
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 <windows.h>
#include <winioctl.h>  
#include <conio.h>
#include <tchar.h>
 
using namespace std;
 
int main() {
    WCHAR drive[] = _T("A:\\");
    DWORD drivesBitMask = GetLogicalDrives();
    while (true)
    {
        DWORD drvPlugCheck = drivesBitMask ^ GetLogicalDrives();
        
        if (drvPlugCheck != 0)
        {
            while (drvPlugCheck >>= 1 != 0)
                drive[0]++;
            UINT dt = GetDriveType(LPCWSTR(drive));
            if (drivesBitMask < GetLogicalDrives() && (dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED))
                cout << "Drive \"" << (char)drive[0] << ":\" is PLUGGET" << endl;
            drivesBitMask = GetLogicalDrives();
        }
 
        if (kbhit())
        {
            char c = getch();
            if (c == 13)
                break;
        }
    }
    system("pause");
    return 0;
}
1
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
27.02.2020, 21:24  [ТС]
Annemesski, Выдает такие ошибки:
1. [Error] int-array initialized from non-wide string
Исправил:
C++
1
WCHAR drive[] = _T( L"A:\\");
2. [Error] cannot convert 'LPCWSTR {aka const wchar_t*}' to 'LPCSTR {aka const char*}' for argument '1' to 'UINT GetDriveTypeA(LPCSTR)'
Исправил:
C++
1
UINT dt = GetDriveTypeW(LPCWSTR(drive));
Но экран пустой хотя должен считать получается битовую маску и взять букву, а потом проверить букву и вывести буквы жестких и флэшек. Что не так не могу понять?
решил в начале написать cout чтоб проверить и всё равно экран пуст.

Добавлено через 1 час 20 минут
И если можно то приписать пояснения, а то вроде начинаю понимать как работает, но некоторые моменты не понятны. Заранее спасибо.

Добавлено через 2 часа 6 минут
Почему она не работает постоянно? Всё ищет и находит ,но не работает постоянно.Объясните пожалуйста!!!!
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
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
#include <iostream>
#include <windows.h>
#include <winioctl.h>  
#include <conio.h>
#include <tchar.h>
#include <Setupapi.h>
#include <stdio.h>
 
using namespace std; 
 
int main()
{
     while (true)
    {
    int stp=0;
    int chet=0;    
    char *SN;
    char *PID;          
    DWORD dwBytesReturned;
    STORAGE_PROPERTY_QUERY query;
    STORAGE_DEVICE_DESCRIPTOR *buffer;
 
    buffer = new STORAGE_DEVICE_DESCRIPTOR[5];
    setlocale (LC_ALL, "Rus"); 
    char charRootPath[10]={0};
    char FileName[10]={0};
    char FindDevice[10]={0};
    int i=0;
       bool bHave;
    UINT dt;
    // Initial Dummy drive
    char myDrives[] = "A:\\";  
 
      
    DWORD myDrivesBitMask = GetLogicalDrives();  
 
    
    if(myDrivesBitMask == 0)   
        wprintf(L"GetLogicalDrives() failed with error code: %d\n", GetLastError());  
    else  { 
        wprintf(L"This machine has the following logical drives:\n");   
        while(myDrivesBitMask)     {      
           
            if(myDrivesBitMask & 1)    {    
             cout<<"drive "<<myDrives<<endl; 
                    UINT dt = GetDriveType(LPCSTR(myDrives));
            if ( dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED){
            
                cout<<"drive "<<myDrives<<endl; 
                FileName[4]=myDrives[0];
        FileName[0] = 47;
        FileName[1] = 47;
        FileName[2] = 46;
        FileName[3] = 47;
        FileName[5] = 58; 
                HANDLE hDrive = CreateFile(FileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_EXISTING, 0, NULL);
 
    memset((void *)&query, 0, sizeof (query));
    memset((void *)buffer, 0, sizeof (buffer));
 
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyExistsQuery;
 
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyStandardQuery;
 
    DeviceIoControl(hDrive, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
        buffer, 500, &dwBytesReturned, NULL);
 
  
    if (buffer->ProductIdOffset != 0) {
        char *str = (char*)((char*)buffer + buffer->ProductIdOffset);
        PID=str;
    }
    if (buffer->SerialNumberOffset != 0) {
        char *str = (char*)((char*)buffer + buffer->SerialNumberOffset);
        SN=str;
    }
    stp=0;
    chet++;
    cout << "ProductId: " << PID << endl;
    cout << "SerialNumber: " << SN << endl;  
}
            } 
               
            // increment counter for the next available drive.   
            myDrives[0]++;    
            // shift the bitmask binary right    
            myDrivesBitMask >>= 1;   
        }   
        wprintf(L"\n");  
    }
      if (kbhit())
        {
            char c = getch();
            if (c == 13)
                break;
        }
}
    system("pause");
    return 0;   
}
Добавлено через 1 минуту
Срабатывает только один раз ,а мне надо мониторить комп и я не понимаю как это сделать, помогите!!!!
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
27.02.2020, 23:39
Почему она не работает постоянно? Всё ищет и находит ,но не работает постоянно.Объясните пожалуйста!!!!
Непонятно, вроде все норм, должно крутиться пока не нажмешь клавишу Enter

И если можно то приписать пояснения, а то вроде начинаю понимать как работает, но некоторые моменты не понятны. Заранее спасибо.
должен считать получается битовую маску и взять букву, а потом проверить букву и вывести буквы жестких и флэшек.
Что тут еще пояснять, все верно drvPlugCheck меняется если какой-то накопитель был подключен или отключен, drivesBitMask < GetLogicalDrives() - если текущая битовая маска больше предыдущей, значит какое-то устройство было подключено, если меньше, значит отключено.

Срабатывает только один раз ,а мне надо мониторить комп и я не понимаю как это сделать, помогите!!!!
Попробуйте для теста убрать эту часть:
C++
1
2
3
4
5
6
if (kbhit())
{
 char c = getch();
 if (c == 13)
  break;
}
Возможно дело в ней и надо будет переделать её не под простой Enter, а под сочетание клавиш.
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
28.02.2020, 12:30  [ТС]
Annemesski, Очень странную вещь заметил что на моем ноутбуке программа не крутит и завершается
,а попробовал на другом компе то там она крутит и не завершается. С чем это может быть связано?

Добавлено через 4 минуты
И в ходе экспериментов выяснилось что именно жесткий диск где винда во всем виноват
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
28.02.2020, 12:40
С чем это может быть связано?
на ноуте скорее всего уиезанная винда, эмбидед какой-нить, леший ее знает как она свои api предоставляет, может заглушки какие. Тут может помочь установка msvs redistributable
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
28.02.2020, 12:46  [ТС]
и почему то ваш код не работает у меня даже если исключить диск С
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 <windows.h>
#include <winioctl.h>  
#include <conio.h>
#include <tchar.h>
 
using namespace std;
 
int main() {
    WCHAR drive[] = _T("A:\\");
    DWORD drivesBitMask = GetLogicalDrives();
    while (true)
    {
        DWORD drvPlugCheck = drivesBitMask ^ GetLogicalDrives();
        
        if (drvPlugCheck != 0)
        {
            while (drvPlugCheck >>= 1 != 0)
                drive[0]++;
            UINT dt = GetDriveType(LPCWSTR(drive));
            if (drivesBitMask < GetLogicalDrives() && (dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED))
                cout << "Drive \"" << (char)drive[0] << ":\" is PLUGGET" << endl;
            drivesBitMask = GetLogicalDrives();
        }
 
        if (kbhit())
        {
            char c = getch();
            if (c == 13)
                break;
        }
    }
    system("pause");
    return 0;
}
А вот этот который я пробовал написать срабатывает хотя логика вашего кода лучше.не понимаю почему так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char myDrives[] = "A:\\";  
 
      
    DWORD myDrivesBitMask = GetLogicalDrives();  
 
    
    if(myDrivesBitMask == 0)   
        wprintf(L"GetLogicalDrives() failed with error code: %d\n", GetLastError());  
    else  { 
        wprintf(L"This machine has the following logical drives:\n");   
        while(myDrivesBitMask)     {      
           
            if(myDrivesBitMask & 1)    {    
             cout<<"drive "<<myDrives<<endl; 
                    UINT dt = GetDriveType(LPCSTR(myDrives));
            if ( dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED){
Добавлено через 7 секунд
и почему то ваш код не работает у меня даже если исключить диск С
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 <windows.h>
#include <winioctl.h>  
#include <conio.h>
#include <tchar.h>
 
using namespace std;
 
int main() {
    WCHAR drive[] = _T("A:\\");
    DWORD drivesBitMask = GetLogicalDrives();
    while (true)
    {
        DWORD drvPlugCheck = drivesBitMask ^ GetLogicalDrives();
        
        if (drvPlugCheck != 0)
        {
            while (drvPlugCheck >>= 1 != 0)
                drive[0]++;
            UINT dt = GetDriveType(LPCWSTR(drive));
            if (drivesBitMask < GetLogicalDrives() && (dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED))
                cout << "Drive \"" << (char)drive[0] << ":\" is PLUGGET" << endl;
            drivesBitMask = GetLogicalDrives();
        }
 
        if (kbhit())
        {
            char c = getch();
            if (c == 13)
                break;
        }
    }
    system("pause");
    return 0;
}
А вот этот который я пробовал написать срабатывает хотя логика вашего кода лучше.не понимаю почему так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char myDrives[] = "A:\\";  
 
      
    DWORD myDrivesBitMask = GetLogicalDrives();  
 
    
    if(myDrivesBitMask == 0)   
        wprintf(L"GetLogicalDrives() failed with error code: %d\n", GetLastError());  
    else  { 
        wprintf(L"This machine has the following logical drives:\n");   
        while(myDrivesBitMask)     {      
           
            if(myDrivesBitMask & 1)    {    
             cout<<"drive "<<myDrives<<endl; 
                    UINT dt = GetDriveType(LPCSTR(myDrives));
            if ( dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED){
0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,682
28.02.2020, 13:02
мой вариант реагирует только на подключение устроства
[CPP]
if (drivesBitMask < GetLogicalDrives() && (dt == DRIVE_REMOVABLE || dt == DRIVE_FIXED))
cout << "Drive \"" << (char)drive[0] << ":\" is PLUGGET" << endl;
drivesBitMask = GetLogicalDrives();/CPP]
добавьте
C++
1
2
else if (drivesBitMask > GetLogicalDrives())
 cout <<  "Drive \"" << (char)drive[0] << ":\" is UnPLUGGET" << endl;
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
28.02.2020, 13:32  [ТС]
Спасибо за помощь!!!
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
03.03.2020, 22:50  [ТС]
Появилась ещё одна проблемка. Вообщем использовал код (выше) на снятия серийника и проверку подключения и обнаружил что данный код работает только на виндовс 10. То есть код запускается, но вместо серийника флэшки выдаёт только стрелочку вниз хотя PID видет то же самое и с жёсткими дисками, а вот запускаешь код на 10 винде то всё работает отлично. С чем это связано и как можно решить?
0
1 / 1 / 0
Регистрация: 22.04.2019
Сообщений: 64
04.03.2020, 12:22  [ТС]
Экспериментально выяснил что на виндовс 7 работает вывод жёстких и как я понимаю серийник не помещается в размеры. Маленькие серийники жёстких помещаются, а длинные выводит какую-то стреллчку вниз
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.03.2020, 12:22
Помогаю со студенческими работами здесь

не работают системные функции (DeviceIoControl) в Windows 7
Здравствуйте, я только учусь, так что просьба не ругаться. Стоит рэйд контроллер и система Сервер 2003, драйвер для рейда и программа для...

Использование функции DeviceIoControl с кодом IOCTL_SCSI_PASS_THROUGH
Всем доброго времени суток. Пытаюсь передать диску скази запрос для чтения памяти, но есть проблемы: при использовании логического...

Как вытащить файлы с флешки SanDisk
Друзья, всем привет! Нужен совет и помощь. micro SD SanDisk Ultra перестала работать. При подключении: 1) Букву присвает флешке. ...

Как вытащить инфу с флешки с нарушенной файловой системой
Здравствуйте! Есть флешка на 8 Гб с кучей всяких НУЖНЫХ документов. Подскажите как их оттуда вытащить. R-studio, R.saver не помогают. В...

Не устанавливается Windows 7 ни с флешки, ни с диска
Всем доброго времени суток! Ситуация такая - взяли недавно вот такой ноутбук,заранее была установлена W8. Решил снести на 7-ку и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru