I'm trying to pass some parameters to a SQL stored procedure in my classic ASP. I've seen several posts on this and not sure what I'm doing wrong as I don't seem to see my discrepancy.
set conn = CreateObject("ADODB.Connection")
conn.open ("DSN=SERVER;UID=username;PWD=pwd;Database=MyDatabase")
set cmd = Server.CreateObject("ADODB.Command")
set cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = my_proc
cmd.Parameters.Refresh
cmd.Parameters(1) = "MyParam"
set rs = cmd.execute
I'm getting the error
Arguments are of the wrong type, are out of acceptable range, or are in conflict
with one another.
on the line cmd.CommandType = adCmdStoredProc. I also tried to do it the following way with the same error
set conn = CreateObject("ADODB.Connection")
conn.open ("DSN=SERVER;UID=username;PWD=pwd;Database=MyDatabase")
set cmd = Server.CreateObject("ADODB.Command")
set cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = my_proc
cmd.Parameters.Refresh
cmd.Parameters.Append cmd.CreateParameter("#MyParam, adVarWChar, adParamInput, 50, "test")
set rs = cmd.execute
#KekuSemau is correct but let me a suggest a more efficient and manageable approach then using the adovbs constants file.
METADATA allows you to define a reference to the DLLs constants even if your using Late Binding as is the case in a Classic ASP environment. It's probably worth mentioning that you can add METADATA references in individual pages but then again why would you?
To use it simply add the METADATA tag to your global.asa file (should be located in the root of your Web Application).
<!--
METADATA TYPE="typelib" FILE="C:\Program Files\Common Files\System\ADO\msado20.tlb"
-->
Depending on the system the ADO Type Library maybe different, adjust the FILE attribute accordingly.
I use this approach in all my applications mainly for referencing constants in the ADO and CDO Type Libraries.
ADO Type Library
<!--
METADATA
TYPE="typelib"
FILE="c:\program files\common files\system\ado\msado15.dll"
-->
CDO Type Library
<!--
METADATA
TYPE="typelib"
UUID="CD000000-8B95-11D1-82DB-00C04FB1625D"
NAME="CDO for Windows 2000 Library"
-->
These are examples of my own personal references, file locations maybe different whereas UUID attributes should be exactly the same.
IMPORTANT:
Remember to remove any references to adovbs constant include file (adovbs.inc or adovbs.asp commonly) when using METADATA approach in your global.asa or you will get a
Name redefined error
Also METADATA is only available in IIS 4.0 and above.
Useful Links
Using METADATA to Import DLL Constants (Recommended reading)
You use ADO through late binding, which means that the constants like adCmdStoredProc, adParamInput etc. are unknown to your code (so they are always 0).
You can either look them up and define the ones you need as a constant in your code (or use the numbers directly, but that's not well readable if you edit the code again later).
Or take a look here on msdn - you may find a file that defines all the constants at
c:\Program Files\Common Files\System\ado\adovbc.inc.
I think there is only a very small piece that you are doing wrong:
set conn = CreateObject("ADODB.Connection")
conn.open ("DSN=SERVER;UID=username;PWD=pwd;Database=MyDatabase")
set cmd = Server.CreateObject("ADODB.Command")
set cmd.ActiveConnection = conn
cmd.CommandType = 4 ' adCmdStoredProc constant is not defined in your context
cmd.CommandText = my_proc
cmd.Parameters.Refresh
cmd.Parameters(1).value = "MyParam"
set rs = cmd.execute
The ADO constants are probably undefined, and also (but not sure) the parameter should be assign via its value property.
Related
I'm primarily an PHP developer, but I have some old ASP one of our previous developers made that broke and I can't figure out how to fix it. We have a program that sends some variables to a listener page that compares that data to registration codes an msSQL database and then lets the program know if the registration code is valid.
I'm getting the following error where
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
is line 134:
ADODB.Parameters error '800a0e7c'
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
/checkregistrationpro.asp, line 134
I've already specified any named constants in an include file that I have not included in the code, so it isn't to do with that.
My Connection String (I've already verified that these settings are right):
set conn = Server.CreateObject("ADODB.Connection")
set cmd = Server.CreateObject("ADODB.Command")
sConnString = "Provider=sqloledb; Data Source=MYDATASOURCE; Initial Catalog=MYCATALOG; User ID=MYUSERID; Password='MYPASSWORD';"
conn.Open sConnString
My Code:
...
Function BlockInjectCode(StrVal)
BlockInjectCode = Replace(StrVal,"--","")
BlockInjectCode = Replace(BlockInjectCode,"'","")
BlockInjectCode = Replace(BlockInjectCode,"""","")
if instr(lcase(BlockInjectCode),"<") > 0 then
BlockInjectCode = ""
end if
End Function
x = BlockInjectCode(Request.QueryString("rid"))
uid = BlockInjectCode(Request.QueryString("uid"))
chkcode = BlockInjectCode(Request.QueryString("Code"))
CheckPro = BlockInjectCode(Request.QueryString("pro"))
CheckProProd = BlockInjectCode(Request.QueryString("prod"))
CheckProMac = BlockInjectCode(Request.QueryString("mac"))
MacAdd = CheckProMac
CodeValid = False
if x <> "" and uid <> "" then
'-- Get information about this registration code.
sqlStr = "select * from MYTABLE where Code = ? and IsValid = 1"
set cmdCodes = Server.CreateObject("ADODB.Command")
Set cmdCodes.ActiveConnection = Conn
cmdCodes.CommandText = sqlStr
with cmdCodes
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
end With
Set rsCodes = cmdCodes.execute
...
Common occurrence is likely you do not have adVarChar defined, so the CreateParameter() method is "improperly defined".
This is just an example of one of the many named constants found in the ADODB Library. A messy approach to dealing with this is to just define the value yourself something like;
Const adVarChar = 200
The problem with this approach is you then have to define all the named constants which can be a headache. Another approach is to just skip the whole named constants thing and just use the integer values, so the call would be;
.Parameters.Append .CreateParameter("#code", 200, 1, 50, x)
However this isn't easy to read although it looks as though you are doing this already with the ParameterDirectionEnum value of 1 which is the named constant adParamInput in the ADODB Library. Regardless I wouldn't recommend this approach.
A slightly better approach is to use an #include directive so that it includes in the calling page all the named constant definitions you could want and this is how most do it. Microsoft provide a pre defined file for this very purpose with IIS (or possibly the MDAC library installation I'm not sure off the top of my head) known as adovbs.inc or adovbs.asp, by including this file your page would have access to all the named constant definitions within.
The reason for all this is VBScript doesn't support type libraries, so in a Client scenario defining them yourself or copying and pasting from the adovbs.inc file is your only option. However in a Server scenario we still have the power of IIS which lets us do some funky things.
Wouldn't it be nice if the Type Library could just be added once and you don't have to worry about it?, no annoying constants to have to define? Let's face it they already exist in the Type Library so why can't we get them from there? Well turns out we can thanks to the METADATA directive.
Here is an example;
<!--
METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"
-->
The beauty of this approach is you can use for any Type Library (ideally exposed to COM) and you can define in one page, or add it into the global.asa to have defined across the entire Web Application.
With this approach you are then safe to use code like;
.Parameters.Append .CreateParameter("#code", adVarChar, adParamInput, 50, x)
Useful Links
VBScript ADO Programming
Answer to ASP 3.0 Declare ADO Constants w/out Including ADOVBS.inc
Answer to Passing Parameters to a Stored Procedure using ASP
Using METADATA to Import DLL Constants
In the places where you are defining adVarChar, and other ADO magic numbers, get rid of them completely.
Instead add this to the top of your global.asa (create one if it doesn't) exist.
<!--METADATA TYPE="TypeLib" file="C:\Program Files (x86)\Common Files\System\ado\msado15.dll" -->
This will import the msado15 type library which already has all of those magic numbers defined. It will pull in all the defines for you automatically. Meaning you won't have to define adVarChar etc yourself, the metadata tag will import them automatically for you. Credit to #Lankymart for this as his comment lead me to discovering this and figuring it out, and it works great.
Now, turn create a test asp page that's empty and add some test code to it with option explicit on.
<%
Option Explicit
Response.Write "adVarChar: " & adVarChar
%>
If you get an error that adVarChar is not defined, then msado15.dll is not on the server. So you will need to contact godaddy etc to have them tell you the path to whatever version of MSADO is on there and change your metadata tag to reference the right version.
I'm primarily an PHP developer, but I have some old ASP one of our previous developers made that broke and I can't figure out how to fix it. We have a program that sends some variables to a listener page that compares that data to registration codes an msSQL database and then lets the program know if the registration code is valid.
I'm getting the following error where
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
is line 134:
ADODB.Parameters error '800a0e7c'
Parameter object is improperly defined. Inconsistent or incomplete information was provided.
/checkregistrationpro.asp, line 134
I've already specified any named constants in an include file that I have not included in the code, so it isn't to do with that.
My Connection String (I've already verified that these settings are right):
set conn = Server.CreateObject("ADODB.Connection")
set cmd = Server.CreateObject("ADODB.Command")
sConnString = "Provider=sqloledb; Data Source=MYDATASOURCE; Initial Catalog=MYCATALOG; User ID=MYUSERID; Password='MYPASSWORD';"
conn.Open sConnString
My Code:
...
Function BlockInjectCode(StrVal)
BlockInjectCode = Replace(StrVal,"--","")
BlockInjectCode = Replace(BlockInjectCode,"'","")
BlockInjectCode = Replace(BlockInjectCode,"""","")
if instr(lcase(BlockInjectCode),"<") > 0 then
BlockInjectCode = ""
end if
End Function
x = BlockInjectCode(Request.QueryString("rid"))
uid = BlockInjectCode(Request.QueryString("uid"))
chkcode = BlockInjectCode(Request.QueryString("Code"))
CheckPro = BlockInjectCode(Request.QueryString("pro"))
CheckProProd = BlockInjectCode(Request.QueryString("prod"))
CheckProMac = BlockInjectCode(Request.QueryString("mac"))
MacAdd = CheckProMac
CodeValid = False
if x <> "" and uid <> "" then
'-- Get information about this registration code.
sqlStr = "select * from MYTABLE where Code = ? and IsValid = 1"
set cmdCodes = Server.CreateObject("ADODB.Command")
Set cmdCodes.ActiveConnection = Conn
cmdCodes.CommandText = sqlStr
with cmdCodes
.Parameters.Append .CreateParameter("#code", adVarChar, 1, 50, x)
end With
Set rsCodes = cmdCodes.execute
...
Common occurrence is likely you do not have adVarChar defined, so the CreateParameter() method is "improperly defined".
This is just an example of one of the many named constants found in the ADODB Library. A messy approach to dealing with this is to just define the value yourself something like;
Const adVarChar = 200
The problem with this approach is you then have to define all the named constants which can be a headache. Another approach is to just skip the whole named constants thing and just use the integer values, so the call would be;
.Parameters.Append .CreateParameter("#code", 200, 1, 50, x)
However this isn't easy to read although it looks as though you are doing this already with the ParameterDirectionEnum value of 1 which is the named constant adParamInput in the ADODB Library. Regardless I wouldn't recommend this approach.
A slightly better approach is to use an #include directive so that it includes in the calling page all the named constant definitions you could want and this is how most do it. Microsoft provide a pre defined file for this very purpose with IIS (or possibly the MDAC library installation I'm not sure off the top of my head) known as adovbs.inc or adovbs.asp, by including this file your page would have access to all the named constant definitions within.
The reason for all this is VBScript doesn't support type libraries, so in a Client scenario defining them yourself or copying and pasting from the adovbs.inc file is your only option. However in a Server scenario we still have the power of IIS which lets us do some funky things.
Wouldn't it be nice if the Type Library could just be added once and you don't have to worry about it?, no annoying constants to have to define? Let's face it they already exist in the Type Library so why can't we get them from there? Well turns out we can thanks to the METADATA directive.
Here is an example;
<!--
METADATA
TYPE="TypeLib"
NAME="Microsoft ActiveX Data Objects 2.5 Library"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"
VERSION="2.5"
-->
The beauty of this approach is you can use for any Type Library (ideally exposed to COM) and you can define in one page, or add it into the global.asa to have defined across the entire Web Application.
With this approach you are then safe to use code like;
.Parameters.Append .CreateParameter("#code", adVarChar, adParamInput, 50, x)
Useful Links
VBScript ADO Programming
Answer to ASP 3.0 Declare ADO Constants w/out Including ADOVBS.inc
Answer to Passing Parameters to a Stored Procedure using ASP
Using METADATA to Import DLL Constants
In the places where you are defining adVarChar, and other ADO magic numbers, get rid of them completely.
Instead add this to the top of your global.asa (create one if it doesn't) exist.
<!--METADATA TYPE="TypeLib" file="C:\Program Files (x86)\Common Files\System\ado\msado15.dll" -->
This will import the msado15 type library which already has all of those magic numbers defined. It will pull in all the defines for you automatically. Meaning you won't have to define adVarChar etc yourself, the metadata tag will import them automatically for you. Credit to #Lankymart for this as his comment lead me to discovering this and figuring it out, and it works great.
Now, turn create a test asp page that's empty and add some test code to it with option explicit on.
<%
Option Explicit
Response.Write "adVarChar: " & adVarChar
%>
If you get an error that adVarChar is not defined, then msado15.dll is not on the server. So you will need to contact godaddy etc to have them tell you the path to whatever version of MSADO is on there and change your metadata tag to reference the right version.
I am trying to link an Oracle table to access using the following Visual Basic 6.0 code:
Dim objApp, objDB, objTable As Object
Dim strFile, strConnect, strLocalTable, strServerTable As String
strFile = "C:\path\to\base.mdb"
strLocalTable = "local"
strServerTable = "BASE.TABLE_NAME"
strConnect = "ODBC;Driver={Microsoft ODBC for Oracle};ConnectString=name.world;Uid=username;Pwd=password;"
Set objApp = CreateObject("Access.Application")
objApp.OpenCurrentDatabase strFile
Set objDB = objApp.CurrentDb()
Set objTable = objDB.CreateTableDef(strLocalTable)
objTable.Connect = strConnect
objTable.SourceTableName = strServerTable
objDB.TableDefs.Append objTable 'Generates 3000 Error
objDB.TableDefs.Refresh
On the second to last row I get (loosely translated from swedish by me) "Run time error 3000: Reserved error (-7778). There is no message for this error."
Any ideas on why this may be? I am told this code has worked before, so it could possibly be some kind of version conflict with updated software. The database is in Access 2000 format, and Access 2013 is installed on the computer (however, saving the database as Access 2013 does not help). Or is there something wrong with the connection string perhaps?
EDIT: I tried using a DSN in the connection string:
strConnect = "ODBC;Driver={Microsoft ODBC for Oracle};DSN='test';"
I get the same error, even though I can use that very DSN to link the tables manually in Access.
Also (as I stated in the comments) changing some of the information in the connection string (like deliberately providing an incorrect username) leads to a different error (3146: Connection failed). This leads me to believe that the connection to the database works, since it seems to be able to differentiate between good and bad credentials.
Try this connection string and leave out the 'world.' part
ODBC;DRIVER={Oracle in orahome32};UID=userId;PWD=password;SERVER=servername;dbq=servername
(I was having trouble earlier today with connections that left the dbq out)
Or maybe your existing one will work, but regardless...I think Access likes you to create the table default in one swoop and not break things up so.....
Instead of this:
Set objTable = objDB.CreateTableDef(strLocalTable)
objTable.Connect = strConnect
objTable.SourceTableName = strServerTable
Try This:
Set objTable = objDB.CreateTableDef(strLocalTable, dbAttachSavePWD, strServerTable, strConnect)
(NOTE: the dbAttachSavePWD will help avoid users getting prompted for password every time they touch the table; leave it out if that is not desired)
I've been looking for a way to get Active Directory's LDAP server url from code running as domain user. The code needs to work correctly in situation with disjoint namespace, if possible. It's unmanaged code so any .NET solutions are not an option unfortunately.
For some reason serverless binding doesn't seem to be working in this case with ADO query returning unhelpful One or more errors occurred during processing of command error when using LDAP://DC=mycompany,DC=local (that's the value of the defaultNamingContext attribute of rootDSE object).
Using the LOGONSERVER and USERDNSDOMAIN environment variables doesn't appear to be an option either because the code also needs to be able to run under the SYSTEM account and there are no such variables there.
Any ideas or hints or specific RTFM advice will be much appreciated.
Update: The DNSHostName attribute of rootDSE seems to be what I need.
I use this Visual Basic Script (VBS). Save the code as .vbs file and use ANSI charset. This script is old, but this can guide you to a better solution.
Set cn = CreateObject("ADODB.Connection")
Set cmd= CreateObject("ADODB.Command")
cn.Provider = "ADsDSOObject;"
cn.open
cmd.ActiveConnection = cn
' Root DSE required to get the default configuration naming context to
' be used as the root of the seach
set objRootDSE = getobject("LDAP://RootDSE")
' Construct the LDAP query that will find all the domain controllers
' in the domain
ldapQuery = "<LDAP://" & objRootDSE.Get("ConfigurationNamingContext") & _
">;((objectClass=nTDSDSA));ADsPath;subtree"
cmd.CommandText = ldapQuery
cmd.Properties("Page Size") = 1000
Set rs = cmd.Execute
do while rs.EOF <> True and rs.BOF <> True
' Bind to the domain controller computer object
' (This is the parent object of the result from the query)
set objDC = getobject(getobject(rs(0)).Parent)
wscript.echo objDC.dNSHostName
rs.MoveNext
Loop
cn.close
The DNSHostName attribute of rootDSE seems to be what I need.
I am trying to get a user's SIP address so I can use a JavaScript object to check their presence in Office Communicator. Here is a script I found that is similar to what I am looking to do.
Option Explicit
DIM objConnection, objCommand
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
Dim objOU, objUser, strUPN, strSIP, SIPLine
' Bind to the OU object.
Set objOU = GetObject("LDAP://chkenergy.net/DC=chkenergy,DC=net")
' Enumerate all users in the OU.
objOU.Filter = Array("user")
For Each objUser In objOU
' Skip computer objects.
If (objUser.Class = "user") Then
strUPN = objUser.userPrincipalName
strSIP = objUser.get("msRTCSIP-PrimaryUserAddress")
wscript.echo strSIP
End If
Next
Basically, I can get their username from AD, and I would like to pass that in and get their SIP address (strSIP) back. Is there a way to fix this code to do that task specifically?
The problems of your posted vbscript are
It enumerates the user on the client side, which will take a lot of time to find the correct user. Similarly, instead of pulling all the records from the database and do the comparison on your client side, you would run a SQL query. Right?
The enumeration is done at one single level only. You have to fix your code to do recursive enumeration. However, if you fix it to do recursive enumeration, it's going to take even longer time and even more resources to do your job.
Before I answer your question, here are some basic background knowlege on Active Directory.
User objects on Active Directory contains a number of attributes.
In particular, samAccountName is your pre-Windows 2000 name.
userPrincipalName is in the format of user#domain.name
You can actully execute a query using an ADO connection object. Since you are binded to an Active Directory, you can execute a LDAP query. The LDAP query string contains four parts.
Root path, where we start the search.
LDAP filter
Returned attributes
Search scope
The LDAP query string that you should use should be something like
<LDAP://chkenergy.net/DC=chkenergy,DC=net>;(&(objectClass=user)(samAccountName=yourusername));msRTCSIP-PrimaryUserAddress;subtree
The root path in the above example is <LDAP://chkenergy.net/DC=chkenergy,DC=net>.
The LDAP filter is (&(objectClass=user)(samAccountName=yourusername)). Of course, you need to replace yourusername to something else inside your code. I am assuming you can pass in a samAccountName. If that's not the case, you need to modify the filter yourself.
Returned attributes is msRTCSIP-PrimaryUserAddress. I think that's what you need. Right?
I am assuming you are trying to search for all user objects under the same domain. So, your search scope should be subtree
Here is a complete sample that I guess it should do your job
userName = "harvey"
ldapStr = "<LDAP://chkenergy.net/DC=chkenergy,DC=net>;(&(objectClass=user)(samAccountName=" & userName & "));msRTCSIP-PrimaryUserAddress;subtree"
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "ADSDSOObject"
conn.Open "ADs Provider"
Set rs = conn.Execute(ldapStr)
While Not rs.EOF
wscript.echo rs.Fields("msRTCSIP-PrimaryUserAddress")
rs.MoveNext
Wend