31 октября 2008 г.

Ответ на задачку №2

Главная проблема в приведённом коде находится в этой строке:
if not CreateProcess(PChar(Converter), 
       PChar('"' + Converter + '" "' + SrcFile + '" "' + Result + '" /storefile'), 
       nil, nil, False, 0, nil, nil, SI, PI) then

Нет, программа при этом запустится, но вот параметры к ней будут испорчены. Почему? Посмотрим на типы переменных: Converter - это AnsiString, т.к. это глобальная переменная внутри DLL. SrcFile - это тоже AnsiString, т.к. это временная переменная внутри процедуры. А вот Result - это WideString, т.к. он передаётся между DLL и главным приложением.

Что будет, когда мы соединяем строки нескольких разных типов? Чтобы избежать потери информации, компилятор вынужден сконвертировать Ansi-строки в Unicode-строки. Это значит, что всё выражение '"' + Converter + '" "' + SrcFile + '" "' + Result + '" /storefile' в целом имеет тип WideString. Приводя такую строку к PChar, получим строку, состоящую всего из одного символа '"'. Разумеется, ParamStr в вызываемой программе в этом случае покажет полную ерунду.

Вообще говоря, компилятор в таких случаях генерирует предупреждения о "подозрительном приведении типов". Но стабильность генератора предупреждений в Delphi иногда оставляет желать лучшего. Иногда хинты/предупреждения могут не показываться, а иногда показываться в ненужных местах. Конкретно в этом месте никакого предупреждения компилятор показать не счёл нужным. Получили загадочную ситуацию на пустом месте: вроде бы программа вызывается с нужными параметрами (мы под отладчиком видим, что параметры в CreateProcess передаются верно), но в самой программе параметров нет.

Как это можно исправить? Например, поставить явное приведение к нужному типу:
if not CreateProcess(PChar(String(Converter)), 
       PChar(String('"' + Converter + '" "' + SrcFile + '" "' + Result + '" /storefile')),
       nil, nil, False, 0, nil, nil, SI, PI) then
а можно собрать сперва строки в переменную типа AnsiString.

Кстати, заметим, что в Delphi 2009 приведённый код работает на ура. Предлагаю самостоятельно подумать почему.

2 комментария :

  1. Анонимный3 июня 2010 г., 16:49

    Потому что в D2009 вызывается CreateProcessW?

    ОтветитьУдалить
  2. Потому что в D2009 String - это WideString

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и (опционально) ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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