{"id":69443,"date":"2005-07-07T15:09:00","date_gmt":"2005-07-07T15:09:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2005\/07\/07\/how-can-i-get-a-list-of-the-odbc-drivers-that-are-installed-on-a-computer\/"},"modified":"2005-07-07T15:09:00","modified_gmt":"2005-07-07T15:09:00","slug":"how-can-i-get-a-list-of-the-odbc-drivers-that-are-installed-on-a-computer","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-get-a-list-of-the-odbc-drivers-that-are-installed-on-a-computer\/","title":{"rendered":"How Can I Get a List of the ODBC Drivers that are Installed on a Computer?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hey, Scripting Guy! How can I get a list of the ODBC drivers that are installed on a computer?<BR><BR>&#8212; VV<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, VV. This is one of those questions that end up driving us crazy. That\u2019s because it: a) seems so simple and, b) <I>appears<\/I> as though there are a number of ways to get this information. For example, on our Windows XP computer we have no fewer than eight WMI classes than include the acronymn <I>ODBC<\/I> somewhere in the class name. Surely <I>one<\/I> of those classes will return a list of installed drivers, right?<\/P>\n<P>Wrong. What we\u2019re trying to get at is the information found on the <B>Drivers<\/B> tab of the <B>ODBC Data Source Administrator<\/B> dialog box:<\/P><IMG border=\"0\" alt=\"ODBC Drivers\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/odbc1.jpg\" width=\"375\" height=\"312\"> \n<P><BR>But none of the WMI classes seem to return that information, at least not directly. (There might be a convoluted way of getting at this information, but we Scripting Guys try to avoid convoluted ways whenever possible.) All hope seemed lost, but then one of the Scripting Guys decided to apply the Upstairs Closet theory to the problem. In this particular Scripting Home, any time something is lost you can almost bet that it will be found in the upstairs closet, even though the item should have never been thrown into the closet and even though everyone in the house solemnly swears that <I>they<\/I> didn\u2019t put it there. <\/P>\n<TABLE id=\"EWD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. Befitting his status as father, this Scripting Guy used to say sarcastically, \u201cWell, it didn\u2019t just walk there itself, did it?\u201d Now, 11 years later, he\u2019s beginning to think that maybe these lost items <I>do<\/I> just walk there themselves.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>The registry, as you doubtless know, is the upstairs closet of the operating system: if you\u2019re willing to look, you can find almost anything in the registry. And, sure enough, that\u2019s where we found the list of installed ODBC drivers, in HKEY_LOCAL_MACHINE\\SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers. (Oddly enough, we also found a pair of shoes, that jacket that we always liked, and a hacksaw that disappeared 5 or 6 years ago.)<\/P>\n<P>As soon as we knew we could get this information out of the registry it was easy to write a script that retrieved a list of all the installed ODBC drivers:<\/P><PRE class=\"codeSample\">Const HKEY_LOCAL_MACHINE = &amp;H80000002<\/p>\n<p>strComputer = &#8220;.&#8221;<\/p>\n<p>Set objRegistry = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\default:StdRegProv&#8221;)<\/p>\n<p>strKeyPath = &#8220;SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers&#8221;\nobjRegistry.EnumValues HKEY_LOCAL_MACHINE, strKeyPath, arrValueNames, arrValueTypes<\/p>\n<p>For i = 0 to UBound(arrValueNames)\n    strValueName = arrValueNames(i)\n    objRegistry.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue    \n    Wscript.Echo arrValueNames(i) &amp; &#8221; &#8212; &#8221; &amp; strValue\nNext\n<\/PRE>\n<P>We begin by defining a constant named HKEY_LOCAL_MACHINE and setting the value to &amp;H80000002; we\u2019ll use this constant to indicate that we want to work with the HKEY_LOCAL_MACHINE registry hive. We connect to the WMI service and to the standard registry provider (<B>root\\default:StdRegProv<\/B>), then use this line of code to assign the registry path within HKEY_LOCAL_MACHINE to the variable strKeyPath:<\/P><PRE class=\"codeSample\">strKeyPath = &#8220;SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers&#8221;\n<\/PRE>\n<P>As it turns out, the installed ODBC drivers are stored as individual registry values within this registry key, something like this:<\/P><IMG border=\"0\" alt=\"ODBC Drivers\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/odbc2.jpg\" width=\"375\" height=\"228\"> \n<P><BR>Therefore, to retrieve a collection of all these registry values we need to call the <B>EnumValues<\/B> method, a method which automatically grabs all the values within a specified key:<\/P><PRE class=\"codeSample\">objRegistry.EnumValues HKEY_LOCAL_MACHINE, strKeyPath, arrValueNames, arrValueTypes\n<\/PRE>\n<P>When we call EnumValues we need to supply two in parameters and two out parameters. \u201cIn parameters\u201d are values we supply to the method; in this script we pass the constant HKEY_LOCAL_MACHINE and the variable strKeyPath. Taken together, these parameters tell the script which registry key we\u2019re working with. <\/P>\n<P>\u201cOut parameters\u201d represent information that the method provides to us. To get this information all we have to do is provide a pair of variable names. In our script, the variable arrValueNames will end up holding an array of all the registry value names found in SOFTWARE\\ODBC\\ODBCINST.INI\\ODBC Drivers; the variable arrValueTypes will hold an array of data types for each of these registry values. (We\u2019re including this particular parameter only because it\u2019s required. Because all our registry values have the same data type &#8211; REG_SZ &#8211; we don\u2019t need to worry about data types and thus won\u2019t use arrValueTypes.)<\/P>\n<P>After calling EnumValues all the individual registry value names will be stored (as an array) in the variable arrValueNames. To access those values we need to set up a For-Next loop that runs from 0 to the last item (the upper bound or UBound) in the array. (As you know, in VBScript the first item in an array is always item 0.) That\u2019s what this line of code does:<\/P><PRE class=\"codeSample\">For i = 0 to UBound(arrValueNames)\n<\/PRE>\n<P>Inside the loop, we assign the name of the first registry value to a variable named strValueName:<\/P><PRE class=\"codeSample\">strValueName = arrValueNames(i)\n<\/PRE>\n<P>We do that because, at the moment, all we have are the <I>names<\/I> of the individual registry values. To actually get the values that have been assigned to those registry entries we need to call the <B>GetStringValue<\/B> method, something we do here:<\/P><PRE class=\"codeSample\">objRegistry.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue\n<\/PRE>\n<P>As you can see, we pass GetStringValue four parameters:<\/P>\n<TABLE border=\"0\" cellSpacing=\"0\" cellPadding=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>HKEY_LOCAL_MACHINE, representing the registry hive.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>strKeyPath, the registry path within HKEY_LOCAL_MACHINE.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>strValueName, representing the individual registry value.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>strValue, an out parameter which will store the value of the registry entry.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>After that we can simply use this line of code to echo back the name of the registry value and the value assigned to it:<\/P><PRE class=\"codeSample\">Wscript.Echo arrValueNames(i) &amp; &#8221; &#8212; &#8221; &amp; strValue\n<\/PRE>\n<P>And when we run the script, we\u2019ll get back output similar to this:<\/P><PRE class=\"codeSample\">SQL Server &#8212; Installed\nMicrosoft Access Driver (*.mdb) &#8212; Installed\nMicrosoft Text Driver (*.txt; *.csv) &#8212; Installed\nMicrosoft Excel Driver (*.xls) &#8212; Installed\nMicrosoft dBase Driver (*.dbf) &#8212; Installed\nMicrosoft Paradox Driver (*.db ) &#8211; Installed\n<\/PRE>\n<P>Might not have been as straightforward as we would have liked but you know what they say: a list of installed ODBC drivers is a list of installed ODBC drivers. (We\u2019re not sure why they say that, but at least in this case it makes some sense.)<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I get a list of the ODBC drivers that are installed on a computer?&#8212; VV Hey, VV. This is one of those questions that end up driving us crazy. That\u2019s because it: a) seems so simple and, b) appears as though there are a number of ways to get this [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[146,669,26,3,5,6],"class_list":["post-69443","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-databases","tag-odbc","tag-registry","tag-scripting-guy","tag-vbscript","tag-wmi"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I get a list of the ODBC drivers that are installed on a computer?&#8212; VV Hey, VV. This is one of those questions that end up driving us crazy. That\u2019s because it: a) seems so simple and, b) appears as though there are a number of ways to get this [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/69443","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=69443"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/69443\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=69443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=69443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=69443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}