Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

### Исправление ошибки `ERROR_INVALID_NAME` при получении GUID диска в Delphi

Delphi , Синтаксис , Справочник по API-функциям

Исправление ошибки ERROR_INVALID_NAME при получении GUID диска в Delphi

Вопрос, с которым сталкиваются разработчики, работающие с функциями операционной системы в Delphi, заключается в правильном использовании внешних функций, таких как GetVolumeNameForVolumeMountPoint. Эта функция предназначена для получения имени тома по его точке монтирования, но она может возвращать ошибку ERROR_INVALID_NAME при неправильном использовании.

Описание проблемы

Проблема заключается в том, что разработчик пытается получить GUID конкретного диска, используя функцию GetVolumeNameForVolumeMountPoint. В коде, предоставленном разработчиком, используется неправильный тип кодировки для строковых аргументов функции, что приводит к ошибке ERROR_INVALID_NAME с кодом 123.

Пример кода с ошибкой

Function GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint: LPCTSTR; lpszVolumeName: LPTSTR; cchBufferLength: DWORD): BOOL; stdcall;
  external 'kernel32.dll' name 'GetVolumeNameForVolumeMountPointW';

procedure TForm1.Button1Click(Sender: TObject);
var
  Buffer: array[0..50] of AnsiChar;
begin
  if GetVolumeNameForVolumeMountPoint('C:\', Buffer, SizeOf(Buffer)) then
  begin
    ShowMessage(Buffer); // Ожидается вывод: "\\?\Volume{deadbeef-895e-4a1d-9d64-9b82fa068d76}\"
  end
  else RaiseLastOSError; // Фактически: ERROR_INVALID_NAME (123).
end;

Подтвержденный ответ

Ошибка возникает из-за того, что разработчик вызывает Unicode-версию функции, но передает ей строку в ANSI-формате. Это приводит к неправильной кодировке первого аргумента, что и вызывает ошибку.

Исправление

Для корректной работы с функцией GetVolumeNameForVolumeMountPoint необходимо использовать соответствующую версию функции, в зависимости от того, используете ли вы ANSI или Unicode версию Delphi. В случае использования ANSI версии Delphi, код должен выглядеть следующим образом:

{$APPTYPE CONSOLE}
uses
  SysUtils, Windows;

function GetVolumeNameForVolumeMountPointA(lpszVolumeMountPoint: PAnsiChar;
  lpszVolumeName: PAnsiChar; cchBufferLength: DWORD): BOOL; stdcall;
  external 'kernel32.dll';

procedure Main;
var
  Buffer: array [0 .. 49] of AnsiChar;
begin
  Win32Check(GetVolumeNameForVolumeMountPointA('C:\', Buffer, Length(Buffer)));
  Writeln(Buffer);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Если же вы используете Unicode версию Delphi, код будет выглядеть так:

{$APPTYPE CONSOLE}
uses
  SysUtils, Windows;

function GetVolumeNameForVolumeMountPointW(lpszVolumeMountPoint: PWideChar;
  lpszVolumeName: PWideChar; cchBufferLength: DWORD): BOOL; stdcall;
  external 'kernel32.dll';

procedure Main;
var
  Buffer: array [0 .. 49] of WideChar;
begin
  Win32Check(GetVolumeNameForVolumeMountPointW('C:\', Buffer, Length(Buffer)));
  Writeln(Buffer);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Для совместимости с различными версиями Delphi можно использовать следующий подход:

{$APPTYPE CONSOLE}
uses
  SysUtils, Windows;

const
  Win32ImportSuffix = {$IFDEF Unicode}'W'{$ELSE}'A'{$ENDIF};

function GetVolumeNameForVolumeMountPointA(lpszVolumeMountPoint: PAnsiChar;
  lpszVolumeName: PAnsiChar; cchBufferLength: DWORD): BOOL; stdcall;
  external 'kernel32.dll';
function GetVolumeNameForVolumeMountPointW(lpszVolumeMountPoint: PWideChar;
  lpszVolumeName: PWideChar; cchBufferLength: DWORD): BOOL; stdcall;
  external 'kernel32.dll';
function GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint: PChar;
  lpszVolumeName: PChar; cchBufferLength: DWORD): BOOL; stdcall;
  external 'kernel32.dll' name 'GetVolumeNameForVolumeMountPoint' + Win32ImportSuffix;

procedure Main;
var
  Buffer: array [0 .. 49] of Char;
begin
  Win32Check(GetVolumeNameForVolumeMountPoint('C:\', Buffer, Length(Buffer)));
  Writeln(Buffer);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Этот код автоматически выбирает нужную версию функции в зависимости от того, используете ли вы ANSI или Unicode версию Delphi. Это позволяет избежать ошибки ERROR_INVALID_NAME и корректно получить GUID диска.

Создано по материалам из источника по ссылке.

Разработчик столкнулся с ошибкой `ERROR_INVALID_NAME` при попытке получить GUID диска в Delphi из-за несоответствия типа кодировки строковых аргументов функции `GetVolumeNameForVolumeMountPoint`.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Справочник по API-функциям ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2024-12-26 13:59:05/0.0031669139862061/0