1

Тема: Робота з Windows API

У програмі 1.2 вирішується завдання копіювання файлів за допомогою Windows API,
Програма 1.2. cpW: копіювання файлів з використанням Windows

/* Глава 1. Базовая программа копирования файлов cp.
   Реализация, использующая Windows. */
/* cpW файл1 файл2: Копировать файл1 в файл2. */
#include <windows.h>
#include <stdio.h>
#define BUF_SIZE 256
int main (int argc, LPTSTR argv [])
{
   HANDLE hIn, hOut;
   DWORD nIn, nOut;
   CHAR Buffer [BUF_SIZE];
   if (argc != 3) {
      printf ("Использование: cpW файл1  файл2\n");
      return 1;
   }
   hIn = CreateFile (argv [1], GENERIC_READ, 0, NULL,
         OPEN_EXISTING, 0, NULL);
   if (hIn == INVALID_HANDLE_VALUE) {
      printf ("Невозможно открыть входной файл. Ошибка: %x\n",
            GetLastError ());
      return 2;
   }
   hOut = CreateFile (argv [2], GENERIC_WRITE, 0, NULL,
         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
   if (hOut == INVALID_HANDLE_VALUE) {
      printf ("Невозможно открыть выходной файл. Ошибка: %x\n",
            GetLastError ());
      return 3;
   }
   while (ReadFile (hIn, Buffer, BUF_SIZE, &nIn, NULL) && nIn > 0) {
      WriteFile (hOut, Buffer, nIn, &nOut, NULL);
      if (nIn != nOut) {
         printf ("Неустранимая ошибка записи: %x\n", GetLastError ());
         return 4;
      }
   }
   CloseHandle (hIn);
   CloseHandle (hOut);
   return 0;
}

Для того щоб виконати це завдання я створив проект Windows Desktop Wizard(Win32) з іменем "cpW" і закинув в нього даний код. Він успішно компілюється. Потім я створив в папці проекту(там де exe файл) два текстових файли - File1.txt і File2.txt і записав у них різний текст. Потім я зайшов в командний рядок і перейшов в папку проекта із exe файлом(застосунком), ввів команду cpW.exe File1.txt File2.txt і замість того щоб копіювати мої файли мені вивело що неможливо відкрити вхідний файл. Підкажіть будь-ласка у чому проблема. Як мені запустити мою програму з командного рядка?? Можливо я неправильно ввів аргументи або неправильно задав кодіровку моїх txt файлів(там за замовчуванням кажись UTF-8).

Post's attachments

Png1.png 17.62 kb, 62 downloads since 2021-02-25 

2 Востаннє редагувалося koala (25.02.2021 14:05:34)

Re: Робота з Windows API

Повідомлення відрізняється від того, що в цьому коді. Тобто код, який ви виконуєте, і той, що ви виклали тут - різний. Яким же чином, на вашу думку, ми маємо за одним кодом встановити, яка помилка в іншому?
Ну і про всяк випадок перевірте назву файлу, бо 2 - це ERROR_FILE_NOT_FOUND. Може, там кирилиця десь.

3 Востаннє редагувалося lucas-kane (25.02.2021 16:22:41)

Re: Робота з Windows API

CreateFile - Це макрос, він може приймати декілька значень залежно він налаштувань проекту.

#define CreateFile CreateFileA

Або

#define CreateFile CreateFileW

Вам потрібно:
1. Або перекодувати масив argv[] із LPTSTR, до LPCWSTR. How to convert LPTSTR to LPCWSTR?

HANDLE __stdcall CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)

2. Або використовувати CreateFileA явно в коді.

HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
    hIn = CreateFileA(argv[1], GENERIC_READ, 0, NULL,
                     OPEN_EXISTING, 0, NULL);
    if (hIn == INVALID_HANDLE_VALUE)
    {
        printf("Неможливо відкрити вхідний файл. Помилка: %x\n",
               GetLastError());
        return 2;
    }
    hOut = CreateFileA(argv[2], GENERIC_WRITE, 0, NULL,
                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        printf("Неможливо відкрити вихідний файл. Помилка: %x\n",
               GetLastError());
        return 3;
    }

3. Або копирсатись у налаштуванні проект How do I turn off Unicode in a VC++ project?

Подякували: leofun011

4

Re: Робота з Windows API

LPTSTR - це такий самий UNICODE-залежний макрос, якщо там CreateFileA, то це LPCSTR, а якщо CreateFileW, то LPCWSTR.

Подякували: leofun011

5

Re: Робота з Windows API

спробуй запустити від імені адміна та/або надати повний доступ до файла для усіх додатків

6

Re: Робота з Windows API

Код який я запускаю і код який я виклав відрізняється лише тим що в першому я переклав англійською весь російськомовний текст. Тобто замість "Невозможно открыть входной файл. Ошибка: " в коді написано "Unable to open input file. Error: ".  Також я перевірив назви файлів на наявність кирилиці і виявилося що все норм. Код змінювати не треба оскільки я взяв його з книги і він правильний. Моє завдання це запустити його з командного рядка. І в цьому моя проблема . Можливо через те що я неправильно передаю аргументи або txt файли повинні мати якусь іншу кодіровку. А може треба змінити якісь налаштування Visual Studio???

7

Re: Робота з Windows API

https://replace.org.ua/uploads/images/7111/5c1fc7a05a15ac02fa884a42a8c6bf69.png

8

Re: Робота з Windows API

Це картинка з ранніх версій Visual Studio. У мене 2019-го року, тому я даної опції поки що в себе не знайшов

9

Re: Робота з Windows API

Mirek7098 написав:

Це картинка з ранніх версій Visual Studio. У мене 2019-го року, тому я даної опції поки що в себе не знайшов

Дивно в мене також 2019 і там є за таки посиланням:
Project->[Назва проекту]Properties->Configuration Proptrties->Advanced->Character Set: {Not Set, Use Unicode Character Set, Use Multi-Byte Character Set, ...} Я Спробував 1 та 3 параметр і все працює .
Коли вказуєш Not Set та Multi-Byte Character Set тоді тип TCHAR = char, але із UNICODE не спрацювало... Підозрюю, що із-за того, що він може мати різний розмір в пам'яті... Спробую пошукати де це налаштування в проєкті.

Подякували: Mirek70981

10 Востаннє редагувалося koala (26.02.2021 07:48:34)

Re: Робота з Windows API

А чого ви, якщо використовуєте типи з T, пишете main, а не _tmain? У MS є 3 варіанти: main - для char, wmain - для wchar_t і макрос _tmain, який розкривається у main чи wmain залежно від визначення макросу UNICODE. Хочете крос-компільований варіант - беріть _tmain.

Подякували: lucas-kane, leofun01, Mirek7098, Betterthanyou4

11

Re: Робота з Windows API

Я зайшов в налаштування і змінив з UNICODE на Multi-Byte. Все працює. Всім дякую за допомогу

12

Re: Робота з Windows API

https://replace.org.ua/uploads/images/7111/0e7cdaac3ffdb1a50fca363f3ca64c01.png