エントリー
良い一日。 0xc00007b例外に精通していますか? X-Rayエンジンのx64への移行以来、0cx00007bの問題に関する多くの報告がありました。 ケースの90%で、これは64ビットOpenALドライバーの不足による問題でした。
問題を解決するためのアイデア
最初は、ドライバーをインストールする必要があると絶えず答えました。数か月後、スタートアップと起こりうる問題に関するFAQを書きました。 しかし、このようなレポートは消えませんでした。CISの人々は特に読むことを好まないため、問題を根本的に解決することにしました。ドライバーがない場合は、エンジンの下からドライバーをインストールします。
ステップ1:dllが十分でないときにプログラムを開始する
ライブラリを相互に接続する最も簡単な方法は、ビルド( プラグマコメント )ですが、この場合はこれを実行できません。
したがって、ステップ1: 明示的なリンクまたはhi extern "C"
。
必要なもの:exeをエンジンライブラリから解放します。 これは次の方法で行われます。
1)ダイナミックライブラリでエンジンを起動する関数を取り出します。
extern "C" --// LoadLibrary, , API { void ENGINE_API RunApplication(LPCSTR commandLine) { ... // Your code } }
2)exeから関数を呼び出します。
using RunFunc = void(__cdecl*)(const char*); // bool OpenALFound = false; // int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if(OpenALFound) { HMODULE hLib = LoadLibrary("xrEngine.dll"); // IsRunFunc RunFunc = (IsRunFunc)GetProcAddress(hLib, "RunApplication"); // RunFunc(params); // } return 0; }
ステップ2:ドライバーの確認
さて、すべてがシンプルです。システム1を取得し(誰かが驚くかもしれませんが、OSは常にCにあるとは限りません)、ドライバーフォルダー内のdllを確認します。
/// R_ASSERT - , , - ... // WinMain code TCHAR szOpenALDir[MAX_PATH] = { 0 }; // R_ASSERT(GetSystemDirectory(szOpenALDir, MAX_PATH * sizeof(TCHAR))); #ifndef UNICODE _snprintf_s(szOpenALDir, MAX_PATH * sizeof(CHAR), "%s%s", szOpenALDir, "\\OpenAL32.dll"); #else _snwprintf_s(szOpenALDir, MAX_PATH * sizeof(WCHAR), L"%s%s", szOpenALDir, L"\\OpenAL32.dll"); #endif DWORD dwOpenALInstalled = GetFileAttributes(szOpenALDir); // , . , . if (dwOpenALInstalled != INVALID_FILE_ATTRIBUTES) { OpenALFound = true; }
ステップ3:ファイルが見つかりません
まず、管理者にユーザー権限を尋ねる必要があります。なぜなら、 システムディレクトリを操作する必要があります。
// , bool IsProcessWithAdminPrivilege() { SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; LPVOID pAdministratorsGroup = nullptr; BOOL bRet = FALSE; // init SID to control privileges AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsGroup); // ckeck membership CheckTokenMembership(nullptr, pAdministratorsGroup, &bRet); // clean pointer if (pAdministratorsGroup) { FreeSid(pAdministratorsGroup); pAdministratorsGroup = nullptr; } return !!bRet; } { ...// WinMain code // , if (!IsProcessWithAdminPrivilege()) { TCHAR szPathToLib[MAX_PATH] = { 0 }; GetModuleFileName(nullptr, szPathToLib, ARRAYSIZE(szPathToLib)); SHELLEXECUTEINFO shellInfo = { sizeof(SHELLEXECUTEINFO) }; shellInfo.lpVerb = TEXT("runas"); shellInfo.lpFile = szPathToLib; shellInfo.hwnd = nullptr; shellInfo.nShow = SW_NORMAL; if (ShellExecuteEx(&shellInfo)) ExitProcess(GetCurrentProcessId()); } }
ステージ2:ライブラリをシステムにコピーします
{ ... // WinMain code TCHAR szPath[MAX_PATH] = { 0 }; // GetModuleFileName(GetModuleHandle(nullptr), szPath, MAX_PATH); PathRemoveFileSpec(szPath); #ifndef UNICODE _snprintf_s(szPath, MAX_PATH * sizeof(CHAR), "%s%s", szPath, "\\OpenAL32.dll"); #else _snwprintf_s(szPath, MAX_PATH * sizeof(WCHAR), L"%s%s", szPath, L"\\OpenAL32.dll"); #endif dwOpenALInstalled = GetFileAttributes(szPath); if (dwOpenALInstalled != INVALID_FILE_ATTRIBUTES) // , { DWORD LibrarySize = 0; HANDLE hFile = CreateFile(szPath, GENERIC_READ, NULL, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); R_ASSERT(hFile != INVALID_HANDLE_VALUE); FILE_STANDARD_INFO fileInfo = { 0 }; GetFileInformationByHandleEx(hFile, FileStandardInfo, &fileInfo, sizeof(fileInfo)); LPVOID pImage = HeapAlloc(GetProcessHeap(), 0, fileInfo.EndOfFile.QuadPart); ReadFile(hFile, pImage, fileInfo.EndOfFile.QuadPart, &LibrarySize, nullptr); CloseHandle(hFile); hFile = CreateFile(szOpenALDir, GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); R_ASSERT(hFile != INVALID_HANDLE_VALUE); WriteFile(hFile, pImage, fileInfo.EndOfFile.QuadPart, &LibrarySize, nullptr); HeapFree(GetProcessHeap(), 0, pImage); CloseHandle(hFile); OpenALFound = true; // , , } }
おわりに
もちろん、この方法は非常に面白いですが、そのようなプロジェクトに適しています。 皆さんに幸運を!