воскресенье, 17 мая 2009 г.

UAC для разработчика 2

Сегодня наконец-то нашел решение проблемы с повышением привилегий для приложения в runtime, которую я озвучивал в одном из своих предыдущих постов. Решение крылось в создании специального COM объекта, который будет содержать весь привилегированный код, требующий повышенных привилегий.
Не буду полностью рассказывать эту возможность, поскольку это все уже описано в блоге Alexander Bozhko Bold&ECO blog
Цикл статей посвященный UAC:
Использование Vista UAC в Delphi: Часть 1
Использование Vista UAC в Delphi: Часть 2
Использование Vista UAC в Delphi: Часть 3

По всей видимости эти же методы будут работать и в Windows 7 - поскольку Microsoft обещает практически полную совместимость с программами, разработанными для Vista.




четверг, 14 мая 2009 г.

Borland утонул

Для многих это уже не новость, но о качестве моего Интернета уже можно слагать легенды - поэтому пишу пока работает, а со стороны выглядит, что притормаживаю. :)

Итак, Borland окончательно утонул. Как мне кажется, основной причиной стало то, что он в свое время отвернулся от того - что и было его именем - от инструментов для программистов и углубился в жизненный цикл. И вот - пожалуйста:

По заключенному 6 мая соглашению, Micro Focus купит Borland из расчета один доллар за акцию. Это на 25% выше стоимости ценных бумаг Borland по итогам торгов во вторник, когда за каждую акцию компании давали 80 центов. Средний же курс ценных бумаг Borland за последние 30 дней составил 60 центов.

Но, тем не менее, последние его решения можно только поприветствовать. Утонув сам - не утащил за собой все наиболее значимые проекты, которые удалось спасти.

Первой ласточкой уходящего Borland'a стала СУБД Interbase - после открытия исходных кодов которой на свет появился проект Firebird.

Затем было выделение отдельно средств разработки и передача их компании Embarcadero - опять же во спасение. (Это было как раз год назад - я писал об этом) И только после того как все эти телодвижения были совершены - Borland спокойненько прекратил свое существование. Причем бесславно. Будем надеяться новые хозяева смогут вернуть к жизни эти продукты и они снова будут столь популярны и востребованы. Но их уже будут знать под другим именем ...

вторник, 12 мая 2009 г.

Субботник на блоге

После небольшого перерыва в месяц (отпуска?) заглянул на собственный блог и ужаснулся. Чертовски долго грузится, плюс ко всему ошибки со скриптами везде. Поэтому перво-наперво решил навести "порядок" - своего рода майский субботник :).

Первое - тормоза. Из-за чего? Конечно же из-за скриптов. Дело в том, что пока я отдыхал - бесславно помер сервис feedmates (ссылку не привожу - помер ведь). Виджет, установленный на блоге пытался обратиться и ждал ... ждал ... ждал... пока не наступал таймаут соединения. Естественно страничка все это время не прорисовывалась. Все, убрал его.

Вместо этого добавил список рекомендуемых постов после каждой заметки - думаю пригодится новым посетителям. :)

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

Но это еще не все! Меня ждал ещё один не очень приятный сюрприз - исходный код в постах перестал подсвечиваться. Синтаксис исходного кода у меня подсвечивается с помошью скрипта, способом описанном на блоге BlogoHelp. Там не мудрствуя лукаво предлагается грузить скрипт сразу с ресурса авторов. Но авторы - тоже люди, и не стали терпеть такую наглость и просто убрали скрипт в другое место. Не став наглеть дальше - закачал скрипт к себе на хостинг и все заработало как и прежде.

Решил поменять иконку блога. Особо не отличаясь оригинальностью, поставил стандартную иконку приложения написанного на Delphi. Кстати, для размещения favicon.ico я воспользовался сервисом для генерации и хостинга favicon (да-да есть и такое - чего только не придумают для блоггеров). Там ничего сложного, кому надо - разберется, если возникнут проблемы - пишите в комментарии, постараюсь помочь.

Пока решил на этом остановиться, но улучшения на этом не заканчиваются - многое ещё предстоит сделать.

суббота, 11 апреля 2009 г.

Простой пример клиента для WebService

Одному моему коллеге понадобилось написать небольшого клиента для сервера контента системы электронного документооборота. Собственно сам сервер контента реализован в виде WEB-сервиса, предоставляющего некоторые функции для доступа к документам. Что он только не пробовал и ClientSocket и TCPConnection и HTTPRIO. Но на самом деле все достаточно просто, и не нужно изобретать велосипед :)

Сразу же оговорюсь , что данный пост не претендует на полноту изложения данной темы, здесь я просто хочу показать в каком направлении следует «копать» и покажу как обойти один подводный камень, на который можно наткнуться при создании клиента для WEB-сервисов.

Итак, приступим … У нас есть некоторый WEB-сервис, предоставляющий некоторые функции. Пусть это будет некоторый ASP.NET WebService запущенный на соседней машине с именем Athlon, URI данного WEB-сервиса выглядит следующим образом: http://athlon/test/service.asmx . Набрав данный URI в браузере получаем тестовую страничку, сгенерированную IIS для проверки работоспособности WEB-сервиса:


Из тестовой страницы видно, что WEB-сервис поддерживает одну единственную процедуру с именем HelloWorld. Попробуем ее вызвать из клиентского приложения на Delphi. Естественно создадим новый проект, сохраним куда-нибудь по-удобнее, и займемся самым интересным – автоматической генерацией кода для доступа к WEB-сервису. Для этого в среде Delphi есть специальный мастер который вызвается следующей командой: File -> New -> Other … -> WebServices -> WSDL Importer:



В мастер вводится один единственный параметр – это URI нашего WEB-сервиса:



Но при попытке перейти на следующий шаг мастера появится сообщение об ошибке, примерно следующего содержания, толком ничего не говорящего:



Давайте разберемся, что это такое и почему это происходит. Еще раз наберем URI WEB-сервиса в строке адреса браузера – на экране отобразится тестовая страничка. Тоже самое происходит когда по данному URI обращается мастер – в соответствии с протоколом SOAP он ждет XML описания WEB-сервиса, а ему вместо этого выдают обычную html-страницу. Именно по этому он вываливается с ошибкой невразумительного содержания, поскольку пытается разобрать html и ему это не удается и он сообщает на каких именно тэгах разметки он вы вывалился. Чтобы этого не происходило, мы должны явно указать WEB-сервису, что мы ждем от него WSDL описание сервиса. Делается это очень просто, просто добавляется параметр ?WSDL в URI WEB-сервиса:


http://athlon/test/service.asmx?WSDL



Теперь мастер получает именно те данные, которые ожидает и генерация кода происходит без ошибок:



В результате сгенерировался довольно большой код, ключевой фрагмент которого выглядит так:


  ServiceSoap = interface(IInvokable)
['{77573149-9C57-FA51-F11F-EFD527C91BD9}']
function HelloWorld: string; stdcall;
end;

function GetServiceSoap(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): ServiceSoap;

Здесь объявляется интерфейс нашего WEB-сервиса и функция для получения этого интерфейса, именно с ними мы и будем дальше работать. Просто для примера вызовем в обаботчике события OnClick для кнопки процедуру и выведем сообщение с результатом


procedure TForm1.Button1Click(Sender: TObject);
var
ws: ServiceSoap;
begin
// получаем интерфейс
ws := GetServiceSoap();
// вызываем процедуру сервиса
with ws do
ShowMessage(HelloWorld);
end;

Вот собственно и все - клиент для WEB-сервиса готов. На его создание потрачено совсем немного времени и написано совсем небольшое количество кода.


понедельник, 9 февраля 2009 г.

Windows 7 и Delphi

Поддавшись случившейся не так давно в Интернете истерии по поводу выхода первой публичной беты Windows 7, скачал себе 64-разрядную версию и на некоторое время пропал в ней. :) Это было мое первое знакомство с 64-разрядной операционной системой (не говоря уже о Windows 7), хотя мой компьютер уже давным-давно поддерживает их. Все установилось и заработало на удивление гладко, за исключением дурацкого 3G модема от билайна (обыкновенный GPRS-модем от мегафона даже нисколечко не сопротивлялся). Возможно, Microsoft более серьезно подошла к разработке своей новой операционки, а возможно рассказы о проблемах 64-битных систем оказали такими же «сказками на ночь», как и большинство сказок про Vista. Мне почему-то кажется что второе. :)

Но это не очередной хвалебный пост в пользу Microsoft, так что на этом закругляюсь. Остановлюсь только на работе Delphi в Windows 7. Delphi 2009 устанавливается и работает без проблем – так как ей и положено. Про Delphi 7 пока ничего толком сказать не могу, поскольку еще не устанавливал ее, но мне кажется, что также проблем не будет.

Удивительно, но весь негатив сопутствующий появлению Windows Vista, превратился в позитивные настроения всей «экосистемы» (как это называет Microsoft) перед выходом Windows 7. Это касается Delphi-сообщества, вот например Daniel Wischnewski уже создал прототип нескольких компонентов, позволяющих уже сейчас добавлять в приложения поддержку новых возможностей Windows 7 (в первую очередь визуальных).


Естественно, что все эти новые возможности будут работать только в Windows 7. И еще важное замечание. Хотя у компонентов и присутствует инсталлятор, он просто копирует необходимые файлы, устанавливать их придется вручную.


суббота, 31 января 2009 г.

UAC для разработчика

UAC (User account control) впервые появился в Windows Vista, и сразу же, не заслуженно, получил отрицательную репутацию, а в Интернете появилось полным полно статей как его отключить. Доходит даже до откровенного маразма, что эту функцию ставят как основной недостаток этой операционной системы. Не буду здесь подробно на нем останавливаться, скажу лишь, что у меня он включен по умолчанию, и я нахожу его очень даже полезным для себя, тем более что в Windows 7 он был значительно переработан, хотя на вкус и цвет – все фломастеры разные.

Хотим мы этого или нет UAC есть в операционной системе, и будет дальше, а разработчик программного обеспечения должен учитывать все возможные конфигурации системы, в том числе и с включенным UAC.

Несмотря на то, что UAC обладает некоторой "интеллектуальностью" и при запуске может определить нужно ли приложению увеличение привилегий или нет – возможности его ограничены, и он не всегда корректно работает, что приводит к тихому (или не всегда к тихому) «помиранию» запущенной программы, которой необходимы права администратора, но которые ей никто не дал. Поэтому перед разработчиком стоит задача явно указать необходимый уровень привилегий для своего приложения. Делается это через все тот же файл-манифест приложения, который появился в Windows XP и который используется для отрисовки интерфейса "в стиле XP".

Для явного указания необходимого уровня привилегий используется раздел Security:

<security>
<requestedprivileges>
<requestedexecutionlevel level="requireAdministrator">
</requestedprivileges>
</security>

Полностью файл-манифест приложения может выглядеть, например следующим образом:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*"
name="UAC_Elevation_Prompt" type="win32" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32"
name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*" />
</dependentAssembly>
</dependency>
</assembly>

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

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

Но не все так просто в Delphi 2009. По каким-то своим, никому не известным причинам, разработчики решили добавлять манифест во все проекты по умолчанию. С одной стороны – довольно удобно, но с другой получается наоборот больше работы. Вот, например, так же по умолчанию в ресурсы добавляется иконка приложения и информация о версии. Это не плохо – потому, что существуют инструменты для их быстрого и безболезненного изменения. А манифест – не очень хорошо, мягко говоря, потому как он жестко задан в файле WindowsXP.res в наиболее общей форме и не учитывает специфики конкретного приложения, и нет инструментов для его изменения.

Так вот, при попытке добавления описанного выше манифеста в проект Delphi 2009 получаем предупреждение компилятора о дублировании ресурсов и наш манифест не включается в приложение. Можно перейти в исходный код проекта и убрать директиву компилятора {$R *.res}, но в этом случае мы лишимся иконки приложения и информации о версии. Можно убрать файл WindowsXP.res куда подальше, чтобы Delphi его не нашла – но это тоже неудачный способ выхода из положения – поскольку нарушается работа VCL.

Пока я не нашел способа грамотно подменить манифест приложения, так же остается открытым вопрос повышения привилегий во время выполнения программы, поскольку приложению могут понадобится права администратора только для выполнения какой либо одной операции, которая еще и не всегда используется и нет смысла его постоянно гонять под админом.

Оригинальный способ для решения проблем использован в файловом менеджере Total Commander – для выполнения операций требующих повышения привилегий используется отдельное приложение TCADMIN.EXE, которому передается команда в случае невозможности выполнения операции с правами текущего пользователя.

Интересно, а как еще можно организовать повышение привилегий в Runtime и решить проблемы с манифестом в Delphi 2009?

суббота, 24 января 2009 г.

Установка FIBPlus на Delphi 2009 Trial

Установка обновленных компонентов FIBPlus, о релизе которых я писал ранее, не обошлась без пляски с бубном.

Началось все с того, что инсталлятор не смог корректно установить компоненты на пробную версию Delphi 2009. В результате я получил оошибку:

!!! Unsucessfuly compile package FibPlus2009.dpk!!!


Открыв лог-файл, созданный в результате установки, я обнаружил истинную причину:

Generate DCC32 config file: C:\Program Files\Devrace\FIBPlus_Unicode\7.0.1076\sources\dcc32.cfg
Initial directory = C:\Program Files\Devrace\FIBPlus_Unicode\7.0.1076\sources\
Command Line = "C:\Program Files\CodeGear\RAD Studio\6.0\bin\dcc32.exe" FibPlus2009.dpk

Command line tools are not supported in the trial version.

Замечательно! Ну ладно, всегда можно скомпилировать и установить пакеты через IDE Delphi. Но эта попытка тоже не увенчалась успехом. Компилятор отказался найти файлы библиотеки FIBPlus, не смотря на то что при установке было указано добавить все пути в нужное место. Даже после того как я прописал все необходимые пути (Tools->Options->Library Win32), один из пакетов (FIBDBMidas2009.dpk) все равно наотрез отказался компилироваться. Но зато другие компоненты и мастеры установились и наконец-то заработали.


Интересный момент: готовилась к выходу именно новая версия компонентов FIBPlus с индексом 7.0, но что-то изменило планы разработчиков. :) В пользу этой версии говорит инсталлятор и файл readme.txt с описанием нововведений:

7.1076
1. Уникодные поля теперь могут маппироваться не на TFIBWideStringField а на
TFIBStringField
2 Добавлено свойство TFIBXSQLVAR.AsAnsiString: AnsiString ;

7.1019
1. В скриптере ошибка при обработке содержимого блоб-полей
2. Ошибка при работе строковых полей не являющихся FIBStringField
3. Подключен быстрый Locate
4. Восстановлена работоспособность IB_Services
5. Восстановлена работоспособность SQLEditor
6. Добавлен обработчик pFIBDataSet.OnLockSQLText. Позволяет заменить генерацию лок-сиквела своей.

и версия в Object Inspector :)


Ну как же так! Проверять программы надо перед релизом! ;-)

пятница, 23 января 2009 г.

Вышло обновление FIBPlus для Delphi/C++ Builder 2009

Без преувеличения можно сказать, что событие, которого ждали многие Delphi-программисты (и я в том числе) наконец-то свершилось! Не прошло и пол года (или прошло? :)) как вышла обновленная версия библиотеки компонентов для доступа к Firebird и Interbase – FIBPlus. Номер версии компонентов остался прежним – 6.9.5 поскольку единственное нововведение – это поддержка Delphi 2009, и эта версия не может быть установлена на более ранние версии Delphi. По сути – это те же самые компоненты только для Delphi 2009.

Теперь многие проекты, основанные на этой библиотеке, могут быть переведены на Delphi 2009, что не может не радовать. А то я уже стал задумываться об использовании стандартных IBX и хорошо, что до этого не дошло. :)

Единственное, что омрачает это приятное известие – это то, что разработчики тянули-тянули с выходом библиотеки, и у многих уже закончилась годовая подписка на обновления. У меня она закончилась буквально меньше месяца назад, что вдвойне обидно.

А еще иногда проскакивает мысль, что задержка с выходом компонентов делалась намеренно, но оставим это на совести разработчиков, а догадки – при себе.

вторник, 20 января 2009 г.

Delphi Prism - первое знакомство

Пару дней назад кое-как руки дошли и до нового продукта - Delphi Prism. (Что-то отставать я стал от технологий :)). Буду наверстывать.

Первое что бросается в глаза - разработчики обленились не стали возиться с собственной IDE и воспользовались бесплатным готовым решением компании Microsoft - оболочкой Microsoft Visual Studio.

Собственно, как и обещали разработчики - Delphi Prism совершает скачок из феодализма в коммунизм из .NET 1.1 в .NET 3.5. И первым подключенным по умолчанию модулем является System.Linq. На эту возможность я и решил сегодня посмотреть в первую очередь.

Для первого теста я выбрал LINQ to XML - решил посмотреть как будет выглядеть работа с XML файлами здесь. Файл и задачу выбрал такую же что и в моем предыдущем посте про работу с XML в Delphi. И по аналогии с C# быстро набросал код программы.

Первое, что бросилось в глаза - синтаксис LINQ немного отличается, так например меня ввело в ступор сообщение об ошибке на операторе orderby, оказывается тут он пишется как order by. Так же по привычке объявил переменные перед блоком begin ... end; что тут являлось ошибкой. :)

В конце-концов у меня получился следующий код:


namespace ConsoleApplication1;

interface

uses
System.Linq,
System.Xml,
System.Xml.Linq;

type
ConsoleApp = class
public
class method Main;
end;

implementation

class method ConsoleApp.Main;
begin
var ComputersFile: System.Xml.Linq.XElement;
ComputersFile := XElement.Load('test.xml');
var Elements := from el in ComputersFile.Descendants()
where el.Name = 'DisplayName'
order by el.Value
select el;

for e in Elements do
Console.WriteLine(e.value);

Console.Read;
end;

end.

Такую же программу я написал и на C# и решил их сравнить. Первое - размеры файлов были разные. Файл написанный с помощью Delphi Prism был больше. Мне это показалось странным - решил выяснить. Оказалось все просто: Delphi по умолчанию даже к консольному приложению, по каким-то своим личным соображениям добавляет иконку по умолчанию, удалив ее - размеры файлов стали одинаковы.

Еще не поленился дизассемблировать обе версии программы. IL-код их оказался совершенно разным, как собственно я и предполагал, сам не знаю что я надеялся там увидеть :) Не стал дальше копать и на этом решил пока остановиться.

В общем, первое впечатление осталось приятное - надо бы найти время по плотнее сесть поразбираться, но катастрофически ни на что не хватает времени.

Кстати в поставку Delphi Prism входят провайдеры для доступа к базам данных Interbase и Blackfish SQL, что позволяет писать управляемый код для работы с этими базами данных. Интересно, а как Delphi Prism интегрируется с Visual Studio? Будут ли доступны эти провайдеры при написании кода на C#? Но это уже материал для следующей заметки...