Главная SQL, Без рубрики, Новое Reporting Services, SQL, SQL 2008 R2, Конкурс
  • Интеграция сервера отчетов Reporting Services 2008 R2 в клиентское приложении Visual FoxPro 9.0

    08092517255439973_f0_0 Первоначально я решил интегрировать отчеты сервера отчетов Microsoft Reporting Services 2005 в свои клиентские приложения, написанные на Visual FoxPro 9.0. Когда эта задача была решена, подоспела версия сервера отчетов Reporting Services 2008. Пришлось переводить свое решение в эту новую редакцию сервера отчетов. Это потребовало некоторых усилий (небольших), т.к. реализация самого Web сервиса в версии Reporting Services 2008 существенно поменялась по сравнению с прошлой (2005) версией сервера отчетов. А вот переход от версии Reporting Services 2008 к версии Reporting Services 2008 R2 практически не потребовал никаких изменений. Да, в версии Reporting Services 2008 R2 появилась новая  конечная точка Web сервиса ReportService2010, но при этом конечная точка ReportService2005 также осталась. Поскольку для интеграции сервера отчетов в клиентское приложение Visual FoxPro 9.0 я использую именно конечную точку ReportService2005, то переход от версии Reporting Services 2008 к версии Reporting Services 2008 R2 не потребовал от меня никаких изменения в коде реализации интерфейсов IAuthenticationExtension и IAuthorizationExtension. В дальнейшем, в статье я буду для сокращения текста статьи упоминать версию Reporting Services 2008, но при этом надо понимать, что все это также будет работать и в версии  Reporting Services 2008 R2.

    Причины переноса отчетной системы приложения в отдельную отчетную подсистему

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

    • Включение отчетов в клиентское приложение существенно уменьшает гибкость системы при ее эксплуатации у клиента;
    • Выделение отчетной системы в отдельную подсистему дает возможность подразделению Help Desk заказчика в случае необходимости самим создавать требуемые отчеты без моего вмешательства. Это дает дополнительные конкурентные преимущества моей системе;
    • Microsoft Reporting Services 2008 R2 представляет из себя HTTP сервер, и службам Reporting Services больше не нужны службы IIS для доступа к ASP.NET, диспетчеру отчетов или конечной точке веб-службы сервера отчетов. В SQL Server 2008 службы Reporting Services выполняют следующие задачи:
      • Поддерживают размещение технологий ASP.NET и Microsoft .NET Framework, которые построены на основе среды SQL Server CLR.
      • Используют возможности компонента HTTP.SYS операционной системы.
      • Серверные приложения служб Reporting Services 2008 объединены в единую службу. В рамках единой службы запускаются следующие серверные приложения: веб-служба сервера отчетов (для интерактивной обработки отчетов), диспетчер отчетов (обслуживает запросы от клиентов) и обработчик планирования и доставки (фоновое приложение для обработки заданий по расписанию).



    Другими словами, для просмотра отчетов Reporting Services 2008 не нужно никакого иного клиентского приложения, кроме Internet Explorer.

    • Возможности среды разработки отчетов Microsoft Reporting Services 2008 R2 (SQL Server Business Intelligence Development Studio 2008, Report Builder 2.0 или Report Builder 3.0 ) существенно выше по функциональности, чем возможности построителя отчетов Microsoft Visual FoxPro 9.0. Отметим несколько основных преимуществ Reporting Services 2008 как среды разработки отчетной системы:
      • Большое число источников данных. Можно создавать отчеты, использующие реляционные и многомерные данные из SQL Server и служб Analysis Services. Можно также с помощью поставщиков данных .NET Framework обрабатывать данные из баз данных Oracle и других производителей. Поддерживаются также поставщики данных ODBC и OLE DB. Чтобы получить данные из любого источника XML-данных, можно воспользоваться модулем обработки XML-данных.
      • Табличное, матричное, графическое и произвольное представление макетов отчетов. Особо отмечу матричное представление данных (кол-во и строк и колонок данных может меняться). Аналога этой области данных в Visual FoxPro 9.0 просто нет. Также интересны области данных сервера ответов «Датчик» и «Табликс»;
      • Можно добавить к отчету интерактивные возможности, предоставив ссылки на связанные отчеты и отчеты, содержащие подробные данные. К отчету также можно добавить сценарии на языке Microsoft Visual Basic Script.NET;
      • Можно добавить параметры для уточнения запроса или фильтрации данных. Динамическим параметрам числовые значения присваиваются во время выполнения в соответствии с пользовательским выбором;
      • Различные форматы вывода отчета. Доступны следующие форматы: HTML, MHTML, PDF, XML, CSV, TIFF, Excel и Word;
      • Можно внедрить пользовательские элементы управления и элементы отчетов, созданные самостоятельно или приобретенные у сторонних поставщиков. Для пользовательского элемента управления необходим модуль обработки пользовательских отчетов;
      • Чтобы облегчить перемещение внутри большого отчета, можно добавлять закладки и схемы документов;
      • Статистическая обработка и анализ данных могут выполняться с помощью элементов управления и выражений. Статистические (агрегатные) функции позволяют выполнить суммирование, найти среднее, минимальное или максимальное значения, подсчитать количество элементов, вычислить промежуточные итоги;
      • Можно внедрить в отчет рисунки и другие ресурсы, содержащие внешние данные;
      • Отчет может содержать ссылки на другие отчеты с передачей им параметров, что позволяет использовать один отчет многократно. Такие отчеты можно пометить как “невидимые” для вызова их ТОЛЬКО из “главного” отчета, но не из списка отчетов. Ах, как жаль что ничего подобного нет в отчетах Visual FoxPro 9.0!
      • Подписки для доставки по электронной почте или доставки в общую папку Windows. Применяются для автоматической доставки отчетов с помощью стандартной подписки и для задания пользовательских настроек представления отчета. В подписке указывается предпочтительный для пользователя формат доставляемого отчета, например формат Microsoft Excel или Word. Готовый для просмотра отчет доставляется в ящик электронной почты. Можно задать параметры доставки, определяющие форму доставки отчета: в виде ссылки или вложения. Готовый для просмотра отчет может быть доставлен в общую папку. Также можно выбрать способ сохранения отчета в папке: добавление или перезапись;
      • Автоматизированное распространение отчетов с помощью управляемых данными подписок, формирующее список получателей и команды доставки во время выполнения из внешнего источника данных. Для настройки отчета для большого числа пользователей используйте сведения о запросе и сопоставлении столбцов. Т.е. вы создаете таблицу и в ней добавляете по одной строке для каждого подписчика. В этой строке присутствует информация об адресе и о способе доставки отчета, параметрах выполнения отчета (если они есть) и пр. Саму таблицу вы можете легко заполнять из своего клиентского приложения Visual FoxPro 9.0;
      • Доступ по URL-адресу. Можно получать доступ к элементам сервера отчетов с помощью параметризованных строк URL-адреса. Пространство имен сервера отчетов может быть использовано для доступа к отчетам и элементам, хранящимся на сервере отчетов. Именно этот способ я использую для обращения к отчетам Reporting Services 2008 из своего клиентского приложения, написанного на Visual FoxPro 9.0;
      • Чтобы направить отчеты в общие папки, внутреннее хранилище архивов или во внутренние приложения, можно создать пользовательские модули доставки. Можно расширить обработку данных, запрашивая и преобразовывая данные из новых типов источников данных. Можно создать пользовательские модули подготовки отчетов для поддержки представления отчета в формате приложения или в
        веб-ориентированном формате, которые не поддерживаются базовой версией продукта. Также можно создать или встроить модуль безопасности, обеспечивающий проверку подлинности, отличную от Windows. Далее я подробно покажу, как заменить стандартный способ проверки подлинности, основанную на Windows, на свой собственный, основанный на проверки пользователей из моей базы данных;
    • Увеличение скорости работы при большой нагрузке на реляционную базу данных за счет использование механизма кэширования. Кэширование отчетов в собственной базе данных Reporting Services 2008 позволяет ему повторно использовать уже считанные ранее из реляционной базы данные. Есть возможность управлять временем сохранения в кэше считанных данных;
    • Просмотр “исторических” данных. Т.е. тех данных, которых уже нет в реляционной базе данных, но были в ней на момент генерации отчета. Это обеспечивается хранением данных отчетов Reporting Services в своей базе данных. Очень полезная функция!

    Структура использования отчетов Reporting Services 2008 в клиентском приложении Visual FoxPro 9.0

    Для организации программного доступа к отчетам Microsoft Reporting Services 2008 существует несколько технологий:

    • API Simple Object Access Protocol (SOAP);
    • Управляющий элемент ReportViewer;
    • URL Access.

    SOAP

    Веб-служба сервера отчетов использует протокол SOAP по протоколу HTTP и выступает в роли интерфейса связи между клиентскими программами и сервером отчетов. Веб-служба предоставляет две конечные точки — одну для выполнения отчетов и другую для управления отчетами. Веб-служба состоит из методов и набора объектов сложного типа, которые можно использовать для доступа ко всем функциональным возможностям служб Reporting Services 2008. Для вызова службы следует создать ссылку на язык описания веб-служб (WSDL) служб Reporting Services.

    Для успешного вызова веб-службы следует знать метод доступа к данной службе, поддерживаемые ей операции, параметры, ожидаемые этой службой, а также возвращаемые ей данные. Язык WSDL предоставляет эти данные в XML-документе, который может быть считан или обработан компьютером.

    Веб-служба сервера отчетов доступна в двух различных конечных точках. У каждой конечной точки существует разное имя WSDL-файла. Конечная точка ReportService2005 содержит методы управления объектами на сервере отчетов. Доступ к WSDL файлу данной конечной точки осуществляется посредством ReportService2005.asmx?wsdl.

    • Конечная точка ReportExecution2005 позволяет разработчикам программным образом обрабатывать и подготавливать к просмотру отчеты на сервере отчетов. Доступ к WSDL файлу данной конечной точки осуществляется посредством ReportExecution2005.asmx?wsdl
    • В Reporting Services 2008 R2 добавилась новая конечная точка ReportService2010, которая объединяет функции конечных точек ReportExecution2005 и ReportExecution2006. Эта конечная точка также включает новые возможности, появившиеся в SQL Server 2008 R2, такие как общие наборы данных и обновление кэша.

    WSDL-файл может быть использован средствами разработки, поддерживающими SOAP и веб-службы, например пакетом Microsoft .NET Framework SDK.

    В следующем примере показывается формат URL-адреса управляющего WSDL-файла служб Reporting Services:

    http://server/reportserver/ReportService2005.asmx?wsdl

    Дополнительные сведения о формате WSDL см. в спецификации языка WSDL консорциума World Wide Web (W3C) по адресу http://www.w3.org/TR/wsdl.

    Для разработки приложений с помощью веб-службы сервера отчетов Reporting Services 2008 необходимо:

    • обозреватель Microsoft Internet Explorer 5.5 или более поздней версии, установленный на компьютере, который соединен с Интернетом и имеет доступ к серверу отчетов;
    • Microsoft среда Visual Studio или пакет SDK для Microsoft .NET Framework, установленные на компьютере, если необходимо разрабатывать и развертывать приложения служб Reporting Services с помощью Microsoft .NET Framework;
    • полное представление о функциях и возможностях служб Microsoft SQL Server Reporting Services 2008;
    • уверенное владение протоколом SOAP и службами XML Web Services;
    • опыт разработки на языке, совместимом с платформой .NET Framework, например Microsoft Visual C# или Microsoft Visual Basic, если планируется использовать .NET Framework в качестве платформы разработки

    Как видно из этого списка, среда разработки клиентского приложения Visual FoxPro 9.0 не удовлетворяет этим требованиям. Так, что SOAP, как технология доступа к отчетом Reporting Services 2008 нам, увы, не подходит.

    Управляющий элемент ReportViewer

    Если вы пишите клиентскую программу в среде .NET Framework, то в Visual Studio  вам доступен управляющий элемент ReportViewer. Достаточно разместить на своей форме этот элемент и настроить его соответствующим образом для работы с вашим Reporting Services 2008. Данный управляющий элемент есть и для Windiows Forms и для Web Forms. Выглядит эта красота в режиме редактирования формы следующим образом:


    Но это не ActiveX, а control для .NET Framework приложения. При разработке клиентского приложения на Visual FoxPro он, увы, он не годится.

    URL Access

    В своих клиентских приложениях на Visual FoxPro 9.0 для доступа к отчетам Reporting Services 2008 я использую технологию, основанную на передаче параметров Web сервису Reporting Services в строке URL. Подробнее о параметрах, которые вы можете передать через URL, можно почитать в MSDN. В этом случае, я, на форме Visual FoxPro размещаю ActiveX элемент Web Browser и вызываю его метод Navigate с передачей ему в качестве параметра URL требуемого отчета с необходимыми параметрами. Выглядит эта технология в работе следующим образом:


    Теперь разберемся с аутентификацией и авторизацией пользователей в Reporting Services.

    Аутентификация пользователя в Microsoft Reporting Services 2008

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

    1.       Уникальный регистрационный номер пользователя (Логин);

    2.       Пароль пользователя.

    Логин, обычно, хранится и передается в открытом виде, а пароль в шифрованном. Microsoft Reporting Services 2008 для аутентификации использует базу данных операционной системы (локального компьютера или домена), т.е. он использует Windows authentication. При интеграции отчетов Reporting Services 2008 в клиентское приложение Visual FoxPro 9.0, этот способ аутентификации показался мне не очень удобным по следующим причинам:

    • Пользователь должен вводить разные логины и пароли при старте моего приложения и при выполнении отчетов;
    • Права на выполнения отчетов Reporting Services придется “раздавать” на уровне Windows пользователей, а не на уровне пользователей моего приложения.

    Что делать?
    К счастью, разработчики Microsoft Reporting Services 2008 предусмотрели расширение функциональности своего продукта в том числе и в плане безопасности. Это расширение реализуется с помощью аутентификацией, основанной на Forms authentication технологии ASP.NET. Эта функциональность реализована во всех версиях Reporting Services 2008, кроме Express и Express with Tools.

    Выглядит эта технология следующим образом:


    Для реализации такого способа аутентификации мне пришлось написать свой модуль Security Extension (он выделен желтым цветом на рисунке) для Reporting Services 2008 и подключить его соответствующим образом (об этом будет рассказано далее). Модуль должен реализовывать интерфейс IAuthenticationExtension через перегрузку нескольких методов. Подробно об этом вы можете почитать в MSDN. Свой Security Extension я написал на C#. При его разработке я внимательно изучил два примера:

    1.       MSDN Microsoft Security Extension Sample

    2.       Harden MS Reporting Services Using Custom Extensions

    Учтите, что в первом примере в разделе “To debug the Forms Authentication sample code” есть ошибка в описании процесса отладки. Правильную процедуру отладки кода сборки я опишу в разделе, посвященному процессу инсталляции моего примера.

    Авторизация пользователя в Microsoft Reporting Services 2008

    Авторизация (authorization) контролирует права на использования объектов Reporting Services 2008 пользователем, уже прошедшего в нем аутентификацию.

    В Reporting Services 2008 есть возможность также расширить и эту функциональность с помощью Authorization Extension.
    Выглядит это следующим образом:


    Желтым цветом на рисунке показан модуль, который должен быть написан разработчиком для внедрения своей модели авторизации. Он должен реализовывать интерфейс IAuthorizationExtension с перегрузкой методов CheckAccess, GetUserInfo и др. Свой модуль расширения я написан на C#. Подробнее о своих модулях расширения я расскажу далее.

    В результате, работа с Report Services выглядит следующим образом:


    Желтым цветом на рисунке выделен модуль расширения, написанный мною на C# и подключенный к Reporting Services 2008, путем изменения его XML-файлов конфигурации. Для аутентификации пользователей, модуль обращается к таблице Users моей базы данных через представление dbo.VUsers  и хранимую процедуру dbo.Admin_TestPassword (на рисунке – Custom security authority). При внедрении данного метода интеграции отчетов Reporting Services 2008 в свое клиентское приложение Visual FoxPro 9.0, вы можете легко поменять данный метод аутентификации на свой собственный метод.

    Теперь что касается клиентского приложения на Visual FoxPro 9.0.
    Собственно говоря, все это расширение Reporting Services 2008 и было задумано для того, чтобы пользователь моего приложения, введя один раз пароль и логин при входе в него, далее пользовался разрешенными ему отчетами, не выходя из приложения Visual FoxPro 9.0 и не запуская явно Internet Explorer.
    При интеграции отчетов Reporting Services 2008 в мое клиентское приложение, написанное на Visual FoxPro 9.0 было учтено следующее:

    • Из моего приложения, написанного на Visual FoxPro 9.0, пользователи могут только просматривать отчеты Reporting Services 2008. Разработка отчетов и их развертывание на сервере отчетов выполняется штатными средствами самого Reporting Services 2008: SQL Server Business Intelligence Development Studio 2008, Report Builder 3.0, Report Manager (через Internet Explorer);
    • Права на использования отчетами Reporting Services 2008 определяются не его средствами администрирования, а через редактирование таблицы dbo.Reports_Permissions в моей базе данных SQL Server. Таблица заполняется через специальную форму клиентского приложения и связывает пользователей моей системы и отчеты Reporting Services 2008 по их ItemID, что и определяет права пользователей на просмотр выбранного отчета;
    • Модуль расширения авторизации для Reporting Services 2008 написан мною таким образом, что предоставляются ВСЕ права в Reporting Services 2008 администраторам моей системы (права Content Manager) и виртуальному администратору Reporting Services 2008, имя и пароль которого описаны в секции <Authentication> файла конфигурации RSReportServer.config. Там же определена строка подключения к моей базе данных для доступа к двум объектам:
      • Представление dbo.VUsers – список всех пользователей моей системы;
      • Хранимая процедура dbo.Admin_TestPassword – возвращает строку из dbo.VUsers, если пользователь опознан, или User_ID = 0 – если пользователь не опознан.
    • В данном тестовом примере параметры данного виртуального администратора Reporting Services 2008 следующие:
      • Логин – ReportAdmin;
      • Пароль – Pa$$w0rd.
    • При доступе к отчетам Reporting Services 2008 из клиентского приложения  Visual FoxPro 9.0, я использую механизм олицетворения (impersonation). Это означает, что подключение к Reporting Services 2008 осуществляется не от имени пользователя, который запустил клиентское приложение Visual FoxPro 9.0 и вошел в мою систему, а от имени пользователя, имеющего права просматривать любые отчеты – от имени, упомянутого выше, вирутального адимнистратора. В этом случае все права на просмотр отчетов определяются не на уровне методанных Reporting Services 2008 и с помощью Диспетчера Отчетов (Report Manager), а на уровне моего приложения. Главная проблема, которую мне пришлось решить при внедрении этой технологии, связана с передачей Логина и Пароля пользователя в Reporting Services 2008, использую URL выбранного отчета. Об этом будет подробно рассказано далее.
    • Если такой механизм доступа к отчетам вас не устраивает, то можно передавать в модуль аутентификации пользователя Reporting Services 2008 логин и пароль пользователя, который вошел в систему. В программный код сборки на C# никаких изменений вам вносить не потребуется, но в этом случае вам придеться давать этому пользователю права на просмотр (Browse)  на требуемые отчеты также и через Диспетчера Отчетов  (Report Manager).

    Структура интеграции отчетов Microsoft Reporting Services 2008 в клиентское приложениt Visual FoxPro 9.0

    Взаимодействие всех компонентов расширения Reporting Services 2008 и клиентского приложения Visual FoxPro показано на следующем рисунке:


    После внедрения данной системы аутентификации и авторизации, любой администратор моей системы имеет все права в Reporting Services 2008. Требуемые права на выбранный отчет, папку, источник данных и другие объекты Reporting Services 2008, можно назначить ТОЛЬКО пользователям моей системы (а не Windows).

    Реализация интерфейса IAuthenticationExtension (методы GetUserInfo, LogonUser, IsValidPrincipalName и SetConfiguration)

    Для реализации интерфейса IAuthenticationExtension необходимо переписать несколько методов класса AuthenticationExtension.

    AuthenticationExtension.SetConfiguration:

    public void SetConfiguration(String configuration)

    {

    // Ищем в файле configuration элемент ADMIN_CONFIG

    // и из его дочерних элементов извлекаем элементы:

    // CONNECTION_STRING

    // ADMIN_USER_NAME

    // ADMIN_USER_PASSWORD

    XmlDocument doc = new XmlDocument();

    doc.LoadXml(configuration);

    if (doc.DocumentElement.Name == ADMIN_CONFIG)

    {

    foreach (XmlNode child in doc.DocumentElement.ChildNodes)

    {

    switch (child.Name)

    {

    case SQL_CONNECTION_STRING: m_connectionstring = child.InnerText; break;

    case ADMIN_USER_NAME: m_adminUserName = child.InnerText; break;

    case ADMIN_USER_PASSWORD: m_adminPassword = child.InnerText; break;

    default: throw new Exception(“Не распознанный элемент: ” + child.Name.Trim() +

    ” в файле конфигурации: ” + configuration.Trim());

    }

    }

    }

    else

    throw new Exception(“В файле конфигурации: ” + configuration.Trim() +

    ” нет элемента: AdminConfiguration”);

    }

    Метод вызывается при инициализации сервиса и принимает в качестве параметра имя секции конфигурации конфигурационного файла Reporting Services 2008 RSReportServer.config (элемент <Authentication>). Я использую данную секцию для хранения следующих элементов:

    • Строка подключения к моей базе данных;
    • Имя виртуального пользователя – главного администратора Reporting Services 2008 – по умолчанию это ReportAdmin;
    • Пароль виртуального пользователя – главного администратора Reporting Services – по умолчани он равен Pa$$w0rd.

    Последние два параметра определяют виртуального пользователя – администратора Reporting Services 2008. При входе в Reporting Services 2008 данным пользователем можно администрировать сервер, даже если нет ни одного администратора в моей базе данных. Если моя система построена таким образом, что в ней всегда есть хотя бы один администратор, то данного пользователя можно и не использовать.

    AuthenticationExtension.LogonUser:

    public bool LogonUser(string userName, string password, string EncryptMode)

    {

    bool UserIsAuthentication = false;

    l_AdminKIS = false;

    if (EncryptMode == “Encrypt”)

    {

    // Пароль зашифрован, расшифруем его

    string passwordDecrypt = AuthenticationUtilities.Decrypt(password, m_connectionstring);

    if ((userName == m_adminUserName) && (passwordDecrypt == m_adminPassword))

    {

    l_AdminKIS = true;

    UserIsAuthentication = true;

    }

    else

    {

    UserIsAuthentication = AuthenticationUtilities.VerifyPassword(userName, password, m_connectionstring, true);

    }

    }

    else

    {

    // Проверяем, не админ ли!

    if ((userName == m_adminUserName) && (password == m_adminPassword))

    {

    l_AdminKIS = true;

    UserIsAuthentication = true;

    }

    else

    {

    UserIsAuthentication = AuthenticationUtilities.VerifyPassword(userName, password, m_connectionstring, false);

    }

    }

    if (UserIsAuthentication == true && l_AdminKIS != true)

    {

    // Если пользователь опознан и он не администратор сервера отчетов,

    // то надо проверить, а не админ ли он КИС

    l_AdminKIS = AuthenticationUtilities.IsKISAdmin(userName, m_connectionstring);

    }

    return UserIsAuthentication;

    }

    Метод вызывается при аутентификации пользователя. Он принимает три параметра: логин и пароль пользователя (userName и password), а также режим шифрования пароля (EncryptMode). Первые два параметра идентифицируют пользователя, а третий показывает, зашифрован ли пароль. Дело в том, что если данный метод вызывается из форм аутентификации (Logon.aspx или UILogon.aspx), то пароль не зашифрован и его расшифровка не требуется (EncryptMode <> “Encrypt”). Но данный метод, как будет показано далее, может вызываться также из формы Logon.aspx при обнаружении в параметрах логина и пароля, переданного через URL отчета. В этом случае я передаю пароль в URL в шифрованном виде, который необходимо будет расшифровать при его проверке. Для расшифровке пароля используется метод AuthenticationUtilities.Decrypt(). В данном примере метод содержит только код перевода из Hex – формата в символьный и не содержит никакого  кода расшифровки пароля. Это означает, что в ознакомительном примере я НЕ использую шифрование пароля. В реальной системе, конечно, шифрование необходимо, т.к. пароль передается в URL и может быть перехвачен злоумышленником. Альтернативным методом защиты может служить включение протокола SSL между клиентом и Web-сервером. Данный метод защиты очень надежный, но его реализация выходит за пределы данной статьи.  При передаче пароля через URL я на всякий случай кодирую пароль в Hex формат, т.е. передаю каждый символ пароля в виде двух символов (от 0 до 9 и буквы A, B, C, D, E и F). Это не шифрование пароля, а просто страховка от того, что среди символов пароля может встретиться символ, который нельзя передать через URL. Кодировка пароля  в Hex формат на клиенте производиться с помощью следующего кода Visual FoxPro 9.0:

    m.lcOutHex = STRCONV(m.lcInStr,15)

    Проверка пароля происходит в методе AuthenticationUtilities.VerifyPassword().

    AuthenticationUtilities.VerifyPassword:

    // Проверка пользователя и пароля

    // Для этого используется хранимая процедура сервера – Admin_TestPassword

    internal static bool VerifyPassword(string suppliedUserName, string suppliedPassword, string connectionString, bool PasswordIsEncrypt)

    {

    bool passwordMatch = false;

    SqlDataReader reader;

    SqlConnection conn = new SqlConnection(connectionString);

    // Читаем имя сервера и его дату, время

    SqlCommand cmd = new SqlCommand(“Admin_TestPassword”, conn);

    cmd.CommandType = CommandType.Text;

    try

    {

    conn.Open();

    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Add(“@USERLOGIN”, SqlDbType.VarChar, 40);

    cmd.Parameters[“@USERLOGIN”].Value = suppliedUserName.Trim();

    cmd.Parameters.Add(“@PASSWORD”, SqlDbType.VarChar, 16);

    cmd.Parameters[“@PASSWORD”].Value = suppliedPassword.Trim();

    reader = cmd.ExecuteReader();

    reader.Read();

    int User_ID = (int)reader[“User_ID”];

    if (User_ID > 0)

    {

    passwordMatch = true;

    }

    }

    catch (Exception ex)

    {

    throw new Exception(string.Format(CultureInfo.InvariantCulture,

    CustomSecurity.VerifyUserException + ex.Message));

    }

    finally

    {

    conn.Close();

    }

    return passwordMatch;

    }

    Проверка пользователя моей системы происходит в хранимой процедуре dbo.Admin_TestPassword. Для этого в нее передается логин пользователя и его пароль.

    Внимание! Пароль не шифруется!

    Такой способ аутентификации пользователя выбран только для примера. В вашем приложение вы можете поменять данный метод на свой собственный. Достаточно поменять код метода AuthenticationUtilities.VerifyPassword().

    Для проверки пользователя вызывается метод AuthenticationUtilities.IsValidPrincipalName() с передачей ему логина проверяемого пользователя и строку подключения.

    AuthenticationUtilities.IsValidPrincipalName:

    internal static bool IsValidPrincipalName(string suppliedUserName, string connectionString)

    {

    bool isValid = false;

    if (suppliedUserName.Trim() == String.Empty)

    return false;

    SqlConnection conn = new SqlConnection(connectionString);

    SqlCommand cmd = new SqlCommand(“SELECT * FROM dbo.VUsers WHERE Login = @Login_Name”, conn);

    cmd.CommandType = CommandType.Text;

    SqlParameter sqlParam = cmd.Parameters.Add(“@Login_Name”, SqlDbType.Char, 8);

    sqlParam.Value = suppliedUserName;

    try

    {

    conn.Open();

    SqlDataReader reader = cmd.ExecuteReader();

    if (reader.HasRows)

    {

    isValid = true;

    }

    }

    catch (Exception ex)

    {

    throw new Exception(“Ошибка идентификации пользователя: ” + suppliedUserName.Trim() + ex.Message);

    }

    finally

    {

    conn.Close();

    }

    return isValid;

    }

    Метод осуществляет поиск в представлении dbo.VUsers логина suppliedUserName. Если логин найден (объект reader содержит запись), то метод возвращает тrue. Иначе, метод возвращает false. Для соединения с сервером метод использует переданную строку подключения (connectionString).

    AuthenticationExtension.GetUserInfo:

    public void GetUserInfo(out IIdentity userIdentity, out IntPtr userId)

    {

    // Если текущий пользователь не null, то устанавливаем

    // userIdentity в текущего пользователя

    if (HttpContext.Current != null

    && HttpContext.Current.User != null)

    {

    userIdentity = HttpContext.Current.User.Identity;

    }

    else

    userIdentity = null;

    // initialize a pointer to the current user id to zero

    userId = IntPtr.Zero;

    }

    Метод вызывается сервером отчетов каждый раз, когда необходимо аутентифицировать пользователя. Если пользователь уже прошел аутентификацию, то именно он и возвращается. Иначе, возвращается пустой пользователь, что заставит Reporting Service провести повторную аутентификацию пользователя.

    Все методы интерфейса IAuthenticationExtension реализованы в классе AuthenticationExtension. Необходимая для работы данного класса дополнительная функциональность реализована в виде статических методов класса AuthenticationUtilities.

    Реализация интерфейса IAuthorizationExtension (методы CheckAccess, CreateSecurityDescriptor, GetPermissions и SetConfiguration)

    Интерфейс IAuthorizationExtension реализован с помощью класса Authorization. Рассмотрим некоторые методы этого класса.

    Authorization.CheckOperations:

    private bool CheckOperations(string principalName, AceCollection acl, object requiredOperation)

    {

    if (principalName.Trim() == String.Empty)

    return false;

    // Сначала надо определить параметры отчета

    // Если это администратор Reporting Server, то права не проверяются. Они даны и так

    if (0 == String.Compare(principalName, m_adminUserName, true, CultureInfo.CurrentCulture))

    return true;

    // Если это админ КИС ВиртуалСофт, то его права тоже не проверяем.

    // Если он прошел аутентификацию (т.е. смог подключиться к системе),

    // то он должнен обладать и всеми правами админа Report Server

    if (AuthenticationExtension.AdminKIS == true)

    return true;

    // Иначе, проверяем права в методе IsUserAuthorized

    if (IsUserAuthorized(principalName, acl, requiredOperation))

    {

    return true;

    }

    return false;

    }

    Метод используется для проверки возможности пользователем principalName выполнения операции requiredOperation. Сначала я проверяю, что пользователь является виртуальным пользователем – администратором Report Services (0 == String.Compare(principalName, m_adminUserName, true, CultureInfo.CurrentCulture)). Если это так, то метод возвращает true без проверки его прав с помощью метода IsUserAuthorized. Затем я проверяю роль пользователя в моей базе данных. Для этого используется свойства AdminKIS класса AuthenticationExtension. Это свойство устанавливатся в методе AuthenticationExtension.LogonUser() и будет равно true, если пользователь является администратором моей системы. В этом случае в методе CheckOperations() я также не проверяю права пользователя на требуемые операции, а из метода просто возвращаю значение true.

    Разработка клиентского приложения Visual FoxPro для просмотра отчетов Reporting Services 2008

    Сформулируем требования к функциональным возможностям клиентской части приложения Visual FoxPro для работы с отчетами Reporting Services 2008:

    • Просмотр отчетов из формы Visual FoxPro;
    • Управление правами на просмотр отчетов для выбранного пользователя (только для администратора моей системы);
    • Просмотр истории выполнения отчетов на сервере отчетов.

    Reporting Services 2008 поддерживает несколько форматов вывода отчета. Наиболее универсальным является формат HTML. В этом случае для  отображения выбранного отчета можно использовать Web обозреватель. В качестве Web обозревателя я использую ActiveX компонент Web-Browser, а точнее, класс _webbrowser4, построенный на его основе и размещенный в библиотеке _webview.vcx. Класс является копией класса Web Browser Control, взятого из Componet Gallery, входящего в поставку Visual FoxPro 9.0. и позволяющего использовать Microsoft Internet Explorer Browser для просмотра HTML страниц. Дополнительная функциональность, которая добавлена в _webbrowser4, в основном касается расширения управлением навигации по страницам и ведение истории выбранных URL.

    Вся функциональность, обеспечивающая работу моего клиентского приложения Visual FoxPro реализована в виде нескольких классов, размещенных в библиотеке reportservice.vcx


    Центром работы с отчетами Reporting Services 2008 является класс ViewReportService_Main. В дизайнере он выглядит следующим образом:


    Рассмотрим наиболее важные методы данного класса.

    Init:

    LPARAMETERS m.lnIDObject, m.lnNumber, m.lnBar, m.lcNameMenu, m.lnDK_ID, m.lnStr_ID

    *– Читаем параметр – URL Report Server

    WITH THIS

    .cmdSetPermissions.Visible = (oApp.User_Role = ‘A’)

    .cmdViewLog.Visible = (oApp.User_Role = ‘A’)

    .ReportServerDB = ‘ReportServer’

    IF EMPTY(.ReportServer)

    .ReportServer = ALLTRIM(oApp.SQL_FullName)

    ENDIF

    *– Если параметра нет, то имя Report Server устанавливаем по имени SQL Server

    IF EMPTY(.ReportServerURLAccess)

    .ReportServerURLAccess = ‘http://’ +.ReportServer + ‘/reportserver’

    ENDIF

    IF VARTYPE(m.lnNumber) == “N” AND m.lnNumber > 0

    .Caption = .Caption + ;

    ” Окно # ” + ALLTRIM(STR(m.lnNumber))

    .Name = ALLTRIM(.Name) + ALLTRIM(STR(m.lnNumber))

    ENDIF

    .IDObject = m.lnIDObject

    DODEFAULT(m.lnBar, m.lcNameMenu)

    *– Читаем список отчетов

    IF !.GetListReports()

    .Destroy()

    RETURN .F.

    ENDIF

    ENDWITH

    В этом методе я сначала определяю необходимые параматеры сервера отчетов и запоминаю их в свойствах класса:

    • ReportServerDB – имя базы данных сервера отчетов;
    • ReportServer – имя сервера Reporting Services. Если свойство не установлено, то оно установливается равным имени компьютера, где находится серер базы данных;
    • ReportServerURLAcces – URL к Web-сервису сервера отчетов;

    Эти свойства можно передавать в класс как параметры, можно загружать с сервера из конфигурационной таблицы моей базы данных (в своих приложениях я так и делаю) или читать из конфигурационного файла (INI-файла, XML и т.п.). Если URL сервера отчетов не задано, то я считаю, что Reporting Services 2008 находится на компьютере, где находится и моя база данных. Затем я читаю с сервера в локальный курсор SReports список отчетов Reporting Services 2008, путем вызова метода класса GetListReports() и копирую этот список в локальный курсор ListReport, который и предъявляю пользователю посредством объекта cboListReports класса ComboBox.

    GetListReports:

    *– Чтение списка отчетов

    LOCAL m.lcDSNLess, m.lnConnect, loCAD AS CursorAdapter

    WITH THIS

    .cboListReports.RowSource = “”

    ZAP IN ListReport

    *– Создаем новое соединение под логином админа и читаем список пользователей

    TEXT TO lcDSNLess TEXTMERGE NOSHOW PRETEXT 15

    Driver={<<ALLTRIM(oApp.Driver)>>};Server=<<ALLTRIM(oApp.SQLServer)>>;

    Database=<<ALLTRIM(oApp.SQLDatabase)>>;

    Uid=AppAdmin;Pwd=Pa$$w0rd;

    APP=Интерграция RS 2008 и Visual FoxPro, Чтение списка отчетов

    ENDTEXT

    m.lnConnect = SQLSTRINGCONNECT(m.lcDSNLess)

    IF m.lnConnect <= 0

    RETURN .F.

    ENDIF

    loCAD = CREATEOBJECT(“sql.sqlca”)

    WITH m.loCAD

    .DataSource = m.lnConnect

    .Alias = “SReports”

    .CursorSchema = ‘PolicyRoot I, Type I, CreationDate T, ModifiedDate T, ItemID C(36), ParentID C(36), Path M, Name M’

    ENDWITH

    TEXT TO m.loCAD.SelectCmd TEXTMERGE NOSHOW PRETEXT 15

    EXEC EXEC dbo.RS_GetListReports @DBReportServer='<<.ReportServerDB>>’,@USER_ID=<<oApp.User_ID>>,

    @ReportServer='<<.ReportServer>>’

    ENDTEXT

    IF m.loCAD.CursorFill(.T., .F.)

    INSERT INTO ListReport (ItemID, Path, Name) ;

    SELECT ItemID, Path, LEFT(Name, 120) ;

    FROM SReports WHERE Type = 2

    ENDIF

    m.loCAD.CursorDetach()

    SELECT ListReport

    GOTO TOP

    WITH .cboListReports

    .RowSourceType = 2

    .RowSource = ‘ListReport.Name’

    .Value = ListReport.Name

    ENDWITH

    ENDWITH

    Для формирования строки подключения к моему SQL Server, используются следующие свойства PUBLIC класса oApp:

    • Driver – имя драйвера для подключения к SQL серверу. Для версии сервера SQL 2008 драйвер называется – SQL Server Native Client 10.0;
    • SQLServer – имя SQL сервера с которым работает приложение;
    • SQLDatabase – имя моей базы данных на SQL сервере.

    Для чтения списка отчетов служит хранимая процедуры dbo.RS_GetListReports. Она использует функцию OPENROWSET для чтения таблиц dbo.Catalog и dbo.ExecutionLog базы данных Reporting Services 2008. Для доступа к этим таблицам у пользователя, который используется  в строке подключения функции OPENROWSET, должны быть необходимые права на чтения из этих таблиц. Для разрешения использования функции OPENROWSET необходимо открыть Faset сервера Surface Area Сonfiguration и установить его параметр AdHocRemoteQueriesEnabled = true.

    dbo.RS_GetListReports:

    CREATE PROCEDURE dbo.RS_GetListReports

    @DBReportServer SYSNAME = NULL,

    @USER_ID INT = NULL,

    @ReportServer SYSNAME = NULL

    AS

    BEGIN TRY

    — Хранимая процедура должна получить список отчетов из Reportig Services

    — Находим базу данных, которая обслущивает Reportig Services

    DECLARE @COMMAND NVARCHAR(1000),

    @ROLE CHAR(1)

    IF NOT EXISTS(SELECT * FROM dbo.Users WHERE User_ID = @USER_ID)

    RAISERROR(‘Не найден пользователь User_ID=%d!’, 16, 127, @USER_ID)

    SELECT @ROLE = RoleUser FROM dbo.Users WHERE User_ID = @USER_ID

    CREATE TABLE #ListReport (PolicyRoot int, Type int, CreationDate datetime, ModifiedDate datetime

    , ItemID char(36)

    , ParentID char(36), Path varchar(425) COLLATE SQL_Latin1_General_CP1251_CI_AS

    , Name varchar(425) COLLATE SQL_Latin1_General_CP1251_CI_AS )

    IF @DBReportServer IS NULL

    BEGIN

    SET @DBReportServer = dbo._Constans(‘ReportServerDB’)

    IF @DBReportServer = ”

    SET @DBReportServer = ‘ReportServer’

    END

    IF @ReportServer IS NULL

    BEGIN

    SET @ReportServer = dbo._Constans(‘ReportServer’)

    IF @ReportServer = ”

    SET @ReportServer = ‘ReportServer’

    END

    — Удаляем из таблицы Reports.Permissions те записи, которых уже нет в Catalog (Уборка мусора)

    SET @COMMAND = N’DELETE FROM dbo.Reports_Permissions WHERE ItemID NOT IN

    (SELECT a.ItemID FROM OPENROWSET(”SQLNCLI”, ”Server=’ +

    @ReportServer + N’;Uid=AppAdmini;Pwd=Pa$$w0rd;Database=’ + @DBReportServer + ”’,”’ +

    N’SELECT ItemID FROM dbo.Catalog”) a)’

    EXECUTE(@COMMAND)

    SET @COMMAND =

    N’INSERT INTO #ListReport (PolicyRoot, Type, CreationDate, ModifiedDate, ItemID, ParentID, Path, Name)

    SELECT PolicyRoot, Type, CreationDate, ModifiedDate, CAST(ItemID AS char(36)),

    cast(ParentID AS char(36)), Path, Name

    FROM OPENROWSET(”SQLNCLI”, ”Server=’ + @ReportServer + N’;Uid=AppAdmin;

    Pwd=Pa$$w0rd;Database=’ + @DBReportServer + ”’,”’ +

    ‘SELECT * FROM dbo.Catalog WHERE ISNULL(Hidden, 0) = 0”) AS a’ +

    CASE WHEN @ROLE <> ‘A’ THEN N’ WHERE (a.ItemID IN (SELECT ItemID

    FROM dbo.Reports_Permissions) OR (a.Type = 1))’ ELSE ” END

    EXECUTE(@COMMAND)

    SELECT * FROM #ListReport

    ORDER BY Name

    END TRY

    BEGIN CATCH

    IF @@NESTLEVEL = 1

    BEGIN

    IF (XACT_STATE()) <> 0

    ROLLBACK TRAN

    EXEC dbo.ErrorProcess

    END

    ELSE

    EXEC dbo.ErrorProcess 0

    END CATCH

    GO

    GRANT EXECUTE ON dbo.RS_GetListReports TO ASU

    Вместо AppAdmin и Pa$$w0rd необходимо подставить логин и пароль учетной записи (Login – Server-Level Principal), имеющей права на чтение из таблиц dbo.Catalog и dbo.ExecutionLog базы данных сервера отчетов.

    oApp.User_ID – ID пользователя, который вошел в мое клиентское приложение Visual FoxPro. Список пользователей хранится в таблице dbo.Users моей базы данных. Список  доступен через представление (View) dbo.VUsers.

    Использование предложения COLLATE обусловлено различием параметров COLLATE моей базы данных и сервера (а значит, и базы данных сервера отчетов). Это наследие “проклятого прошлого”, т.к. моя база данных была разработана еще во времена SQL сервера версии 6.5!  Если у вас COLLATE сервера и вашей базы данных не отличаются, то предложения COLLATE необходимо исключить.

    Если база данных сервера отчетов находится на другом сервере, то для доступа к таблицам dbo.Catalog и dbo.ExecutionLog базы данных сервера отчетов вместо Remote Query (OPENROWSET), можно использовать расширение олицетворения (EXECUTE AS LOGIN и свойство базы данных TRUSTWORTHY) или механизм доверительных отношений, устанавливаемых с помощью сертификатов. В последнем случае  я должен создать сертификат (CREATE CERTIFICATE…) в своей базе данных, подписать им хранимую процедуру, которая из моей базы данных обращается к ресурсам (таблице) другой базы данных (ADD SIGNATURE TO … BY CERTIFICATE …), сделать BACKUP сертификата в файл (BACKUP CERTIFICATE…), восстановить из этого BACKUP-па сертификат в базе данных Reporting Services 2008 (CREATE CERTIFICATE .. FROM FILE = …) и создать в ней пользователя на основе данного сертификата (CREATE USER … FROM CERTIFICATE …). Затем этому пользователю необходимо дать права на чтение из таблиц базы данных сервера отчетов dbo.Catalog и dbo.ExecutionLog. Подробнее об использовании сертификатов MS SQL Server 2008 для обеспечения доступа из одной базы данных к ресурсам другой, можно прочитать в BOL к SQL Server 2008.

    Метод ViewReport:

    LOCAL m.lcURL

    IF EOF(“ListReport”) OR EMPTY(ListReport.Path)

    RETURN .F.

    ENDIF

    TEXT TO lcURL TEXTMERGE NOSHOW PRETEXT 15

    <<ALLTRIM(THIS.ReportServerURLAccess)>>?<<THISFORM.Url1.AddressToURL(ALLTRIM(ListReport.Path))>>

    &rs:Command=Render&rs:format=HTML4.0&rs:Login=ReportAdmin&rs:Password=

    <<THIS.Encrypt(‘Pa$$w0rd’)>>

    ENDTEXT

    THISFORM.ViewWeb.Navigate(m.lcURL)

    Метод вызывается из события Click() кнопки cmdReport и предназначен для отображения в объекте ViewWeb (ActiveX Web Browser) выбранного отчета. Выбранный отчет находится в текущей записи поля Path курсора ListReport. Для формирования URL отчета я должен к URL Web сервиса сервера отчетов (он хранится в свойстве класса ReportServerURLAccess) через символ знака вопроса’? ‘ добавить необходимые параметры с использование синтаксиса URL Report Services. Синтаксис очень прост:

    http://server/virtualroot?[/pathinfo]&prefix:param=value[&prefix:param=value]…n], где:
    server – Имя компьютера, где запущен Report Services;
    vitualroot – Имя виртуальной директории Report Services. По умолчанию имя этой виртуальной директории равно reportserver;
    ? – символ – разделитель адреса сервера и параметров в полном URL;
    [/pathinfo] – полный путь к выбранному отчету;
    & – разделитель пар “параметр = значение” друг от друга;
    prefix – Опция. Указатель на тип параметра. Если префикс отсутствует, то параметр воспринимается как параметр выбранного отчета;
    param – Имя параметра;
    value – текст, соответствующий значению параметра.

    Пример:

    http://servername/reportserver?/SampleReports/Employee Sales Summary&rs:Command=Render&rs:format=HTML4.0

    Для передачи серверу отчетов логина и пароля я использую префикс rs. Если пользователь еще не прошел аутентификацию, то Reporting Services 2008 вызовет форму Logon.aspx. В методе Page_Load() формы Logon.aspx проверяется наличие переданных параметров (логин и пароль) и в случае их нахождения, делается попытка аутентифицикации пользователя с переданными логином и паролем. В случае успешной аутентификации пользователя, происходит переход по URL требуемого отчета без предъявления формы Logon.aspx для ввода логина и пароля. Вот код события Page_Load() этой формы:

    private void Page_Load(object sender, System.EventArgs e)

    {

    // Получаем параметры, переданные через URL, которые идентифицируют пользователя:

    // 1. in_login – логин пользователя

    // 2. in_password – закодированный пароль пользователя

    if (!this.IsPostBack)

    {

    // Страницу загружаем первый раз, надо проверять информацию в URL

    encPassword = false;

    if (Request.QueryString[“OpType”] == “Export”)

    {

    // Если передан в URL OpType=Export, то это экспорт отчета и подключение

    // также необходимо производить от имени ReportProxyLogin и пароля ReportProxyPassword

    TxtUser.Text = ConfigurationManager.AppSettings[“ReportProxyLogin”];

    TxtPwd.Text = ConfigurationManager.AppSettings[“ReportProxyPassword”];

    BtnLogon_Click(this, null);

    }

    else

    {

    if (Request.QueryString[“rs:Login”] != null)

    {

    TxtUser.Text = Request.QueryString[“rs:Login”];

    }

    if (Request.QueryString[“rs:Password”] != null)

    {

    TxtPwd.Text = Request.QueryString[“rs:Password”];

    }

    if ((string.IsNullOrEmpty(TxtPwd.Text) != true) &&

    (string.IsNullOrEmpty(TxtPwd.Text) != true))

    {

    encPassword = true;

    BtnLogon_Click(this, null);

    }

    }

    }

    }

    В этом методе я пытаюсь найти в списке переданных в URL параметров два параметра: rs:Login и rs:Password. Если параметры переданы, то я сохраняю их в свойствах Text объектов TxtUser и  TxtPwd класса TextBox, устанавливаю свойство класса  encPassword = true и вызываю метод BtnLogon_Click(), который является реакцией на нажатие кнопки “Вход” формы Logon.aspx. Если в URL обнаруживается команда OpType и ее значение Export, то это означает, что пользоваетель из отчета пытается выполнить экспорт данных в один из поддерживаемых экпортируемых форматов Reporting Services 2008. В данном примере в этом случае я также осуществляю подключение к серверу отчетов от имени виртуального администратора, параметры которого (логин и пароль) читаются из раздела AppSettings файла Web.config, находящегося в папке ReportServer. Можно это код заблокировать и тогда при попытке экспорта отчета пользователю предеться вводить свои логин и пароль с которыми он входил в приложение Visual FoxPro 9.0. Разумеется, необходимо данному пользователя через Диспетчер Отчетов (Report Manager) предоставить права “Обозреватель” (Browser) на данный отчет. Если пользователю такое право не дать, то он сможет через клиента Visual FoxPro 9.0 просматривать отчет, но не выполнять его экспорт во внешний файл. В данном реализации метода Page_Load() такое ограничение отсутствует.
    Код метода BtnLogon_Click() осуществляет проверку введенных логина и пароля (свойства Text объектов TxtUser и  TxtPwd соответственно) путем вызова метода LogonUser() прокси объекта моего Reporting Services 2008:

    private void BtnLogon_Click(object sender, System.EventArgs e)

    {

    // Получаем имя сервера отчетов и имя экземпляра сервера отчетов из его файла конфигурации

    string reportServer = ConfigurationManager.AppSettings[“ReportServer”];

    string instanceName = ConfigurationManager.AppSettings[“ReportServerInstance”];

    string redirectUrl = “”;

    try

    {

    ReportServerProxy server = new ReportServerProxy();

    // Получаем URL сервера из файла конфигурации Report Manager

    server.Url = AuthenticationUtilities.GetReportServerUrl(reportServer, instanceName);

    // Вызываю функция сервера LogonUser

    if (encPassword == true)

    {

    server.LogonUser(TxtUser.Text, TxtPwd.Text, “Encrypt”);

    }

    else

    {

    server.LogonUser(TxtUser.Text, TxtPwd.Text, “Empty”);

    }

    encPassword = false;

    redirectUrl = Request.QueryString[“ReturnUrl”];

    if (redirectUrl != null)

    HttpContext.Current.Response.Redirect(redirectUrl, false);

    else

    HttpContext.Current.Response.Redirect(“logon.aspx”, false);

    }

    catch (Exception ex)

    {

    Response.Redirect(“logon.aspx”);

    }

    }

    Передача пароля в форму Logon.aspx должна происходить с его шифрованием. Т.е. значение параметр rs:Password в случае его передачи, должно быть расшифровано перед сравнением с учетными данными пользователя. Для передачи информации о шифровании пароля, метод LogonUser() вызывается с третьим параметром равным “Encrypt”. В случае успешной аутентификации пользователя в методе LogonUser(), я перехожу на требуемый URL ( HttpContext.Current.Response.Redirect(redirectUrl, false)). При этом Reporting Services 2008 просто игнорирует мои параметры rs:Login и rs:Password и отображает требуемый мне отчет. При передачи моих параметров аутентификации через URL без прификса rs, они воспринимаются в сервере отчетов как параметры отчета и передаются ему. Разумеется, в отчете нет таких параметров и возникает ошибка о недопустимых параметров отчета. Поэтому наличие префикса rs для логина и пароля ОБЯЗАТЕЛЬНО!

    Если вызов формы Logon.aspx произошел НЕ из моего клиентского приложения Visual FoxPro 9.0, в просто вводом URL Web сервиса или Диспетчера отчетов Reporting Services 2008, то параметры rs:Login и rs:Password в URL отсутствуют и автоаутентификация не происходит, а форма работает в “штатном режиме”. Это означает, что пользователь должен ввести логин и пароль и нажать на кнопку “Вход”.


    Вернемся к методу ViewReport классу ViewReportService_Main. Полный путь к требуемому отчету может содержать символы, запрещенные для использования в URL. В этом случае их необходимо закодировать в правильном формате в два этапа:

    1. Каждый русский символ переводится в формат UTF-8;
    2. Каждый байт UTF-8 переводится в шестнадцатеричное представление и перед ним ставится символ процента ‘%’.

    Также специальном образом кодируются символы типа ‘<‘, ‘>’, ‘$’, ‘&’ и пр.

    Подробнее об этом можно почитать, например, тут или тут. У меня в приложении за перекодировку отвечает класс URL, который также размещен в библиотеке reportservice.vcx. Для перекодировки URL необходимо вызвать его метод AddressToURL(). Он содержит следующий код:

    LPARAMETERS m.lcAddress

    LOCAL m.i, m.lcChar, m.lcURL, m.lcAddChar

    m.lcAddress = ALLTRIM(m.lcAddress)

    m.lcURL = ”

    m.lcAddChar = ”

    FOR m.i = 1 TO LEN(m.lcAddress)

    m.lcChar = SUBSTR(m.lcAddress, m.i, 1)

    DO CASE

    CASE m.lcChar == ‘ ‘

    m.lcAddChar = ‘+’

    CASE m.lcChar == ‘”‘

    m.lcAddChar = ‘%22’

    CASE m.lcChar == ‘#’

    m.lcAddChar = ‘%23’

    CASE m.lcChar == ‘%’

    m.lcAddChar = ‘%25’

    CASE m.lcChar == ‘&’

    m.lcAddChar = ‘%26’

    CASE m.lcChar == [‘]

    m.lcAddChar = ‘%27’

    CASE m.lcChar == ‘*’

    m.lcAddChar = ‘%2a’

    CASE m.lcChar == ‘,’

    m.lcAddChar = ‘%2c’

    CASE m.lcChar == ‘:’

    m.lcAddChar = ‘%3a’

    CASE m.lcChar == ‘;’

    m.lcAddChar = ‘%3b’

    CASE m.lcChar == ‘<‘

    m.lcAddChar = ‘%3c’

    CASE m.lcChar == ‘>’

    m.lcAddChar = ‘%3e’

    CASE m.lcChar == ‘?’

    m.lcAddChar = ‘%3f’

    CASE m.lcChar == ‘[‘

    m.lcAddChar = ‘%5b’

    CASE m.lcChar == ‘^’

    m.lcAddChar = ‘%5e’

    CASE m.lcChar == ‘`’

    m.lcAddChar = ‘%60’

    CASE m.lcChar == ‘{‘

    m.lcAddChar = ‘%7b’

    CASE m.lcChar == ‘|’

    m.lcAddChar = ‘%7c’

    CASE m.lcChar == ‘}’

    m.lcAddChar = ‘%7d’

    CASE m.lcChar == ‘/’

    m.lcAddChar = ‘%2f’

    CASE m.lcChar $ ;

    “яюьыъщшчцхфутсрпонмлкйизжедгвбаёЯЮЭЬЫЪЩШЧЦХФУТСРПОНМЛКЙИЗЕДГВБАЁ”

    *– Русский символ

    m.lcAddChar = THIS.CharToURL(m.lcChar)

    OTHERWISE

    m.lcAddChar = m.lcChar

    ENDCASE

    m.lcURL = m.lcURL + m.lcAddChar

    ENDFOR

    RETURN m.lcURL

    Метод AddressToURL() с целью перекодировки русского символа вызывает метод CharToURL(). Вот его код:

    LPARAMETERS m.lcChar

    LOCAL m.lcStr

    m.lcStr = STRCONV(m.lcChar,9)

    RETURN LOWER(‘%’ + RIGHT(TRANSFORM(ASC(LEFT(m.lcStr,1)), “@0”), 2) ;

    + ‘%’ + RIGHT(TRANSFORM(ASC(RIGHT(m.lcStr,1)), “@0”), 2))

    Сначала я перевожу символ в формат UTF-8 (STRCONV(m.lcChar,9)) , а затем каждый байт преобразую в шестнадцатеричную форму с добавлением перед каждым символом знак процента ‘%’.

    Управления правами на просмотр отчетов происходит в методе SetPermissions() класса ViewReportService_Main, который вызывается из события Click() кнопки cmdSetPermissions. Вот его код:

    *– Установка прав просмотра данного отчета

    LOCAL m.loForm

    WITH THIS

    m.loForm = CREATEOBJECT(‘ReportService.SetPermission’, ;

    THISFORM, ListReport.ItemID)

    IF VARTYPE(m.loForm) = ‘O’

    m.loForm.lblCaption.Caption = ‘Установка прав на просмотр отчета: ‘ + ;

    ALLTRIM(ListReport.Name)

    m.loForm.Show(1)

    ENDIF

    ENDWITH

    Как видно из приведенного кода, вся функциональность по управлению правами пользователей на просмотр отчета ListReport.ItemID находится в классе ReportService.SetPermission. Класс создан на основе класса Edit_Form из моей библиотеки классов MyClass.vcx. В дизайнере классов он выглядит следующим образом:


    Список прав для выбранного отчета я читаю с помощью хранимой процедуры dbo.RS_GetPermissions, которой передается в качестве параметра уникальный идентификатор отчета. Вот код этой хранимой процедуры:

    CREATE PROCEDURE dbo.RS_GetPermissions

    @ItemID UNIQUEIDENTIFIER = NULL

    — Список всех пользователей и права на заданный отчета

    AS

    BEGIN TRY

    SELECT u.Login, u.User_ID, u.Podr_Name, u.FIO AS User_Name

    , ISNULL(u.EMail, ”) AS EMail

    , IsGrant =

    CASE

    WHEN p.User_ID IS NULL THEN 0

    ELSE 1

    END

    FROM dbo.VUsers u LEFT JOIN dbo.Reports_Permissions p

    ON u.User_ID = p.User_ID AND p.ItemID = @ItemID

    WHERE u.Role <> ‘A’

    END TRY

    BEGIN CATCH

    IF @@NESTLEVEL = 1

    BEGIN

    IF (XACT_STATE()) <> 0

    ROLLBACK TRAN

    EXEC ErrorProcess

    END

    ELSE

    EXEC ErrorProcess 0

    END CATCH

    Хранимая процедура dbo.RS_GetPermissions читает список всех пользователей моей системы и в вычисляемом поле IsGrant находится признак наличия права просмотра на данный отчет данного пользователя.

    Список пользователей выводится в объекте класса SMART_GRID. А в колонке SColumn5 выводится картинка, показывающая доступен ли выбранный отчет данному пользователю. При событии DblClick() на картинке, вызывается метод SetResGrant() класса SetPermission. Вот его код:

    WITH THIS

    SELECT ListUsersPerm

    IF ListUsersPerm.IsGrant = 0

    TEXT TO lcCommand TEXTMERGE NOSHOW PRETEXT 7

    INSERT INTO dbo.Reports_Permissions (User_ID, ItemID)

    VALUES (<<ListUsersPerm.User_ID>>, ‘<<.RSItemID>>’)

    ENDTEXT

    IF SQL(lcCommand) = 0

    SELECT ListUsersPerm

    REPLACE IsGrant WITH 1

    ENDIF

    ELSE

    TEXT TO lcCommand TEXTMERGE NOSHOW PRETEXT 7

    DELETE FROM dbo.Reports_Permissions

    WHERE User_ID = <<ListUsersPerm.User_ID>>

    AND ItemID = ‘<<.RSItemID>>’

    ENDTEXT

    IF SQL(lcCommand) = 0

    SELECT ListUsersPerm

    REPLACE IsGrant WITH 0

    ENDIF

    ENDIF

    .Refresh()

    ENDWITH

    Как видно из приведенного кода, я удаляю (убрать права у выбранного пользователя на просмотр данного отчета) или добавляю запись (дать права выбранному пользователю на просмотр данного отчета).

    Для просмотра истории выполнения отчетов использутся класс rs_viewhistory, который выполняется в методе ViewLog():

    *– Просмотр и редактирование журнала Report Server

    LOCAL loForm

    WITH THIS

    loForm = CREATEOBJECT(‘ReportService.RS_ViewHistory’, THISFORM)

    IF VARTYPE(m.loForm) = ‘O’

    m.loForm.Show(1)

    ENDIF

    ENDWITH

    Данный метод вызывается из события Click() объекта cmdViewLog.

    В редакторе класса форма выглядит следующим образом:


    Для чтения истории выполнений отчетов в Report Services я вызываю в событии Init() данного класса хранимую процедуру dbo.RS_GetLog. Вот ее код:

    CREATE PROCEDURE dbo.RS_GetLog

    @DBReportServer SYSNAME = NULL,

    @ReportServer SYSNAME = NULL

    AS

    BEGIN TRY

    — Хранимая процедура должна получить список отчетов из ReportService

    — Находим базу данных, которая обслущивает ReportServer

    DECLARE @COMMAND NVARCHAR(1000)

    CREATE TABLE #Log (ReportID char(36),UserName VARCHAR(50) COLLATE SQL_Latin1_General_CP1251_CI_AS

    , Format VARCHAR(50), Parameters Text COLLATE SQL_Latin1_General_CP1251_CI_AS

    , TimeStart DATETIME, TimeEnd DATETIME, Status VARCHAR(50)

    , Name varchar(425) COLLATE SQL_Latin1_General_CP1251_CI_AS

    , Path varchar(425) COLLATE SQL_Latin1_General_CP1251_CI_AS)

    IF @DBReportServer IS NULL

    BEGIN

    SET @DBReportServer = dbo._Constans(‘ReportServerDB’)

    IF @DBReportServer = ”

    SET @DBReportServer = ‘ReportServer’

    END

    IF @ReportServer IS NULL

    BEGIN

    SET @ReportServer = dbo._Constans(‘ReportServer’)

    IF @ReportServer = ”

    SET @ReportServer = ‘ReportServer’

    END

    SET @COMMAND =

    N’INSERT INTO #Log (ReportID, UserName, Format, Parameters, TimeStart, TimeEnd, Status, Name, Path)

    SELECT ReportID, UserName, Format, Parameters, TimeStart, TimeEnd, Status, Name, Path

    FROM OPENROWSET(”SQLNCLI”, ”Server=’ + @ReportServer + N’;Uid=AppAdmin;Pwd=Pa$$w0rd;Database=’

    + @DBReportServer + ”’,”’ +

    ‘SELECT e.ReportID, e.UserName, e.Format, e.Parameters, e.TimeStart, e.TimeEnd, e.Status

    , ISNULL(c.Name, ””ОТЧЕТ УДАЛЕН””) AS Name, ISNULL(c.Path, ””””) AS Path

    FROM dbo.ExecutionLog e LEFT JOIN dbo.Catalog c ON e.ReportID = c.ItemID”) a’

    EXECUTE(@COMMAND)

    SELECT * FROM #Log

    ORDER BY TimeStart

    END TRY

    BEGIN CATCH

    IF @@NESTLEVEL = 1

    BEGIN

    IF (XACT_STATE()) <> 0

    ROLLBACK TRAN

    EXEC dbo.ErrorProcess

    END

    ELSE

    EXEC dbo.ErrorProcess 0

    END CATCH

    Историю выполнения отчетов я читаю из таблиц dbo.ExecutionLog и dbo.Catalog базы данных сервера отчетов.

    После чтения данных они отображаются на форме с помощью объекта класса SMART_GRID. Имя отчета, полный путь к нему и список параметров при его выполнении также отображаются и в соответствующих объектах класса Editbox.

    При большом кол-ве отчетов, доступных пользователю, или сложной иерархической структуры папок размещения отчетов на сервере отчетов, становится не очень удобно использовать объект cboListReports класса Combobox для поиска требуемого отчета. Помощь пользователю в этом случае может оказать класс viewreportservice_find, экземпляр которого вызывается из события Click() объекта cmdFindReport. В данном классе отчеты и папки, доступные пользователю выводятся в объекте моего класса aTreeView, который является наследником класса ActiveX TreeView. По клавише F2 можно выполнить поиск в “дереве”, что позволит быстро найти требуемый объект. В режиме работы класс выглядит следующим образом:


    Внедрение интеграции сервера отчетов Reporting Services 2008 R2 в клиентское приложение Visial FoxPro 9.0

    Инсталляция на серверной стороне

    ВАЖНО:

    Перед внесением изменений в конфигурационные файлы Report Server и Report Manager, сделайте их резервную копию. Режим “Forms Authentication security” НЕ ПОДДЕРЖИВАЕТСЯ в Reporting Services 2008 R2 Express.

    По умолчанию, Reporting Services установлен в папку <install>=C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services

    Процесс инсталляции для SQL Server 2008 и для SQL Server 2008 R2 не отличаются друг друг от друга.

    Процесс интеграции сервера отчетов Reporting Services 2008 R2 в клиентское приложене Visial FoxPro 9.0 выполняется с помощью следующих шагов:

    • Скопируйте сборку VFox.RS2008.CustomSecurity.dll в папку <install>\ReportServer\bin;
    • Cкопируйте сборку VFox.RS2008.CustomSecurity.dll в папку <install>\ReportManager\bin;
    • Cкопируйте страницу Logon.aspx в папку <install>\ReportServer;
    • Cкопируйте страницу UILogon.aspx в папку <install>\ReportManager\Pages;
    • Если вы собираетесь отлаживать код своей сборки в Visual Studio 2005, то скопируете вместе с файлом VFox.RS2008.CustomSecurity.dll также и файл VFox.RS2008.CustomSecurity.pdb.

    Учтите, что для такой операций вам необходимы администраторские привилегии при работе в операционных системах Vista, Windows 2008 и Windows 7.

    Изменение файла RSReportServer.config

    Откройте файл RSReportServer.config в среде Visual Studio 2005 или при помощи обычного текстового редактора (например в Блокноте). Файл RSReportServer.config расположен в каталоге <установка>\ReportServer.

    Отключите обязательное использование SSL изменив ключ SecureConnectionLevel с 2 на 0:

    <Add Key=”SecureConnectionLevel” Value=”0″/>

    • Найдите в нем элемент <AuthenticationTypes> и измените параметры следующим образом:

    <Authentication>

    <AuthenticationTypes>

    <Custom/>

    </AuthenticationTypes>

    <EnableAuthPersistence>true</EnableAuthPersistence>

    </Authentication>

    • Найдите элементы <Security> и <Authentication> внутри элемента <Extensions> и измените их следующим образом:

    <Security>

    <Extension Name=”Forms”

    Type=”VFox.RS2008.CustomSecurity.Authorization,VFox.RS2008.CustomSecurity.CustomSecurity”>

    <Configuration>

    </Configuration>

    </Extension>

    </Security>

    <Authentication>

    <Extension Name=”Forms”

    Type=”VFox.RS2008.CustomSecurity.AuthenticationExtension,VFox.RS2008.CustomSecurity”>

    <Configuration>

    <AdminConfiguration>

    <ConnectionString>Server=<ИМЯ ВАШЕГО СЕРВЕРА>;Database=TEST;User ID=LoginForAll;

    Password=Pa$$w0rd;Trusted_Connection=False

    </ConnectionString>

    <AdminLogin>ReportAdmin</AdminLogin>

    <AdminPassword>Pa$$w0rd/AdminPassword>

    </AdminConfiguration>

    </Configuration>

    </Extension>

    </Authentication>

    Значения элементов <AdminLogin> и <AdminPassword> можно установить как вам удобно. Пользователь <AdminLogin> используется для первого входа в Reporting Services. После внедрения данной системы и добавления пользователя в Reporting Services с назначением ему прав Content Manager, этого пользователя можно в дальнейшем не использовать. Если у вас в таблице Users есть хоть один пользователь со значением поля RoleUser = ‘A’ (администратор), то AdminLogin вам может и не потребоваться, т.к. метод CheckOperations в классе Authorization всегда возвращает true если у пользователя RoleUser = ‘A’ в не зависимости от набора прав, выданному данному пользователю на объекты Reporting Services. Если вы поменяете значения элементов <AdminLogin> и <AdminPassword>, то не забудьте также их заменить в методе ViewReport класса ViewreportService_Main.

    Замените в <ConnectionString> имя сервера, имя базы данных и параметры пользователя, имеющего  права в вашей базе читать из представления dbo.VUsers и выполнять хранимую процедуру Admin_TestPassword,  на используемые у вас.

    Найдите элемент <UI> и измените его следующим образом:

    <UI>

    <CustomAuthenticationUI>

    <loginUrl>/Pages/UILogon.aspx</loginUrl>

    <UseSSL>False</UseSSL>

    </CustomAuthenticationUI>

    <ReportServerUrl>http://<Имя Вашего сервера очтетов>/ReportServer</ReportServerUrl>

    </UI>

    Учтите, что вместо <Имя Вашего сервера отчетов> использовать  localhost нельзя. Используйте имя компьютера вашего Reporting Services 2008.

    Изменение файла RSSrvPolicy.config

    • Откройте файл RSSrvPolicy.config, расположенный в каталоге <установка>\ReportServer.
    • Добавьте в файл политики безопасности RSSrvPolicy.config следующий элемент <CodeGroup> непосредственно ПЕРЕД существующей группы кода, имеющей URL-членство $CodeGen:

    <CodeGroup

    class=”UnionCodeGroup”

    version=”1″

    Name=”SecurityExtensionCodeGroup”

    Description=”Code group for integration RS 2008 R2 and Visual FoxPro 9.0 client””

    PermissionSetName=”FullTrust”>

    <IMembershipCondition

    class=”UrlMembershipCondition”

    version=”1″

    Url=”C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\

    ReportServer\bin\VFox.RS2008.CustomSecurity.dll” />

    </CodeGroup>

    Изменение файла RSMgrPolicy.config

    • Откройте файл политики диспетчера отчетов RSMgrPolicy.config, расположенный в каталоге <установка>\ReportManager.
    • Найдите в файле RSMgrPolicy.config следующую группу кода и измените атрибут PermissionSetName с Execution на FullTrust, как показано ниже:

    <CodeGroup

    class=”FirstMatchCodeGroup”

    version=”1″

    PermissionSetName=”FullTrust”

    Description=”This code group grants MyComputer code Execution permission.”>

    <IMembershipCondition

    class=”ZoneMembershipCondition”

    version=”1″

    Zone=”MyComputer” />

    Изменение файла Web.config для сервера отчетов

    • Откройте файл Web.config в текстовом редакторе. По умолчанию сборка расположена в каталоге <установка>\ReportServer.
    • Найдите элемент <identity> и присвойте атрибуту Impersonate значение false.

    <identity impersonate=”false” />

    • Найдите элемент <authentication> и присвойте атрибуту Mode значение Forms.
    • Добавьте следующий элемент <forms> в качестве дочернего элемента для элемента <authentication> и присвойте атрибутам loginUrl, name, timeout и path следующие значения:

    <authentication mode=”Forms”>

    <forms loginUrl=”logon.aspx” name=”sqlAuthCookie” timeout=”60″

    slidingExpiration=”true” path=”/”></forms>

    </authentication>

    • Добавьте следующий элемент <authorization> непосредственно после элемента <authentication>.

    <authorization>

    <deny users=”?” />

    </authorization>

    Это запретит доступ к серверу отчетов не прошедшим проверку   пользователям.
    Ранее установленный атрибут loginUrl элемента   <authentication> будет перенаправлять не прошедшие проверку запросы на страницу Logon.aspx.

    • Добавьте элемент <appSettings> между элементами <system.web> и <runtime>:

    <appSettings>

    <add key=”ReportServer” value=”ИМЯ ВАШЕГО СЕРВЕРА ОТЧЕТОВ”/>

    <add key=”ReportServerInstance” value=”ИМЯ ВАШЕГО ЭКЗЕМПЛЯРА СЕРВЕРА ОТЧЕТОВ”/>

    <add key=”ReportProxyLogin” value=”ReportAdmin”/>

    <add key=”ReportProxyPassword” value=”Pa$$w0rd”/>

    </appSettings>

    Подставьте ваши значения имени сервера отчетов и имени экземпляра сервера отчетов. Ковычки вокруг имен обязательны. По желанию, можете поменять логин и пароль для виртуального пользователя – адимнистратора сервера отчетов.

    Имя экземпляра Reporting Services проще всего выяснить, выполнив следующую PowerShell команду:

    get-wmiobject -namespace “root\Microsoft\SqlServer\ReportServer” -class  “__Namespace”

    Напоминаю, что PowerShell можно запустить из командной строки операционной системы, набрав в ней: powershell.

    Изменение файла Web.config для диспетчера отчетов

    • Откройте файл Web.config диспетчера отчетов. Файл Web.config расположен в каталоге <установка>\ReportManager.
    • Отключите олицетворение, найдя раздел <identity impersonate= “true” /> и изменив его следующим образом:

    <identity impersonate=”false” />

    • Добавьте следующие ключи в элемент <appSettings>:

    <add key=”ReportServer” value=”ИМЯ ВАШЕГО СЕРВЕРА ОТЧЕТОВ”/>

    <add key=”ReportServerInstance” value=”ИМЯ ВАШЕГО ЭКЗЕМПЛЯРА СЕРВЕРА ОТЧЕТОВ”/>

    Подставьте ваши значения имени сервера отчетов и имени экземпляра сервера отчетов. Кавычки вокруг имен обязательны.

    Имя экземпляра Reporting Services проще всего выяснить, выполнив следующую PowerShell команду:

    get-wmiobject -namespace “root\Microsoft\SqlServer\ReportServer” -class  “__Namespace”

    В заключении необходимо перезапустить Reporting Services 2008 с помщью SQL Server Configuration Manager, Reporting Services Configuration Manager или из командной строки с помощью команд:

    net stop “SQL Server Reporting Services (<Instance Name>)”

    net start “SQL Server Reporting Services (<Instance Name>)”

    Отладка кода сборки

    Для отладки кода сборки VFox.RS2008.CustomSecurity.dll необходимо выполнить следующее:

    1. В Visual Studio 2005 откомпилируйте ваш проект с выбранной конфигурацией Debug;
    2. Скопируйте  вместе с самой сборкой также файл VFox.RS2008.CustomSecurity.pdb;
    3. Запустите через утилиту Reporting Services Configuration Manager ваш Report Server;
    4. В Visual Studio 2005 из меню Debug выберете пункт Attach to Process.
    5. Найдите в списке процессов процесс с именем ReportingServicesService.exe и щелкните кнопку Attach;
    6. В Visual Studio 2005 установите точки останова, требуемые для  вашей отладки;
    7. Откройте Internet Explorer и перейдите к URL Web сервиса отчетов или URL диспетчера отчетов (в зависимости от того, что вы отлаживаете). Очень просто это выполнить через Reporting Services Configuration Manager;
    8. Выполните необходимые действия для достижения заданой точки остановки и по ее достижению вы будет переключены в Visual Studio 2005;
    9. Продолжайте отладку кода с использованием окон Local, Watch, Call Stack и пр.

    Инсталляция на клиентской стороне

    • Включите в проект библиотеки классов reportservice.vcx и _webview:
      SET CLASSLIB TO ReportService, _webview ADDITIVE;
    • Учтите, что классы из библиотеки reportservice.vcx наследованы от классов библиотек myclass.vcx и mycontrols.vcx;
    • Для доступа к отчетам Reporting Services достаточно при генерации главного меню приложения (метод DoMenu класса csfw) добавить пункт:
      DEFINE BAR 5 OF p_Test PROMPT “Просмотр отчетов Reporting Services”
      ON SELECTION BAR 5 OF p_Test oApp.ExecObject(“viewreportservice”);
    • Не забудьте отредактировать свойства класса
      ReportServerDB – имя базы данных Reporting Services 2008. По умолчанию оно равно значению ReportServer;
      ReportServer – имя сервера с  Reporting Services 2008. По умолчанию оно равно имени компьютера, где находися ваша база данных;
      ReportServerURLAccess – URL к Web сервису сервера отчетов. По умолчанию оно пусто. Это приводит к тому, что в методе Init класса это свойстов вычисляется как ‘http://’ + имя_компьютера_сервера_отчетов + ‘/reportserver’.

    Для установки вам потребуется скачать:

    • Проект VFox.ReportServer.CustomSecurity2008. Из него вам понадобятся файлы: VFox.RS2008.CustomSecurity.dll, UILogon.aspx, Logon.aspx и VFox.RS2008.CustomSecurity.pdb (только для отладки);
  • Библиотеки классов reportservice и _webview;
  • Обновить картинки и иконки.
  • Скачать скрипты SQL Server, которые создают необходимые серверные объекты (хранимые процедуры, view и пр.).
    Самое удобное – скачать весь демонстрационный проект и backup базы данных TEST. Тогда вы точно ничего не упустите. Только не забудьте после восстановления базы данных создать логины на своем сервере и восстановить их связь с пользователями тестовой базы данных.
  • Также скачать файлы можно со страницы скачивания моего сайта.

    Вот и все! Удачи и пишите если что не получится!

    Алексей Климов

Главная SQL, Без рубрики, Новое SQL, SQL 2008 R2, Конкурс