Having a BOF or EOF error, after call recordCount - asp-classic

I have to call recordCount function to get the count of recordset.
But once I call recordCount function, the recordset is out of control.
...
Dim objRootDSE, strDNSDomain, adoCommand, adoConnection
Set adoCommand = CreateObject("ADODB.Command")
'Set adoRecordset = adoCommand.Execute
Set adoRecordset = Server.CreateObject ("ADODB.Recordset")
adoRecordset.cursorType = 3
adoRecordset.CursorLocation = adUseClient
adoRecordset = adoCommand.Execute
...
totalcnt = adoRecordset.recordCount
If totalcnt > 0 Then
...
Do until adoRecordset.EOF
' Retrieve values... But it fails because it seems adoRecordset is in EOF
...
So I use movefirst and try to retrieve values.
If adoRecordset.recordCount > 0 Then
adoRecordset.movefirst
...
But it occurs an error(below is translated by google)
ADODB.Recordset 오류 '800a0bcd'
BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.
If I didn't call recordCount, there's no problem. But I should know the count of record.
The whole code is :
<%
'On Error Resume next
Dim objRootDSE, strDNSDomain, adoCommand, adoConnection
Dim strBase, strFilter, strAttributes, strQuery, adoRecordset
Dim strDN, strUser, strPassword, objNS, strServer
Dim name,company,physicalDeliveryOfficeName
Const ADS_SECURE_AUTHENTICATION = 1
Const ADS_SERVER_BIND = 0
' Specify a server (Domain Controller).
strServer = "my_ad_server_domain"
' Specify or prompt for credentials.
strUser = "my_account"
strPassword = "my_passwrd"
' Determine DNS domain name. Use server binding and alternate
' credentials. The value of strDNSDomain can also be hard coded.
Set objNS = GetObject("LDAP:")
Set objRootDSE = objNS.OpenDSObject("LDAP://" & strServer & "/RootDSE", _
strUser, strPassword, _
ADS_SERVER_BIND Or ADS_SECURE_AUTHENTICATION)
strDNSDomain = objRootDSE.Get("defaultNamingContext")
' Use ADO to search Active Directory.
' Use alternate credentials.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Properties("User ID") = strUser
adoConnection.Properties("Password") = strPassword
adoConnection.Properties("Encrypt Password") = True
adoConnection.Properties("ADSI Flag") = ADS_SERVER_BIND _
Or ADS_SECURE_AUTHENTICATION
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
' Search entire domain. Use server binding.
strBase = "<LDAP://" & strServer & "/" & strDNSDomain & ">"
' Search for all users.
strFilter = "(&(objectCategory=user)(ExADObjectStatus=10)(samaccountname=*"&"my_search_value"&"*))"
' Comma delimited list of attribute values to retrieve.
strAttributes = "name,company,physicalDeliveryOfficeName"
' Construct the LDAP query.
strQuery = strBase & ";" & strFilter & ";" _
& strAttributes & ";subtree"
' Run the query.
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 60
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
if not adoRecordset.EOF then
totalcnt = adoRecordset.recordCount
If totalcnt > 0 Then
Response.write 111
Do until adoRecordset.EOF
name = adoRecordset.Fields("name").Value
company = adoRecordset.Fields("company").Value
physicalDeliveryOfficeName = adoRecordset.Fields("physicalDeliveryOfficeName").Value
Response.Write name & "<br/>"
Response.Write company & "<br/>"
Response.Write physicalDeliveryOfficeName
adoRecordset.MoveNext
Loop
end if
end if
' Clean up.
adoRecordset.Close
adoConnection.Close
%>
It shows only one result of record.

You can try to face the problem from a different angle. Instead of trying to fix the internal recordCount property (which you can't) simply count the records yourself:
totalcnt = 0
Do until adoRecordset.EOF
totalcnt = totalcnt + 1
adoRecordset.MoveNext
Loop
If totalcnt>0 Then
adoRecordset.MoveFirst
Do until adoRecordset.EOF
name = adoRecordset.Fields("name").Value
'...
adoRecordset.MoveNext
Loop
End If
Update: Looks like in that specific case, the MoveFirst just fails, maybe because it's LDAP and not ordinary query from a database. To bust this once and for all, you can populate your own collection when iterating the records then use that collection as much as you like:
Dim oData, oField, tempArray
Set oData = Server.CreateObject("Scripting.Dictionary")
totalcnt = 0
For Each oField In adoRecordset.Fields
oData.Add oField.Name, Array()
Next
Do until adoRecordset.EOF
For Each oField In adoRecordset.Fields
tempArray = oData(oField.Name)
ReDim Preserve tempArray(UBound(tempArray) + 1)
tempArray(UBound(tempArray)) = oField.Value
oData(oField.Name) = tempArray
Next
totalcnt = totalcnt + 1
adoRecordset.MoveNext
Loop
adoRecordset.Close
Dim x
If totalcnt>0 Then
Response.Write("found total of " & totalcnt & " records<br />")
For x=0 To totalcnt-1
name = oData("name")(x)
company = oData("company")(x)
physicalDeliveryOfficeName = oData("physicalDeliveryOfficeName")(x)
Response.Write name & "<br/>"
Response.Write company & "<br/>"
Response.Write physicalDeliveryOfficeName
Next
End If

As the error indicates, the recordCount fails if you have no records in the recordset.
You can test for this before your code block. Try this:
if not adoRecordset.EOF then
totalcnt = adoRecordset.recordCount
If totalcnt > 0 Then
...
Do while not adoRecordset.EOF
...
Loop
end if
end if
edit: Corrected the loop to test for not adoRecordset.eof

Related

I need help parameterizing some VBScript code in an .asp file

Here is a snippet of what I'm working on. Please let me know if I need to post more:
<% # LANGUAGE = VBScript ENABLESESSIONSTATE = False %>
<!--#include file="Connections/ConnectionString.asp" -->
<!--#include file="SqlCheckInclude.asp" -->
<%
Dim LoginTest
LoginTest = ""
If Request.QueryString("Action") = "Login" Then
Dim IsUserNameLocked
Set IsUserNameLocked = Server.CreateObject("ADODB.Recordset")
IsUserNameLocked.ActiveConnection = ConnectionString
sProUserName = Request.Form("ProUserName")
sanitizedProUserName = "'" & Replace(sProUserName, "'", "''") & "'"
Response.Write(sanitizedProUserName)
Response.End()
IsUserNameLocked.Source = "SELECT IL_Date, IL_Timer, IL_NumOfTimes, ProUserName FROM PROFILE WHERE ProUserName =" & sanitizedProUserName
IsUserNameLocked.CursorType = 2
IsUserNameLocked.CursorLocation = 3
IsUserNameLocked.LockType = 3
IsUserNameLocked.Open
if not IsUserNameLocked.eof then
intNumOfIncorrectLogin = IsUserNameLocked("IL_NumOfTimes")
InCorrectLoginDate = IsUserNameLocked("IL_Date")
InCorrectLoginTime = IsUserNameLocked("IL_Timer")
end if
IsUserNameLocked.close
set IsUserNameLocked = nothing
end if
%>
I attempted to convert it to:
If Request.QueryString("Action") = "Login" Then
Dim IsUserNameLocked
Set IsUserNameLocked = Server.CreateObject("ADODB.Recordset")
IsUserNameLocked.ActiveConnection = ConnectionString
strSql = "SELECT IL_Date, IL_Timer, IL_NumOfTimes, ProUserName FROM PROFILE WHERE ProUserName = ?"
strSearch = Request.Form("ProUserName")
set objCommand = Server.CreateObject("ADODB.Command")
objCommand.ActiveConnection = ConnectionString
objCommand.CommandText = strSql
objCommand.Parameters(0).value = strSearch
IsUserNameLocked.results = objCommand.Execute()
IsUserNameLocked.CursorType = 2
IsUserNameLocked.CursorLocation = 3
IsUserNameLocked.LockType = 3
IsUserNameLocked.Open
end if
But this did not work. I have been searching online for the past few hours attempting to find a method that properly works, but I'm getting no functioning results. If someone could please help with an implementation that properly parameterizes and protects against SQL injection, I would be extremely grateful.
According to the docs, you need to .Append a parameter to a Command's parameter collection. Evidence:
>> Set oCmd = CreateObject("ADODB.Command")
>> WScript.Echo "# parameters", oCmd.Parameters.Count
>> oCmd.Parameters(0).Value = "no such thing"
>>
# parameters 0
Error Number: 3265
Error Description: Item cannot be found in the collection corresponding to the requested name or ordinal.
Do you use a global On Error Resume Next?

VBscript search sAMAccountName from CN

I've written this script which pulls the sAMAccountName of the specified user from the AD via VBscript, but it seems to only work within my own OU group. Is this due to a permissions restriction within my company? Or is this due to something i'm not seeing in the code?
Dim result
result = getsAMAccountName("Some Name")
msgbox result
Function getsAMAccountName(name)
Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strsAM, objUser
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
msgbox strDNSDomain
strBase = "<LDAP://" & strDNSDomain & ">"
'be sure passed var usersel is referenced properly
strFilter = "(cn=" & name & ")"
strAttributes = "distinguishedName"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
Do Until adoRecordset.EOF
strsAM = adoRecordset.Fields("distinguishedName").Value
Set objUser = GetObject("LDAP://" & strsAM)
getsAMAccountName = objUser.sAMAccountName
adoRecordset.MoveNext
Loop
adoRecordset.Close
adoConnection.Close
End Function
Does it work when you specify the OU in your GetObject call?
GetObject("LDAP://OU=YourOU,DC=YourDomain,DC=com")
From this question Querying Active Directory using VBScript
Ended up being permissions, be sure to include/specify a processID and PW when moving LDAP pulls to asp classic... and avoid asp classic
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
With adoConnection
.Properties("User ID") = ' Process ID goes
.Properties("Password") = 'password
.Properties("encrypt password") = True
End With
adoConnection.Open "Active Directory Provider"
Set adoCommand = CreateObject("ADODB.Command")
Set adoCommand.ActiveConnection = adoConnection

Read the values stored in text file separated by comma and display them one by one in classic asp

I have a text file having three fields category name, image name and link or URL. The three fields are stored in the text file separated by comma. I want to read the textfile values and display them one by one that is in a column format. So all the category names will be displayed in one column, image name in one column and link in one column.
I have read the text file and i get all the contents in text file in a variable. The content that i get in variable is as follows:
glass,glassbowlcategory.jpg,www.google.com glass,glassbowlcategory.jpg,www.google.com glass bowl,images1.jpg,http://www.fitnessfirstusa.com/catalog.asp?Brand=LG%20Sciences
In the above string first one is category name, second is image name and third is link.
I have used the folllowing code to read text file.
Sub BuildFileList(strFolder)
Dim strFileName1
Dim strSearchText
Dim objFSO, objTextFile
Dim strReadLineText
Dim intLineNumber,strNewContents
Dim strLineNumbers
Dim objFile
' Name of text file to search:
'
'strFileName = "readme.txt"
strFileName1 = "saveimagename.txt"
Const ForReading = 1
Const ForWriting = 2
'' Create an instance of the the File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile(Server.MapPath(strFileName1))
intLineNumber = 0
'
strLineNumbers = ""
Do While Not objTextFile.AtEndOfStream
intLineNumber = intLineNumber + 1
strReadLineText = objTextFile.ReadLine
' response.Write(strReadLineText)
strNewContents = strNewContents & strReadLineText & vbCrLf
response.Write(strNewContents)
'
Loop
end sub
Please advise how can i split the contents that i get in the variable and display them
For tabular data
Const ForReading = 1
Const ForWriting = 2
Dim objTextFile
Dim intLineNumber, strNewContents, strReadLineText
dim data, columns
strFileName1 = "saveimagename.txt"
Set objTextFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(Server.MapPath(strFileName1))
intLineNumber = 0
strLineNumbers = ""
data = split(objTextFile.readall(), vbcrlf)
for intLineNumber = 0 to ubound(data)
columns = split(data(intLineNumber), ",", 3)
if (ubound(columns) = 2) then
strNewContents = strNewContents & "<tr><td>" & columns(0) & "</td><td>" & columns(1) & "</td><td>" & columns(2) & "</td></tr>" & vbcrlf
end if
next
response.write "<table>" & strNewContents & "</table>"
perhaps you could use Microsoft ActiveX Database Objects (ADO) for that?
here are some links:
Much ADO about Text Files
Microsoft ODBC Desktop Database Drivers
and some sample code:
'http://msdn.microsoft.com/en-us/library/ms974559.aspx
dim conn : set conn = server.createObject("ADODB.Connection")
dim rs : set rs = server.createObject("adodb.recordset")
dim sql
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
importPath & ";" &_
"Extended Properties=""text;HDR=" & HDR & ";FMT=Delimited"""
sql = "SELECT * FROM " & myImportFile
rs.open sql, conn, adOpenStatic, adLockOptimistic, adCmdText

Copy records to another recordset using Active Server Page

I'm programming in Classic ASP. I'm trying to do the paging. My backend is SQL CE 3.5. Unfortunetly, it doesn't support paging in SQL Query (Like row_number() in sql server).
So I go with ASP Paging. But when i ask to the recordset, give me the first 10 records by setting the rs.PageSize and rs.AbsolutePage and all, it gives me all records. So I planned to copy only first 10 rows from the resultant recordset to another new recordset. So I coded like below:
Set rsTemp = CopyRecordsetStructure(objRs)
rsTemp.Open
iRecordsShown = 0
Set objFields = objRs.Fields
intFieldsCount = objFields.Count-1
Do While iRecordsShown < intPageSize And Not objRs.EOF
rsTemp.AddNew
For Idx = 0 To intFieldsCount
rsTemp.Fields(Idx).Value = objRs.Fields(Idx).Value
Next
rsTemp.Update
iRecordsShown = iRecordsShown + 1
objRs.MoveNext
Loop
Public Function CopyRecordsetStructure(ByVal rs)
Dim rsTemp
Set rsTemp = CreateObject("ADODB.Recordset")
Set objFields = rsTemp.Fields
intFieldCount = objFields.Count - 1
For Idx = 0 To intFieldCount
rsTemp.Fields.Append objFields(Idx).Name, _
objFields(Idx).Type, _
objFields(Idx).DefinedSize
Next
Set CopyRecordsetStructure = rsTemp
End Function
The issue is i could not open the" rsTemp". It throws me error
The connection cannot be used to perform this operation. It is either closed or invalid in this context.
If I use some dummy query and connection it doesn't work.
Please help to copy the records from one recordset to another new record set.
Thanks in advance
Ganesh.
Not sure, but this looks wrong
Set objFields = rsTemp.Fields
Shouldn't it be
Set objFields = rs.Fields
With the comments and fixed in the above comments, the function should be updated Set objFields = rs.Fields to:
Usage:
Dim rsTemp
Set rsTemp = CopyRecordset(rsPadicon)
Update Code
Public Function CopyRecordset(rs)
Dim rsTemp, objFields, intFieldsCount, intPageSize
Set rsTemp = CopyRecordsetStructure(rs)
rsTemp.Open
Set objFields = rs.Fields
intFieldsCount = objFields.Count-1
response.write("<li> rs.RecordCount :" & rs.RecordCount & "</li>")
' response.write("<li> intFieldsCount :" & intFieldsCount & "</li>")
rs.MoveFirst
Do While Not rs.EOF
rsTemp.AddNew
Dim i
For i = 0 to intFieldsCount 'use i as a counter
' response.write("<li> Name :" & rs.Fields(i).Name & "</li>")
' response.write("<li> Value :" & rs.Fields(i).Value & "</li>")
if Not IsNull(rs.Fields(i).Value) then
rsTemp.Fields(i).Value = rs.Fields(i).Value
End if
Next
rsTemp.Update
rs.MoveNext
Loop
Set CopyRecordset = rsTemp
End Function
Public Function CopyRecordsetStructure(ByVal rs)
Dim rsTemp, objFields, intFieldCount, Idx
Set rsTemp = CreateObject("ADODB.Recordset")
Set objFields = rs.Fields
intFieldCount = objFields.Count - 1
For Idx = 0 To intFieldCount
rsTemp.Fields.Append objFields(Idx).Name, _
objFields(Idx).Type, _
objFields(Idx).DefinedSize
Next
Set CopyRecordsetStructure = rsTemp
End Function

putting values from database into a drop down list

my tool is in asp. i am using this code for a query in sql
dim req_id
req_id=Request.Form("Req_id")
if req_id<>"" then
Set conn=server.CreateObject("adodb.connection")
conn.Open session("Psrconnect")
Set rs=CreateObject("Adodb.Recordset")
rs.Open "select * from passwords where REQ_ID='"&req_id&"'", conn
i want to put the results of this query into a drop down list. how do i do it? any help is very much appreciated.
Slightly edited code from my working pages :
function HtmlFormOption( byval psReturnValue, byval psDisplayValue ,byval psCurrentDefault)
dim x
if IsNull(psCurrentDefault) then psCurrentDefault = ""
if IsNull(psReturnValue) then psReturnValue = ""
if lCase( cStr(psReturnValue) ) = lCase( cStr(psCurrentDefault)) then
x = "selected "
else
x = ""
end if
HtmlFormOption = "<option " & x & "value='" & psReturnValue & "'>" & psDisplayValue & "</option>"
end function
dim Result, sCode, sWaarde
Result = "<select name='NameCombobox' size='1'>" & vbCrlf
while not objRecLookup.Eof
sCode = objRecLookup.Fields(0) ' first field in result set
sWaarde = objRecLookup.Fields(1) ' second field in result set
if not IsNull(sCode) and not IsNull(sWaarde) then
Result = Result & HtmlFormOption( sCode, sWaarde , psCurrentDft )
end if
objRecLookup.MoveNext
wend
objRecLookup.Close
Result = Result & "</select>" & vbCrlf
And than Response.Write(Result)
Here's a simple solution:
<%
Dim objCommand, objRS
Set objCommand = Server.CreateObject("ADODB.Command")
with objCommand
.ActiveConnection = objConn
.CommandType = adCmdText
.CommandText = "SELECT * FROM PASSWORDS WHERE REQ_ID= '" & req_id & "'"
Set objRS = .Execute
end with
%><select name="selectbox"><%
While NOT objRS.EOF
%><option value="<%=objRS("COLUMN_NAME")%>"><%=objRS("COLUMN_NAME")%></option><%
objRS.MoveNext
Wend
%></select><%
objRS.Close
Set objRS = Nothing
Set objCommand = Nothing
%>

Resources