Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/29: Рейтинг темы: голосов - 29, средняя оценка - 4.69
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176

Запуск .NET C# программы из памяти C++ приложения

13.07.2017, 00:24. Показов 5788. Ответов 31

Студворк — интернет-сервис помощи студентам
Понадобилось реализовать запуск .NET C# программы прямо из памяти C++ приложения.
Использую функцию:
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
BOOL ExecFile(LPWSTR szFilePath, LPVOID pFile)
{
    BOOL bRet = TRUE;
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INH;
    PIMAGE_SECTION_HEADER ISH;
 
    PROCESS_INFORMATION PI;
    HANDLE hProcess; //~
    PCONTEXT CTX; //~
    LPVOID lpAddr; //~
    LPVOID pImageBase; //~
    STARTUPINFOW SI;
    PDWORD dwImageBase;
    NtUnmapViewOfSection xNtUnmapViewOfSection;
    int Count;
 
    IDH = PIMAGE_DOS_HEADER(pFile);
    if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
    {
        printf("1\r\n");
        INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew);
        if (INH->Signature == IMAGE_NT_SIGNATURE)
        {
            printf("2\r\n");
            RtlZeroMemory(&SI, sizeof(SI));
            RtlZeroMemory(&PI, sizeof(PI));
 
            if (CreateProcess(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI))
            {
                printf("3\r\n");
                hProcess = PI.hProcess;
                CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
                CTX->ContextFlags = CONTEXT_FULL;
                if (GetThreadContext(PI.hThread, LPCONTEXT(CTX)))
                {
                    printf("4\r\n");
                    ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL);
 
                    if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase)
                    {
                        xNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
                        xNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
                    }
 
                    lpAddr = LPVOID(INH->OptionalHeader.ImageBase);
 
                    pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), INH->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    if (pImageBase)
                    {
                        printf("5\r\n");
                        WriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL);
                        for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++)
                        {
                            ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40));
                            WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + ISH->VirtualAddress), LPVOID(DWORD(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL);
                        }
                        WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&INH->OptionalHeader.ImageBase), 4, NULL);
                        CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
                        SetThreadContext(PI.hThread, LPCONTEXT(CTX));
                        ResumeThread(PI.hThread);
                    }
                    else
                    {
                        printf("Status : Error VirtualAllocEx!");
                        bRet = FALSE;
                    }
                }
                else
                {
                    printf("Status : Error GetThreadContext!");
                    bRet = FALSE;
                }
            }
            else
            {
                printf("Status : Error CreateProcess!");
                bRet = FALSE;
            }
        }
        else
        {
            printf("Status : Error IMAGE_NT_SIGNATURE!");
            bRet = FALSE;
        }
    }
    else
    {
        bRet = FALSE;
        printf("Status : Password not correct!");
    }
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bRet;
}
Всё проходит хорошо, без ошибок, но C# приложение не видит .NET, возвращает ошибку (в мессейджбоксе): "This application could not be started. Do you want to view information about this issue?". Если нажать "Да" - выполняется переход по ссылке https://support.microsoft.com/... rm-support

Ну и сам вопрос: возможно ли это устранить или с .NET C# приложениями такой вид запуска не прокатит?

P.S. Долго думал, в какой раздел написать, если всё-таки перепутал - модераторы, перекиньте тему в правильный раздел
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.07.2017, 00:24
Ответы с готовыми решениями:

Запуск из программы стороннего приложения в DOS
Добрый день! Необходимо в ходе выполнения программы запустить другое .exe приложение в DOS. Гугл не помог, все ссылки выводятся на...

выдает ошибку памяти. Запуск программы в юникс
#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;string.h&gt; #define BUFFER 50 char* upCase(const char* str) { size_t len =...

Запуск программы или файла с консольного приложения
Помогите пожалуйста. Не могу найти нигде как запустить файл или программу с консольного приложения. Очень срочно нужно. p.s. Заранее...

31
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
14.07.2017, 00:49  [ТС]
Ещё актуально. Подскажите хоть что-то :-(
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
14.07.2017, 08:50
.NET-приложения должны содержать, как минимум, секцию "CLR Runtime Header".
По наличию этой секции загрузчик из ntdll.dll инициализирует и проверяет
нужные структуры, а затем устанавливает правильную точку входа в CONTEXT.
А она, кстати, там равна не OptionalHeader.AddressOfEntryPoint, а _CorExeMain из mscoree.dll.
1
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
14.07.2017, 13:26  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
А она, кстати, там равна не OptionalHeader.AddressOfEntryPoint, а _CorExeMain из mscoree.dll.
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
BOOL ExecFile(LPWSTR szFilePath, LPVOID pFile)
{
    BOOL bRet = TRUE;
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INH;
    PIMAGE_SECTION_HEADER ISH;
 
    PROCESS_INFORMATION PI;
    HANDLE hProcess; //~
    PCONTEXT CTX; //~
    LPVOID lpAddr; //~
    LPVOID pImageBase; //~
    STARTUPINFOW SI;
    PDWORD dwImageBase;
    NtUnmapViewOfSection xNtUnmapViewOfSection;
    int Count;
 
    IDH = PIMAGE_DOS_HEADER(pFile);
    if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
    {
        printf("1\r\n");
        INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew);
        if (INH->Signature == IMAGE_NT_SIGNATURE)
        {
            printf("2\r\n");
            RtlZeroMemory(&SI, sizeof(SI));
            RtlZeroMemory(&PI, sizeof(PI));
 
            if (CreateProcess(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI))
            {
                printf("3\r\n");
                hProcess = PI.hProcess;
                CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
                CTX->ContextFlags = CONTEXT_FULL;
                if (GetThreadContext(PI.hThread, LPCONTEXT(CTX)))
                {
                    printf("4\r\n");
                    ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL);
 
                    if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase)
                    {
                        xNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
                        xNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
                    }
 
                    lpAddr = LPVOID(INH->OptionalHeader.ImageBase);
 
                    pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), INH->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    if (pImageBase)
                    {
                        printf("5\r\n");
                        WriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL);
                        for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++)
                        {
                            ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40));
                            WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + ISH->VirtualAddress), LPVOID(DWORD(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL);
                        }
                        WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&INH->OptionalHeader.ImageBase), 4, NULL);
                        CTX->Eax = DWORD(pImageBase) + _CorExeMain();
                        SetThreadContext(PI.hThread, LPCONTEXT(CTX));
                        ResumeThread(PI.hThread);
                    }
                    else
                    {
 
                        printf("Status : Error VirtualAllocEx!");
                        bRet = FALSE;
                    }
                }
                else
                {
                    printf("Status : Error GetThreadContext!");
                    bRet = FALSE;
                }
            }
            else
            {
                printf("Status : Error CreateProcess!");
                bRet = FALSE;
            }
        }
        else
        {
            printf("Status : Error IMAGE_NT_SIGNATURE!");
            bRet = FALSE;
        }
    }
    else
    {
        bRet = FALSE;
        printf("Status : Password not correct!");
    }
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bRet;
}
Так вроде тоже не работает...
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
14.07.2017, 13:44
Лучший ответ Сообщение было отмечено edward_freedom как решение

Решение

И не должно

Как работает запуск процесса? Ты вызываешь функцию CreateProcessXxx, выполняется
проверка аргументов, подготовка всяких структур данных, переменные окружения и т.д.
Далее выполняется прыжок в ядро. Ядро создает системные объекты EPROCESS (процесс),
ETHREAD (первичный поток), создает адресное пространство для процесса, в нем
структуры PEB, TEB и другие, и далее выполняется прыжок обратно в режим пользователя
(через механизм APC) на функцию ntdll!LdrInitializeThunk. С этого момента начинается
пользовательская часть инициализации процесса: загрузка связанных dll, инициализация
TLS-калбэков и т.д. Вот теперь важный момент: если загрузчик видит, что в exe есть
секция "CLR Runtime Header" (индекс 14 в PE data directories, если не ошибаюсь), то
он сам меняет в CONTEXT точку входа на mscoree!_CorExeMain. Ну а _CorExeMain -
это и есть инициализация процесса .NET. Без секции "CLR Runtime Header" точно
ничего работать не будет.

Подробнее узнать, как запускается процесс, можно в следующих источниках:

1. "Windows Internals" М. Руссиновича. Он там все очень подробно описывает,
страниц на 20, наверное.

2. Исходники NT4/W2K/WRK. См. функции LdrInitialize и далее.

3. Дизассемблирование ntdll современных версий Windows.
3
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
14.07.2017, 14:00  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
если загрузчик видит, что в exe есть
секция "CLR Runtime Header" (индекс 14 в PE data directories, если не ошибаюсь), то
он сам меняет в CONTEXT точку входа на mscoree!_CorExeMain. Ну а _CorExeMain -
это и есть инициализация процесса .NET. Без секции "CLR Runtime Header" точно
ничего работать не будет.

Цитата Сообщение от Убежденный Посмотреть сообщение
1. "Windows Internals" М. Руссиновича.
Цитата Сообщение от Убежденный Посмотреть сообщение
2. Исходники NT4/W2K/WRK.
Цитата Сообщение от Убежденный Посмотреть сообщение
3. Дизассемблирование ntdll современных версий Windows.
Это всё нужно знать, чтобы просто запустить приложение из памяти?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
14.07.2017, 16:20
Цитата Сообщение от Mikha Mikhin Посмотреть сообщение
?

Цитата Сообщение от Mikha Mikhin Посмотреть сообщение
Это всё нужно знать, чтобы просто запустить приложение из памяти?
Это все нужно знать, чтобы в случае возникновения "нештатных" ситуаций знать, в
какую сторону копать и где искать ответы.
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
14.07.2017, 17:10  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
и где искать ответы.
В огромных исходниках Windows? o_0
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
14.07.2017, 17:12
Все исходники не обязательно, достаточно найти нужные фрагменты:
Цитата Сообщение от Убежденный Посмотреть сообщение
См. функции LdrInitialize и далее.
Кстати, почему ты называешь этот способ "запуск из памяти"?
Процесс-то все равно привязывается к файлу на диске (который у
тебя в аргументе szFilePath функции ExecFile)...
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
15.07.2017, 00:01  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Процесс-то все равно привязывается к файлу на диске
Привязывается, но дополнительно не создаёт на диске программу, которую запускает.

Добавлено через 6 часов 35 минут
Почитал про
Цитата Сообщение от Убежденный Посмотреть сообщение
LdrInitialize
правда не понял, что мне с ней надо сделать
При запуске надо выполнить всё за неё или, наоборот, её (как-то) вызвать?
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
16.07.2017, 19:43
Цитата Сообщение от Убежденный Посмотреть сообщение
он сам меняет в CONTEXT точку входа на mscoree!_CorExeMain
Добавлю, что так делается для PE64. В PE32 _CorExeMain вызывается самим приложением (как правило вызов _CorExeMain стоит сразу на EntryPoint).
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
16.07.2017, 19:48  [ТС]
jupman, т.е. мне надо при запуске вызывать _CorExeMain?
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
16.07.2017, 20:26
Цитата Сообщение от Убежденный Посмотреть сообщение
он сам меняет в CONTEXT точку входа на mscoree!_CorExeMain
Извиняюсь, напутал. Так делается на любой x64-разрядной Windows. Если к примеру взять NET-приложение (PE32), и обнулить AddressOfEntryPoint в заголовке, то на x32-разрядных Windows оно не запустится.

Добавлено через 14 минут
Mikha Mikhin, Изменение PE-заголовка в процессе выполнения программы
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
16.07.2017, 20:54  [ТС]
Цитата Сообщение от jupman Посмотреть сообщение
Mikha Mikhin, Изменение PE-заголовка в процессе выполнения программы
У меня ведь другая задача - не "изменение существующего PE-заголовка в процессе выполнения программы", а запуск .NET программы без её сохранения на диск.
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
16.07.2017, 21:02
Цитата Сообщение от Убежденный Посмотреть сообщение
Кстати, почему ты называешь этот способ "запуск из памяти"?
Процесс-то все равно привязывается к файлу на диске (который у
тебя в аргументе szFilePath функции ExecFile)
Суть в том, что в засуспенженый процесс заливается левый образ, правится PEB.ImageBaseAddress на этот образ и поток перенаправляется на новую точку входа.
Цитата Сообщение от Mikha Mikhin Посмотреть сообщение
xNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
Старый образ не освобождай. База образа остается в EPROCESS и в дальнейшем используется системой.

Добавлено через 4 минуты
Цитата Сообщение от Mikha Mikhin Посмотреть сообщение
У меня ведь другая задача - не "изменение существующего PE-заголовка в процессе выполнения программы", а запуск .NET программы без её сохранения на диск.
Ну, я там как раз и описал, способ запуска NET-приложения из памяти.

Можно использовать классический алгоритм загрузки PE (мэппинг образа, настройка релоков/импорта, правка PEB etc) с небольшим дополнением. Дело в том, что NET-приложение, в процессе работы, периодически мэппингует свой PE с диска. И для корректной работы придется хучить ZwMapViewOfSection и подсовывать оригинальный образ. В добавок можно присвоить LDR_DATA_TABLE_ENTRY.Flags флаг LDRP_COR_IMAGE. Хотя последнее, возможно, необязательно. Плюс, вызывать _CorExeMain из mscoree.dll вместо передачи на AddressOfEntryPoint.
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
16.07.2017, 21:11  [ТС]
jupman, т.е. запуск у меня нормальный, но помимо его мне надо будет хукать ZwMapViewOfSection?
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
16.07.2017, 21:30
Mikha Mikhin, таким способом как у тебя реализовать загрузку .NET сложнее. Лучше грузи без инжектов:

1) Собираешь образ в памяти
2) Если требуется обрабатываешь релоки
3) Обрабатываешь таблицу импорта
4) Патчиш PEB.ImageBaseAddress и поля EntryPoint, DllBase, SizeOfImage из LDR_DATA_TABLE_ENTRY
5) Патчиш LDR_DATA_TABLE_ENTRY.Flags на LDRP_COR_IMAGE
6) Ставиш хук на ZwMapViewOfSection (подсовывание оригинального образа)
7) Вызываешь _CorExeMain
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
16.07.2017, 21:40  [ТС]
jupman, как я понимаю, хук надо будет ставить на уровне драйвера?
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
16.07.2017, 21:46
Цитата Сообщение от jupman Посмотреть сообщение
4) Патчиш PEB.ImageBaseAddress и поля EntryPoint, DllBase, SizeOfImage из LDR_DATA_TABLE_ENTRY
5) Патчиш LDR_DATA_TABLE_ENTRY.Flags на LDRP_COR_IMAGE
А, вот еще что вспомнил. Под Wow64 нужно править два PEB-a: PEB32 и PEB64

Добавлено через 2 минуты
Цитата Сообщение от Mikha Mikhin Посмотреть сообщение
jupman, как я понимаю, хук надо будет ставить на уровне драйвера?
Нет, в user mode. Хукаеш ZwMapViewOfSection из ntdll.dll.
0
3 / 3 / 2
Регистрация: 06.12.2016
Сообщений: 176
16.07.2017, 22:11  [ТС]
Цитата Сообщение от jupman Посмотреть сообщение
1) Собираешь образ в памяти
2) Если требуется обрабатываешь релоки
3) Обрабатываешь таблицу импорта
4) Патчиш PEB.ImageBaseAddress и поля EntryPoint, DllBase, SizeOfImage из LDR_DATA_TABLE_ENTRY
5) Патчиш LDR_DATA_TABLE_ENTRY.Flags на LDRP_COR_IMAGE
6) Ставиш хук на ZwMapViewOfSection (подсовывание оригинального образа)
7) Вызываешь _CorExeMain
Уффф, это даже звучит сложно
Пойду гуглить как это всё сделать
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.07.2017, 22:11
Помогаю со студенческими работами здесь

Запуск не .Net приложения в памяти
Подскажите, пожалуйста, возможен ли запуск не .Net приложения прямо в памяти из массива байт. Знаю про assembly.Load, но он подходит только...

Запуск приложения на платформе .NET Framework 4.0, на другом компьютере без установки .NET Framework 4.0
Как запустить приложение на платформе .NET Framework 4.0, на другом компьютере без установки .NET Framework 4.0?

Запуск приложения без .Net
т.е есть Windows forms приложение, нужно чтобы exeшник после щелчка открылся(не важно XP там, 7-ка или 10-ка).Возможно?

Сканирование оперативной памяти запуск приложения
Помогите разобраться. При запуске стартует сразу и спустя несколько секунд перезагружается ПК. А должно запускаться если в ОЗУ появится...

Запуск приложения на всех версиях .Net
Наваял калькулятор в VisualStudio, при создании проекта выбрал .Net 2.0, думал будел хорошо для совместимости, запускается на моей XP SP3,...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru