Ошибка ADODB.Parameters '800a0e7c' Объект параметров определен неправильно. Представлена ​​неверная или неполная информация

Я в первую очередь разработчик PHP, но у меня есть старый ASP, который один из наших предыдущих разработчиков сделал, который сломался, и я не могу понять, как это исправить. У нас есть программа, которая отправляет некоторые переменные на страницу прослушивателя, которая сравнивает эти данные с регистрационными кодами базы данных msSQL, а затем сообщает программе, действителен ли регистрационный код.

Я получаю следующую ошибку, где

.Parameters.Append .CreateParameter("@code", adVarChar, 1, 50, x)

это строка 134:

Ошибка ADODB.Parameters «800a0e7c»

Объект параметра определен неправильно. Была предоставлена ​​противоречивая или неполная информация.

/checkregistrationpro.asp, строка 134

Я уже указал любые именованные константы во включаемом файле, которые я не включил в код, так что это не имеет отношения к этому.

Моя строка подключения (я уже проверил правильность этих настроек):

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

Мой код:

...

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      
...

person nosajimiki    schedule 19.02.2016    source источник
comment
Вам нужно указать значение adVarChar, сейчас оно пусто и недействительно. Используйте документы: w3schools.com/asp/met_comm_createparameter.asp. adVarChar должно иметь значение 200. На самом деле у меня есть хорошая функция, которая делает это автоматически с помощью VarType, когда я получу резервную копию своей виртуальной машины и удалю исходный код, я опубликую ее для вас.   -  person Ryan Mann    schedule 20.02.2016
comment
Во-вторых, Параметры обеспечивают внутреннюю защиту от SQL-инъекций, вам не нужно делать это вручную. Если вы параметрируете весь свой запрос, вы можете забыть о SQL-инъекциях.   -  person Ryan Mann    schedule 20.02.2016
comment
Кроме того, если вы устанавливаете Visual Studio 2015, вы можете включить отладку на стороне сервера ASP в IIS на уровне компьютера (корневой узел IIS) и на уровне сайта. Затем установите удаленный отладчик Visual Studio на сервер IIS. Затем вы можете удаленно подключить визуальную студию к w3wp.exe, на котором работает сайт. Затем вы можете зайти на сайт и фактически выполнить код, и он установит точку останова на ошибке, затем вы можете использовать часы отладчика, чтобы увидеть значения и выяснить проблему.   -  person Ryan Mann    schedule 20.02.2016
comment
И, кроме того, если вы добавите ‹% Option Explicit %› в первую строку страницы, вызывающую ошибку, она включит строгую проверку переменных и выдаст ошибки, если переменные не определены, это точно скажет вам, если adVarChar не имеет значения в любом месте.   -  person Ryan Mann    schedule 20.02.2016
comment
comment
@Ryios Зачем это делать, если можно просто объявить библиотеку типов с помощью тега METADATA на странице или global.asa, и у вас есть доступ ко всем константам ADODB DLL, которые вы могли бы захотеть. Похоже, у вас есть функция, которая заново изобретает колесо. Я бы даже порекомендовал adovbs.asp, а это о чем-то говорит.   -  person user692942    schedule 20.02.2016
comment
Ах да, не подумал переместить константы в глобальную асу, так и сделаю. Хотя во многих случаях я видел, как люди используют adVarChar или adCmdText и т. д., и они нигде не определены. Это то, к чему я клонил. Что касается изобретения велосипеда, то на самом деле я создаю генератор POCO для классического asp, используя шаблоны Node и T4 в Visual Studio. Как PetaPoco, но для классического Asp.   -  person Ryan Mann    schedule 20.02.2016
comment
@Ryios Вау, серьезно? Это должно быть окончательным определением повторного изобретения колеса. Как ваш средний код ASP будет преобразован в POCO? Думаю, идея интересная, удачи.   -  person user692942    schedule 21.02.2016
comment
@Ryios Я не предлагал определять их в global.asa, хотя вы могли бы предложить IIS загружать их напрямую из библиотеки типов, чтобы вам не нужно было определять, а затем просто добавить директиву METADATA на страницу/global.asa .   -  person user692942    schedule 21.02.2016
comment
Ах, я не знал об объявлениях TypeLibrary. Меня недавно подтолкнули к классическому жереху и пришли из более новых пастбищ. У меня есть опыт работы с com-объектами, я даже написал некоторые из них, которые мы используем в классическом банкомате asp. Что касается poco, вы можете написать классы на VBScript, чтобы они были pocos, шаблон T4, над которым я работаю, просто напишет их для меня, поэтому вместо того, чтобы писать 300 строк asp для каждой таблицы как класса, я просто задайте имя таблицы в шаблоне T4, и он автоматически сгенерирует класс.   -  person Ryan Mann    schedule 21.02.2016
comment
@Ryios достаточно честно, хотя, конечно, было бы разумнее переключиться на что-то вроде .net, вместо того, чтобы тратить время на технологию, которая, честно говоря, мертва и похоронена?   -  person user692942    schedule 21.02.2016
comment
Если бы я мог, я на самом деле .net dev, mvc 5/6, nuget и т. Д. И т. Д. Этот проект, в котором я работаю, является последним классическим проектом компании. Решение сделать это было давно принято до того, как я слово ни в чем. И поскольку у нас есть множество других классических вещей asp в производстве, вещи, которые я делаю прямо сейчас, пригодятся для очистки плохого кода и упрощения переноса на .net или java spring.   -  person Ryan Mann    schedule 21.02.2016
comment
adVarChar уже определен. Что касается установки чего-либо на сервер IIS, я бы хотел, но у нас не так много ASP-сайтов, поэтому единственное место, где я должен их размещать, — это сервер общего хостинга с ограниченным доступом к таким вещам. @Ryios ‹% Option Explicit %› была отличной идеей. Это говорит мне, что соединение не определено. Я думаю, что мой недостаток опыта работы с ASP может быть здесь проблемой, но я думал, что set conn = Server.CreateObject(ADODB.Connection) определяет это. Я не очень хорошо разбираюсь в ASP, но есть ли проблемы с настройкой подключения?   -  person nosajimiki    schedule 22.02.2016
comment
PS: Эти проблемы начались с того, что наша хостинговая компания обновила свои серверы несколько месяцев назад, до этого годами они работали безупречно. Поэтому я подозреваю, что это скорее устаревший метод и/или проблема с настройками безопасности, чем что-то явно неправильное в коде. Я просто не знаю, что искать.   -  person nosajimiki    schedule 22.02.2016
comment
Можете ли вы рассказать мне что-нибудь о старом хостинге по сравнению с новым? Например. версия windows или текущая? Версия IIS против текущей? 32 бит против 64 бит и т.д.?   -  person Ryan Mann    schedule 23.02.2016
comment
@Ryios Я знаю, что старый сервер был IIS-7, а новый - IIS-8. Я не знаю версию Windows, но я предполагаю, что они обе 64-разрядные, основанные на версиях IIS. Он находится на общедоступном хостинге Plesk goDaddy на сервере Windows, поэтому было трудно исследовать проблему с ограниченным доступом к настройкам сервера и т. Д.   -  person nosajimiki    schedule 23.02.2016
comment
У вас может быть просто проблема, потому что пул приложений на старом сервере, вероятно, был установлен в классический режим, а пул приложений на новом сервере, возможно, в интегрированном режиме. Или, может быть, новый пул приложений работает в 64-битном режиме, а приложение использует DLL, которая имеет только 32-битную версию, поэтому для работы ему необходимо работать в 32-битном режиме. Также возможно, что ваш тег метаданных typelib в global.asa для ADO относится к ado DLL, которая не существует на новом сервере, что имеет больше смысла в контексте вашей ошибки.   -  person Ryan Mann    schedule 23.02.2016


Ответы (2)


Часто случается так, что у вас не определен adVarChar, поэтому метод CreateParameter() неправильно определен.

Это всего лишь пример одной из многих именованных констант, найденных в библиотеке ADODB. Беспорядочный подход к решению этой проблемы состоит в том, чтобы просто определить значение самостоятельно;

Const adVarChar = 200

Проблема с этим подходом заключается в том, что вам нужно определить все именованные константы, что может быть головной болью. Другой подход состоит в том, чтобы просто пропустить все именованные константы и просто использовать целочисленные значения, поэтому вызов будет таким:

.Parameters.Append .CreateParameter("@code", 200, 1, 50, x)

Однако это нелегко прочитать, хотя кажется, что вы уже делаете это со значением ParameterDirectionEnum 1, которое является именованной константой adParamInput в библиотеке ADODB. В любом случае, я бы не рекомендовал этот подход.

Несколько лучший подход — использовать директиву #include, чтобы она включала в вызывающую страницу все определения именованных констант, которые вам могут понадобиться, и так поступает большинство. Для этой цели Microsoft предоставляет предопределенный файл с IIS (или, возможно, с установкой библиотеки MDAC, я не уверен, что это пришло мне в голову), известный как adovbs.inc или adovbs.asp, включив этот файл на свою страницу. будет иметь доступ ко всем именованным определениям констант внутри.

Причина всего этого в том, что VBScript не поддерживает библиотеки типов, поэтому в сценарии Клиент вам остается только определить их самостоятельно или скопировать и вставить из файла adovbs.inc. Однако в сценарии Server у нас все еще есть мощь IIS, которая позволяет нам делать некоторые необычные вещи.

Было бы неплохо, если бы библиотеку типов можно было добавить один раз, и вам не нужно было бы об этом беспокоиться? Никаких надоедливых констант, которые нужно было бы определять? Посмотрим правде в глаза, они уже существуют в библиотеке типов, так почему мы не можем получить их оттуда? Оказывается, мы можем благодаря директиве METADATA.

Вот пример;

<!--
   METADATA    
   TYPE="TypeLib"    
   NAME="Microsoft ActiveX Data Objects 2.5 Library"    
   UUID="{00000205-0000-0010-8000-00AA006D2EA4}"    
   VERSION="2.5"
-->

Прелесть этого подхода в том, что вы можете использовать любую библиотеку типов (в идеале доступную для COM), и вы можете определить ее на одной странице или добавить в global.asa для определения во всем веб-приложении.

При таком подходе вы можете безопасно использовать такой код, как;

.Parameters.Append .CreateParameter("@code", adVarChar, adParamInput, 50, x)

Полезные ссылки

person user692942    schedule 21.02.2016
comment
У меня уже есть включенный файл конфигурации с adVarChar, определенным в нем точно так же, как этот, который был упущен при рассмотрении моего фрагмента кода. - person nosajimiki; 22.02.2016
comment
@nosajimiki Это хорошо, но опять же, этот ответ не только для тебя. - person user692942; 22.02.2016
comment
Это был отличный совет, не по теме OP, но тег MetaData удалил ПОЛНУЮ кучу неприятного кода объявления из приложения, в разработке которого я участвовал. Кроме того, параметризованные запросы работают в классическом asp, но вы не можете использовать имя. Классический asp поддерживает только ? подстановочный знак в запросах, который в основном собирает ваши параметры в том порядке, в котором они были добавлены к объекту команды. Таким образом, вы можете просто оставить имя (первый параметр) CreateParameter пустым. Если вы не знаете другой подстановочный знак, я не знаю. например где email = @email не работает, а где email = ? делает. - person Ryan Mann; 24.02.2016
comment
@Ryios Начиная с ADO 2.6 вы можете использовать свойство ADODB.Command NamedParameters, чтобы вы могли запрашивать параметры по имени. Однако не все провайдеры поддерживают его. - person user692942; 24.02.2016
comment
Ах, может быть, postgresql не поддерживает его и работает только с вопросительными знаками. - person Ryan Mann; 24.02.2016
comment
@Ryios Я не работал с PostgreSQL, поэтому не могу комментировать, но поддержка зависит от поставщика, единственное, что я могу предложить, это попробовать, но не забудьте сначала установить NamedParameters = True. - person user692942; 24.02.2016

В тех местах, где вы определяете adVarChar и другие магические числа ADO, полностью избавьтесь от них.

Вместо этого добавьте это в начало вашего файла global.asa (создайте его, если он не существует).

<!--METADATA TYPE="TypeLib" file="C:\Program Files (x86)\Common Files\System\ado\msado15.dll" -->

Это приведет к импорту библиотеки типов msado15, в которой уже определены все эти магические числа. Он автоматически подтянет все определения для вас. Это означает, что вам не придется определять adVarChar и т. д. самостоятельно, тег метаданных автоматически импортирует их для вас. Спасибо @Lankymart за это, поскольку его комментарий привел меня к открытию и выяснению этого, и это прекрасно работает.

Теперь создайте тестовую страницу ASP, которая пуста, и добавьте к ней тестовый код с опцией, явно включенной.

<%
    Option Explicit
    Response.Write "adVarChar: " & adVarChar
%>

Если вы получите сообщение об ошибке, что adVarChar не определен, значит, msado15.dll отсутствует на сервере. Таким образом, вам нужно будет связаться с godaddy и т. д., чтобы они сказали вам путь к любой версии MSADO, и изменить тег метаданных, чтобы он ссылался на правильную версию.

person Ryan Mann    schedule 23.02.2016
comment
Какая часть исправила? Добавление тега метаданных msado15.dll или обнаружение того, что на сервере нет ado15? Если это был тег метаданных, дайте ответ LankyMart, потому что я бы даже не знал, как это сделать, если бы он не упомянул об этом в своем комментарии. Узнал постфактум :) - person Ryan Mann; 24.02.2016
comment
Это была msado15.dll. И да, я согласен с тем, что Lankymart обнаружил проблему, но я считаю, что этот ответ намного понятнее для людей, которые еще мало знают об ASP; Итак, два больших пальца вверх вам обоим, ребята, за всю вашу помощь. Спасибо. - person nosajimiki; 25.02.2016