Custom error message when Visual Studio distributable package is not installed on Windows · Issue #48 · oracle/odpi (original) (raw)
How about custom error message when Visual Studio distributable package is not installed?
IMO, oracle/node-oracledb#404 (comment) should be checked in ODPI-C.
When GetLastError() returns ERROR_MOD_NOT_FOUND(The specified module could not be found), do the following.
- Search OCI.DLL in the following directories in this order:
- Executable directory (Get the full path of the executable by
GetModuleFileName(NULL, buf, sizeof(buf))
and truncate the file name.) - Current directory
- each directory in the environment variable
PATH
.
- Executable directory (Get the full path of the executable by
- If OCI.DLL is not found, use the message from FormatMessage().
- If OCI.DLL is found, get the bit of the DLL (see the function below) and skip if it isn't same with the executable.
- If step 3 passes, get import DLL files (see the function below) and get the DLL whose name is 'MSVCR*.DLL'.
- Call LoadLibrary with the 'MSVCR*.DLL' at step 4.
- If step 5 fails, map the 'MSVCR*.DLL' name to VS distributable package name and create a custom error message.
The following is a sample function which prints bit and dependent DLL files.
It is easy to customize this to fit this issue's need.
// link dbghelp.lib also #include <dbghelp.h>
static void print_import_dlls(const char *name) { HANDLE hFile = CreateFile(name, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE hFileMapping = NULL; void *base = NULL; if (hFile == INVALID_HANDLE_VALUE) { printf("failed to open: %s\n", name); return; } hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hFileMapping == NULL) { printf("failed to create file mapping: %s\n", name); goto cleanup; } base = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); if (base == NULL) { printf("failed to map file: %s\n", name); goto cleanup; } IMAGE_NT_HEADERS *nt_hdr = ImageNtHeader(base); if (nt_hdr == NULL) { printf("not executable nor DLL: %s\n", name); goto cleanup; }
printf("%s (%s bit):\n", name, nt_hdr->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 ? "32" : "64");
ULONG uSize = 0;
IMAGE_IMPORT_DESCRIPTOR *desc = (IMAGE_IMPORT_DESCRIPTOR *)ImageDirectoryEntryToDataEx(base, FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &uSize, NULL);
while (desc->Characteristics != 0) {
char *name = (char*)ImageRvaToVa(nt_hdr, base, desc->Name, NULL);
printf(" %s\n", name);
desc++;
}
cleanup: if (base != NULL) { UnmapViewOfFile(base); } if (hFileMapping != NULL) { CloseHandle(hFileMapping); } CloseHandle(hFile); }