Показаны сообщения с ярлыком Delphi 2009. Показать все сообщения
Показаны сообщения с ярлыком Delphi 2009. Показать все сообщения

суббота, 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 и хорошо, что до этого не дошло. :)

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

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

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

Осторожно! Помощники класса!

В продолжение темы помощников классов и записей. Я провел небольшое исследование в результате которого выяснилось несколько неприятных моментов применения хелперов. На первый взгляд все прекрасно! Мы можем взять и дополнить любой класс практически любым функционалом. Но не все так радужно.

Самая большая обнаруженная мной проблема состоит в том, что для класса может существовать только ОДИН хелпер. Для иллюстрации этого создадим один небольшой проект, содержащий один класс и два хелпера к нему, и посмотрим, что же у нас получилось.

program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils;

type
TSomeObject = class
function X: integer;
end;

TSomeObjectHelper = class helper for TSomeObject
function y: integer;
end;

TSomeObjectHelper2 = class helper for TSomeObject
function z: integer;
end;

{ TSomeObjectHelper }

function TSomeObjectHelper.y: integer;
begin
result := 1;
end;

{ TSomeObject }

function TSomeObject.X: integer;
begin
result := 0;
end;

{ TSomeObjectHelper2 }

function TSomeObjectHelper2.z: integer;
begin
result := 2;
end;

begin
try
with TSomeObject.Create do
begin
writeln(z);
writeln(y);
end;
readln;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.

Мы получим ошибку компиляции. Потому что компилятор, видит только один хелпер - TSomeClassHelper2. Если закомнтировать его описание и реализацию, то компилятор увидит второй хелпер.

К чему это может привести? Это может привести к трудноуловимым ошибкам, особенно в больших проектах, разрабатываемых не одним разработчиком. Или, как вариант, представим такую ситуацию: в какой нибудь библиотеке - например FIBPlus или DevExpress вдруг используют хелперы, вы снова добавили хелпер уже в своем коде. Компилятор увидел ВАШ хелпер, а исконный хелпер разработчиков - нет, и все - проект уже не скомпилируется. Ситуация еще больше усугубится если у библиотеки закрыты исходные коды.

Поэтому, применять хелперы следует с большой осторожностью, 100 раз подумав.

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

Помощники записей

Сегодня, разбираясь с проектом, который я пытаюсь перевести на Delphi 2009, натолкнулся на одну забавную недокументированную возможность. Наряду с помощниками классов (Class Helpers) введенными в последних версиях Delphi, разработчику доступны и помощники записей!

Стоит сразу отметить, что данная возможность не поддерживается редактором кода и Code Insight. Так в редакторе код подчеркивается красным, а в Code Insight добавленное недоступно.

НО, с точки зрения компилятора, следующий код абсолютно рабочий:

type
TRectHelper = record helper for TRect
function Width: integer;
end;

{ TRectHelper }

function TRectHelper.Width: integer;
begin
Result := Self.Right - Self.Left;
end;

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

var
p: TRect;
begin
p.Top := 0;
p.Left := 0;
p.Bottom := 12;
p.Right := 12;
ShowMessage(inttostr(p.width));
end;

Не знаю, на сколько эта возможность может быть востребована, но она есть.

P.S. К слову сказать, что Class Helpers разработчики не рекомендуют использовать постоянно, а про Record Helpers они и вообще умолчали. :)

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

Неизвестные возможности стандартных компонентов

Одной строкой: Сегодня Bose сделал уникальное открытие. Оказывается, что стандартный TDbGrid умеет рисовать многострочные заголовки с группировкой. Подробнее можно прочитать и посмотреть в его блоге.

Что самое смешное, что данная возможность не является недокументированной, по крайней мере в справке Delphi 2009 можно найти информацию о ней, но кто бы читал эту самую справку. :)

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

Новое в Delphi 2009: работа с ресурсами

Чуть ранее я уже писал о работе с ресурсами в Delphi. Там был описан абсолютно универсальный способ, работающий в любой версии Delphi. Существует еще одна возможность прикрепления ресурсов. Но сегодня я расскажу о том, какие новые возможности по работе с ресурсами нам предлагает Delphi 2009.

Если раньше можно было добавить файл с описаниями ресурсов (*.rc) в проект, и он автоматически скомпилируется и привяжется, то в Delphi 2009 разработчики пошли еще дальше. Теперь с помощью менеджера проектов (Project Manager) в проект можно добавлять сами ресурсы!


Так же с помощью меню Project -> Resources можно вызвать менеджер ресурсов:


Единственное, чем мне не понравились эти нововведения - это не очень удобный менеджер ресурсов. Мне кажется в нем будет сложно работать при большом количестве подключаемых ресурсов. Так же удивило малое количество поддерживаемых типов ресурсов, поддерживаются только Bitmap, RCData и None. На самом деле тип ресурса определяется по формату файла. Так например при добавлении курсора в выпадающем списке становятся доступны варианты - Cursor, RCData, None, при выборе иконки - Icon, RCData и None, а при выборе JPEG изображения - только RCData И None.

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

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

Технологии интеллектуального редактирования (Часть III)

В этой заметке я продолжу обзор наиболее продвинутых возможностей редактирования исходного кода в Delphi. Напомню, что несколько ранее в Части I рассматривались возможности интеллектуального поиска, а в Части II - возможности по быстрому созданию и переименованию конструкций кода.

Ну чтож, начнем. Наиболее мощной и одновременно ресурсоемкой является возможность перемещения (Move). Причем перемещать можно как статические члены класса в другой класс, так и сами классы в другое пространство имен. Для выполнения этой функции следует встать на соответствующий идентификатор и дать команду Refactor -> Move



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


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

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

Ну и еще - рефакторини можно отменять так же как и любые другие действия в редакторе кода - с помощью клавиш Ctrl+Z, что делает их очень мощным и простым инструментом.

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

Технологии интеллектуального редактирования (Часть II)

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

Как обычно начнем с более простых возможностей, первой из которых рассмотрим быструю декларацию переменной и поля. В заметке посвященной LiveTemplates я уже рассказывал как можно быстро объявить переменную. Но есть еще один вариант. Представим себе ситуацию, когда вы уже пытаетесь скомпилировать проект с не объявленной переменной, естественно компилятор выдаст ошибку:

[DCC Error] Unit2.pas(94): E2003 Undeclared identifier: 's'

Так вот, если теперь встать на эту ошибку и из контекстного меню выбрать пункт Declare Variable то в диалоговом окне можно выбрать тип определяемой переменной и при необходимости даже инициализировать ее:

Этим средством удобно пользоваться когда необходимо быстро задействовать новые локальные переменны - например при добавлении циклов.

Аналогично можно поступить если требуется не локальная переменная, а поле класса - Declare Field. Единственное отличие заключается в том, что для поля класса можно дополнительно выбрать область видимости.

Следующая замечательная возможность называется визуальное создание метода (Extract Method). Она позволяет выделить в редакторе кода произвольную часть кода, и организовать ее в виде метода. На рисунке я выделил код, отвечающий за удаление временных файлов в отдельный метод:

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

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

Ну и в завершение еще одна из часто используемых и полезных функций рефакторинга - глобальное переименование идентификатора (Rename). Сколько хлопот раньше приносило переименование какого-либо визуального контрола (скажем TLabel) если он использовался коде. Все вхождения можно было отловить только с помощью компилятора и спотыкания на каждом вхождении. Но теперь с этим покончено. Необходимо всего лишь встать на необходимый идентификатор и дать команду Refactor -> Rename. Данная операция применима к названиям переменных, методов, полей, классов, структуур, интерфейсов и параметров.

Перед переименованием можно просмотреть все идентификаторы которые будут изменены.

В следующей части речь пойдет перемещениях частей кода. Не переключайтесь. :)

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

Технологии интеллектуального редактирования (Часть I)

Продолжаю публиковать серию заметок начатую мной в заметке "Отличия новых версий Delphi от Delphi 7". Сегодня речь пойдет о технологиях интеллектуального редактирования (в англоязычной терминологии Refactoring). Взамен такого длинного русскоязычного названия я буду применять более короткое – "рефакторинг".

Итак, рефакторинг является одним из наиболее значимых нововведений последних версий Delphi. Ключевой особенностью рефакторинга является то, что перед применением изменений их можно просмотреть, а при необходимости легко отменить.

Начнем, пожалуй, с самых простых сценариев применения рефакторинга с поиска. Рассмотрим первую возможность - "Поиск модуля". Данная возможность позволяет найти необходимый модуль и добавить его к списку подключенных модулей в разделе Interface или Implementation. Кстати сказать, все команды рефакторинга вызываются либо из главного меню среды – Refactorings, либо через контекстное меню редактора кода. Причем можно производить поиск не только по имени модуля, но и по имении функций входяших в него (!!!). На рисунке приведен пример поиска модуля по функции ShellExecute:

При нажатии кнопки OK название модуля ShellAPI добавится в раздел подключенных модулей раздела Implementation.

Еще одна прекрасная возможность поиска - поиск ссылок (FindReference), позволяющаяя найти все упоминания о каком либо идентификаторе во всех связанных файлах проекта.

При двойном щелчке на элементах дерева в редакторе кода будет подсвечиваться соответствующая строчка кода.

Для поиска локальных идентификаторов можно воспользоваться вариантом этой функции - Find Local Reference. Результат ее действия аналогичен.

Рассмотрим еще одну возможность поиска. Новая возможность называется "Поиск класса" (FindClass), позволяющая находить определения классов по их именам.

Нажав кнопку OK мы перейдем к описанию класса.

На сегодня, пожалуй, все, продолжение в следующих заметках.

четверг, 8 января 2009 г.

Перевод проекта на Delphi 2009 – первые грабли

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

Первым делом компилятор споткнулся о «мертвую» (нигде не использующуюся) процедуру RunDosAndWait которая запускала консольное приложение фоном и ждала его выполнения. Честно говоря, я намеренно не стал убирать эту процедуру и берег ее для такого случая, как она мне сегодня пригодится – речь пойдет немного позже.

Итак, не работает функция CreateProcess(nil, PChar(CommandLine), nil, nil, true, 0, nil, nil, StartupInfo, ProcessInfo). Попробовал поискать в инете, толком решения проблемы не нашел. На одном из форумов тоже сталкивались с этой проблемой, но решения предложено не было.

Пробуем просто создать процесс:

Получаем следующую картинку:



Поскольку новая Delphi 2009 это один большой Юникод, то думаю следует поискать причину в этом. Попробуем разобраться почему код отлично работавший в предыдущих версиях резко перестал работать. В предыдущих версиях (не Юникод) при вызове функции CreateProcess фактически вызывалась ANSI-версия этой функции – CreateProcessA, в новой Юникод-версии фактически вызывается CreateProcessW и по всей видимости в этом то и кроется основная проблема. А так как CreateProcess это самая что ни на есть WinAPI функция, попробуем поискать ответы на наши вопросы в MSDN.

Вот собственно, что и следовало доказать. Функции CreateProcessA и CreaterocessW ведут себя по-разному:

The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.

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


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


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

function RunDosAndWait(const CommandLine: string; OutSrings: TStrings): boolean;

написать

function RunDosAndWait(var CommandLine: string; OutSrings: TStrings): boolean;.

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

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

Новый год – новые технологии

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

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

Так как я в прошедшем году так или иначе был связан с программированием, а именно с программированием в среде Delphi, то хочу заострить внимание на ней. Что же случилось за прошедший год с Delphi? А произошло два важных события: 1) в очередной раз перепродались – на этот раз компании Embarcadero 2) выпустили новую версию среды.

Выпущенная версия Delphi имеет номер 12. Существует поверие, которого я тоже придерживаюсь, что наиболее стабильными и удачными являются нечетные версии Delphi. Я работаю с Delphi начиная с 3-й версии, и в основном пользовался именно нечетными версиями. Взять, например такой шедевр, как Delphi 7 не потерявшей актуальности и по сей день. Но как из любого правила есть исключение и таким исключением явилась Delphi версии 9, более известная как Delphi 2005 – полностью провальная и глючная версия. И на сегодняшний момент я считаю наиболее стабильной 11-ю версию среды – Delphi 2007.


Это то, что касалось второго пункта. Теперь первый. Глубоко сомневаюсь, что все эти перестроения пошли продукту на пользу. Есть хорошая поговорка – «Новая метла по новому метет», ну и намела она, на отсутствие обратной совместимости с большим количеством сторонних компонентов и на отсутствие исходных кодов, которые раньше стабильно поставлялись с каждой версией Delphi.

Ладно, оставим в покое саму среду – на самом деле она не такая уж и плохая, и я не сколько не жалею, что посвятил ей очень много времени. Основная проблема мне видится в самой поддержке своих разработчиков от производителя. Вот, к примеру, захотелось мне создать мега стартап, неважно какой. Что мне для этого необходимо? Инструмент. Я неплохо знаю Delphi и хочу использовать его. Версии Turbo Explorer мне явно не достаточно, да и устарела она уже, следовательно, мне придется выкладывать деньги за полную версию ПО (к слову - Delphi 2009 for Win32 Professional Box - 30300 руб). А если разработчик не один – то получается довольно приличная сумма для стартапа.

В то же время, ближайший оппонент – компания Microsoft предлагает довольно интересную программу – BizSpark. Подробнее писать о ней не буду (или пока не буду, кому интересно – можно пойти по ссылке или почитать тут, кстати впервые о ней я услышал на днях разработчика, которые проходили в Хабаровске). Скажу суть – практически все технологии компании доступны для стартапов, на определенных условиях, но все же доступны. А где альтернатива от Embarcadero?

Вот отсюда и получается, что мне как разработчику на данный момент выгоднее пользоваться технологиями Microsoft для создания новых проектов. Отсюда и получаются новые приоритеты на 2009 год, которые уже давно подогреваются мыслями о смене языка и переходом на платформу .NET.

воскресенье, 28 декабря 2008 г.

И снова Delphi 2009

Ура! Наконец то мне удалось запустить Delphi 2009 и избавиться от проблем о которых я писал ранее. Решил проблему кардинально - поставил Microsoft Virtual PC (кстати, был очень удивлен - не знал что она теперь полностью бесплатна) - поднял на ней Windows XP и на чистую систему Delphi 2009 установилась без проблем. А вот в чем была истинная причина тех непонятных сбоев мне выяснить так и не удалось, но и ладно, и в виртуальной машине можно работать, только вот колесо прокрутки что то глючит иногда :)

Но на этом проблемы с ней не закончились. Мой проект, над которым я работаю последние несколько лет - отказался компилироваться. Те ошибки которые касались моего кода удалось довольно быстро локализовать и исправить (они касались несовместимости типов), а вот основная проблема случилась с компонентами FIBPlus. На настоящий момент на сайте разработчиков нет версии компонентов под эту версию Delphi, что очень жаль - непростительно тормозят разработчики! На полумертвом форуме на официальном сайте как то обнаружил запись, что они должны были выйти еще в ноябре ... Что ж, видимо это дух времени - обещать релиз и не выполнять обещания ...

четверг, 27 ноября 2008 г.

Delphi 2009 спустя 3 месяца

Прошло уже почти 3 месяца с момента выхода Delphi 2009, а мне так и не довелось еще попробовать в ней поработать.

Неудачной оказалась попытка установки среды на компьютер с Windows Vista - при загрузке выскакивает сообщение об исключении в модуле coreide120.bpl. Небыло времени разбираться с причинами этой ошибки и я забросил это гиблое дело и снес ее, отметив для себя, что среда скорее всего конфликтует с ранее установленными версиями.

И вот появилось немного свободного времени и я решил разобраться в причинах ошибки. Сразу же не стал пробовать ставить ее на "живую" систему. Поставил на Windows XP - тот же результат, что и был ранее - ошибка в coreide120.bpl.

Далее среда продолжала загружаться и выдала самое мое любимое исключение, которое только можно получить в Delphi :)

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

На следующий день, как я и ожидал, Delphi 2009 совершенно спокойно поставилась на свежую систему, что еще больше меня убедило в мысли конфликта с ранее установленными версиями. Все снес и решил дальше разбираться с причинами проблемы. Сделал образ рабочей системы и приступил к "издевательствам" . Для начала снес все версии Delphi (их оказался целый зопарк - начиная от Turbo Delphi Explorer for Win32 заканчивая BDS 2006 и 2007 - как тут не заглючишь:))) и почистил реестр - не помогло, система упорно продолжает выдавать исключение и не загружаться. Видимо причина всетаки не в конфликтах ... Мне уже становится интересно :) Завтра продолжу свои исследования, поскольку сегодня опять уже 3 часа ночи.

суббота, 13 сентября 2008 г.

Tiburon

Наконец-то дождались! Вышла новая версия Delphi - Delphi 2009 и доступна для скачивания как в виде вэб-инсталлятора, так и в виде ISO-образа. К сожалению у меня нет возможности сейчас скачать и попробовать новую версию, а пре-релиз который у меня был - очень жестко глючил: показывал ошибку в пакете coreide120.bpl и отказывался загружаться в принципе :( Что я только не пробовал ...

Надеюсь получится скачать в течении нескольких дней и "пощупать" своими руками ... Кстати ISO-образ "весит" почти 2 ГБ. Можно впринципе заказать по файловой почте, но кто знает когда он придет. Что-то почта в последнее время стала совсем отвратительно работать. Короче говоря пока не знаю, постараюсь на днях как-нибудь решить этот вопрос.