ERROR_FILE_NOT_FOUND неожиданно возвращен для функции OpenBackupEventLog - PullRequest
2 голосов
/ 09 января 2012

Я пытаюсь открыть файл .evtx на компьютере под управлением Windows 7 x64 с помощью функции OpenBackupEventLog , однако продолжаю получать ERROR_FILE_NOT_FOUND (код ошибки 2), даже если файл существует .

Моя декларация P / Invoke / точка, где я вызываю файл:

[DllImport("advapi32.dll", SetLastError = true, ExactSpelling = false, EntryPoint = "OpenBackupEventLog")]
public static extern IntPtr OpenBackupEventLog(
    [MarshalAs(UnmanagedType.LPTStr)]string uncServerName,
    [MarshalAs(UnmanagedType.LPTStr)]string fileName);

IntPtr ptr = NativeMethods.OpenBackupEventLog(null, filename);
if (ptr == IntPtr.Zero && File.Exists(filename))
{
    // This exception is thrown and so the file does exist
    throw new Win32Exception(string.Format("Failed to open event log archive '{0}'", filename));
}

Обратите внимание, что это внутри процесса x86.

Единственное, о чем я могу думать, это то, что проблема связана с маршаллингом Unicode / ANSI (ранее я вспоминал, что получил ERROR_INVALID_PARAMETER), однако я дважды проверил, и игра с маршаллингом не имеет никакого эффекта.

Почему это не удается открыть файл / как я могу это диагностировать?

Ответы [ 3 ]

1 голос
/ 11 января 2012
[DllImport("advapi32.dll", ..., EntryPoint = "OpenBackupEventLog")]

Свойство EntryPoint является источником вашей проблемы здесь. Имена экспортируемых функций: OpenBackupEventLogA и OpenBackupEventLogW. Соответственно ANSI и Unicode версии этой функции. В вашем объявлении будет использоваться версия ANSI, поскольку вы не указали свойство CharSet.

Маршаллер pinvoke может автоматически найти версии A и W, когда ExactSpelling = false (по умолчанию). Но не тогда, когда вы указываете имя явно.

Нет смысла использовать версию ANSI, используйте CharSet.Auto и опустите EntryPoint. MarshalAs также не нужен, строки уже упорядочены как LPTStr. Таким образом:

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr OpenBackupEventLog(string uncServerName, string fileName);
0 голосов
/ 11 января 2012

Это была кодировка Unicode vs проблема ANSI - мне показалось, что мне удалось как-то снова начать работать, но позже я понял, что он возвращает строки ANSI вместо строк UNICODE - очевидно, я случайно запустил использование ANSI-версий этих функций, что не годится.

Теперь работает со следующим объявлением PInvoke

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "OpenBackupEventLogW")]
public static extern EventLogHandle OpenBackupEventLog(
    string uncServerName, 
    string fileName);

Ключевым моментом является то, что я:

  • Удалены атрибуты MarshalAs
  • Добавлен параметр CharSet = CharSet.Unicdoe в мою DllImport декларацию
  • Добавлен W в конце имени точки входа

Обратите внимание, что это также работает, если я удаляю W с конца имени точки входа, пока есть параметр CharSet = CharSet.Unicdoe.

0 голосов
/ 09 января 2012

Поскольку это 64-разрядная ОС, и вы получаете доступ к файлам с помощью 32-разрядного приложения, наиболее вероятной причиной этого исключения является то, что ОС очень «услужливо» автоматически перенаправляет запросы дляКаталог System (C:\Windows\system, например) в каталог SysWOW64 C:\Windows\SysWOW64.

К счастью, существует встроенное решение: каталог sysnative .

Когда вы генерируете путь к имени файла, используйте что-то похожее на следующее:

string filePath = @ "% WINDIR% \ sysnative \ winevt \ logs \ mylog.evtx";

Однако делать это можно только в том случае, если вы сохраняете приложение как 32-разрядное приложение.Он не будет правильно обрабатываться как 64-битное приложение.

...