Created
May 15, 2017 17:40
-
-
Save jmelosegui/0e644c11f8d092078b904935ab122784 to your computer and use it in GitHub Desktop.
P/Invoke Odbccp32
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Odbccp32 | |
{ | |
/// <summary> | |
/// From sql.h | |
/// </summary> | |
private const int SQL_MAX_MESSAGE_LENGTH = 512; | |
[DllImport(nameof(Odbccp32), CharSet = CharSet.Unicode, SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool SQLGetInstalledDrivers(char[] lpszBuf, ushort cbufMax, out ushort pcbBufOut); | |
[DllImport(nameof(Odbccp32))] | |
public static extern SqlReturnCode SQLInstallerError(int iError, out SqlInstallerErrorCode pfErrorCode, StringBuilder lpszErrorMsg, int cbErrorMsgMax, out int pcbErrorMsg); | |
public static string[] GetOdbcDriverNames() | |
{ | |
string[] odbcDriverNames = null; | |
char[] driverNamesBuffer = new char[ushort.MaxValue]; | |
ushort size; | |
bool succeeded = SQLGetInstalledDrivers(driverNamesBuffer, ushort.MaxValue, out size); | |
if (!succeeded) | |
{ | |
string message = GetErrorMessage(); | |
throw new ApplicationException($"Error within a PIvoke call. {message}"); | |
} | |
char[] driverNames = new char[size - 1]; | |
Array.Copy(driverNamesBuffer, driverNames, size - 1); | |
odbcDriverNames = (new string(driverNames)).Split('\0'); | |
return odbcDriverNames; | |
} | |
public static bool IsSqlServer2016DriverInstalled() | |
{ | |
return true; //GetOdbcDriverNames().Any(d => d.Equals("ODBC Driver 13 for SQL Server", StringComparison.OrdinalIgnoreCase)); | |
} | |
private static string GetErrorMessage() | |
{ | |
StringBuilder result = new StringBuilder(); | |
SqlInstallerErrorCode pfErrorCode; | |
int bufferSizeNeeded; | |
int errorRecord = 1; | |
SqlReturnCode returnCode = SQLInstallerError(errorRecord, out pfErrorCode, result, SQL_MAX_MESSAGE_LENGTH, out bufferSizeNeeded); | |
if (returnCode == SqlReturnCode.SQL_SUCCESS_WITH_INFO) | |
{ | |
while (bufferSizeNeeded >= SQL_MAX_MESSAGE_LENGTH) | |
{ | |
StringBuilder partialMessage = new StringBuilder(); | |
returnCode = SQLInstallerError(++errorRecord, out pfErrorCode, partialMessage, SQL_MAX_MESSAGE_LENGTH, out bufferSizeNeeded); | |
if (returnCode != SqlReturnCode.SQL_NO_DATA) | |
{ | |
result.Append(partialMessage); | |
} | |
} | |
} | |
if (returnCode == SqlReturnCode.SQL_ERROR) | |
{ | |
result.Append("SQLInstallerError cannot access error values"); | |
} | |
return result.ToString(); | |
} | |
} | |
/// <summary> | |
/// From sql.h | |
/// </summary> | |
public enum SqlReturnCode | |
{ | |
SQL_ERROR = -1, | |
SQL_SUCCESS = 0, | |
SQL_SUCCESS_WITH_INFO = 1, | |
SQL_NO_DATA = 100 | |
} | |
/// <summary> | |
/// From odbcinst.h | |
/// </summary> | |
public enum SqlInstallerErrorCode | |
{ | |
ODBC_ERROR_GENERAL_ERR = 1, | |
ODBC_ERROR_INVALID_BUFF_LEN = 2, | |
ODBC_ERROR_COMPONENT_NOT_FOUND = 6, | |
ODBC_ERROR_OUT_OF_MEM = 21 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment