Проблема с преобразованием пути файловой системы в постоянный БАЙТ*

#c #winapi #filesystems #c 17 #registry

#c #winapi #файловые системы #c 17 #реестр

Вопрос:

Чего я пытаюсь добиться, так это запуска моей программы при запуске Windows с использованием реестра. Когда я пытаюсь указать местоположение файла, компилятор жалуется, что он не может преобразовать из filesystem::path в const BYTE* . Я понятия не имею, как это исправить, поскольку я новичок, когда дело доходит до C . Я предоставил приведенный ниже код:

 HKEY newValue;
RegOpenKey(HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Run", amp;newValue);
RegSetValueEx(newValue, "myprogram", 0, REG_SZ, fs::temp_directory_path().append(filename), sizeof("tes3t")); // This line is the issue. fs::temp_directory_path().append(filename)
RegCloseKey(newValue);
return 0;
  

ИСКЛЮЧЕНИЕ: не существует подходящей функции преобразования из «std: filesystem::path» в «const BYTE *»

Комментарии:

1. Сделайте себе одолжение и сохраните желаемое значение в промежуточной переменной. Тогда вы легко отделите манипуляции с путями от вызовов функций доступа к реестру.

2. Извините, но, как я уже говорил ранее, я совершенно новичок в c , и я понятия не имею, что вы имели в виду под этим, я больше визуальный человек. Не могли бы вы привести мне пример?

3. Он означает, что вы упаковываете слишком много вещей в слишком маленькое пространство. Если вы выполняете каждый шаг самостоятельно, сохраняя результаты во временных переменных, вам будет легче увидеть, в чем проблема. Как только ошибка изолирована, исправить ошибку обычно легко.

Ответ №1:

Согласно RegSetValueExA() документации, функция не принимает std::filesystem::path объект. Именно на это жалуется сообщение об ошибке.

 LSTATUS RegSetValueExA(
  HKEY       hKey,
  LPCSTR     lpValueName,
  DWORD      Reserved,
  DWORD      dwType,
  const BYTE *lpData, // <-- here
  DWORD      cbData
);
  

5-й параметр принимает const BYTE* указатель на строку в стиле C с нулевым завершением. 6-й параметр принимает количество символов в строке, включая нулевой ограничитель:

lpData

Данные, которые необходимо сохранить.

Для типов на основе строк, таких как REG_SZ, строка должна заканчиваться нулем. С типом данных REG_MULTI_SZ строка должна заканчиваться двумя нулевыми символами.

Обратите внимание, что значение lpData, указывающее значение null, является допустимым, однако, если это так, cbData должно быть установлено в ‘0’.

cbData

Размер информации, на которую указывает параметр lpData, в байтах. Если данные имеют тип REG_SZ, REG_EXPAND_SZ или REG_MULTI_SZ, cbData должен включать размер завершающего нулевого символа или символов.

std::filesystem::path не имеет неявного преобразования в const BYTE* , отсюда ошибка компилятора. Сначала вам необходимо явно преобразовать path в a std::string или std::wstring (предпочтительнее последнее, поскольку реестр хранит строки как Юникод внутри), прежде чем вы сможете сохранить это строковое значение в реестре, например:

 // using std::string...

HKEY newValue;

// don't use RegOpenKey()! It is provided only for backwards compatibility with 16bit apps...
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Run", 0, KEY_SET_VALUE, amp;newValue) == 0)
{
    // this may lose data for non-ASCII characters!
    std::string s = fs::temp_directory_path().append(filename).string();

    // this will convert the ANSI string to Unicode for you...
    RegSetValueExA(newValue, "myprogram", 0, REG_SZ, reinterpret_cast<LPCBYTE>(s.c_str()), s.size() 1);

    RegCloseKey(newValue);
}

return 0;
  
 // using std::wstring...

HKEY newValue;

// don't use RegOpenKey()! It is provided only for backwards compatibility with 16bit apps...
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\Microsoft\Windows\CurrentVersion\Run", 0, KEY_SET_VALUE, amp;newValue) == 0)
{
    // no data loss here!
    std::wstring s = fs::temp_directory_path().append(filename).wstring();

    // no ANSI->Unicode conversion is performed here...
    RegSetValueExW(newValue, L"myprogram", 0, REG_SZ, reinterpret_cast<LPCBYTE>(s.c_str()), (s.size() 1) * sizeof(WCHAR));

    RegCloseKey(newValue);
}

return 0;
  

Комментарии:

1. Привет! Большое вам спасибо за помощь в этом… Мне немного жаль, что я не понимаю код… Но я научусь.. В конечном итоге. Я принимаю это как ответ, потому что вы предоставили мне 2 решения и предоставили информацию о том, почему это не работает. Это очень актуально, и я просто хочу спросить, нормально ли не понимать код? Потому что это заставляет меня чувствовать себя глупо, ага, еще раз спасибо. РЕДАКТИРОВАТЬ: строка, которую я не понимаю «reinterpret_cast<LPCBYTE>»

2. Это полунормально, но опасно. Если вы не понимаете код, вы не сможете исправить его, когда он сломается. Вам нужно сформулировать проблемы так, чтобы вы могли понять, и обычно это делается путем создания меньших проблем и решения меньших проблем по одной за раз..

3. @JakeNiledon LPCBYTE — это просто псевдоним для const BYTE* . Это reinterpret_cast потому std::(w)string::c_str() , что возвращает const char* / const wchar_t* , который должен быть преобразован из одного типа в другой.

Ответ №2:

Функции WinAPI не принимают аргументы std::filesystem::path типа, поэтому вам нужно как-то преобразовать его в a const BYTE* .

Это один из примеров:

 std::string fullpath = (fs::temp_directory_path() / filename).string();

RegSetValueEx(
    newValue,
    "myprogram",
    0,
    REG_SZ,
    reinterpret_cast<LPCBYTE>(fullpath.c_str()), // returns a "const char*" then cast
    fullpath.size()   1  //   1 for null terminator
);