Werewolf UnLtd. (original) (raw)
Delphi FireDAC Array DML (BULK INSERT) MySQL, PostgreSQL и возможно другие
На заметку: при использовании запроса INSERT INTO с массивом параметров нужно обязательно ставить пробел перед VALUES иначе запрос будет выполняться для каждой записи массива отдельно.
Пример
INSERT INTO TABLE1(FIELD1, FIELD2)[Пробел тут]VALUES(:p1, :p2)
Проблема в разборе запроса и определении места ключевого слова VALUES.
Delphi быстро читаем stdin
Для консольных приложений бывает необходимо быстро считать входные данные.
Сразу к коду:
const rbsize = 65355; var d: longint; rb: array [0 .. 85 * rbsize] of char; procedure ReadInput; var PInput: ^TTextRec; c: byte; begin d := 0; PInput := @Input; PInput^.BufSize := 0; while PInput^.BufEnd = PInput^.BufSize do begin SetTextBuf(Input, rb[d], rbsize); Read(c); Inc(d, PInput^.BufEnd); PInput^.BufPos := PInput^.BufEnd; end; end;
После выполнения процедуры ReadInput массив rb[0..d] будет содержать данные из файловой переменной Input(stdin). Размер массива rb статичен и может быть изменен в зависимости от задачи.
Определяем, что запущенный процесс написан на Delphi
Если программа написана на Delphi и использует модуль Controls, то при её запуске будет создан глобальный атом вида
'Delphi[восьмизначный идентификатор процесса (PID)]'.
Таким образом чтобы проверить написан ли запущенный процесс с использованием Delphi (модуля Controls) достаточно проверить наличие атома с соответствующим идентификатором процесса:
ShowMessage( BoolToStr( GlobalFindAtom( PChar(Format('Delphi%.8X', [StrToInt(Edit1.Text)])) ) <> 0 , True) );
Естественно можно написать программу и без использования Controls. В таком случае можно проверить поле TimeDateStamp PE заголовка программы - для программ написанных на Delphi он равен $2A425E19 (19.06.1992 22:22:17)
Прошел игру bandit
Прошел игру BANDIT от OVERTHEWIRE =)
все уровни простые.
понравились уровни с nc =)
bandit9:UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR bandit10:truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk bandit11:IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR bandit12:5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu bandit13:8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL bandit14:4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e bandit15:BfMYroe26WYalil77FoDi9qh59eK5xNr bandit16:cluFn7wTiGryunymYOu4RcffSxQluehd bandit17:xLYVMN9WE5zQ5vHacb0sZEVqbrp7nBTn bandit18:kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd bandit19:IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x bandit20:GbKksEFF4yrVs6il55v6gwY5aVje5f0j bandit21:gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr bandit22:Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI bandit23:jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n bandit24:UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ
Delphi Региональные настройки и TFormatSettings
Часто региональные настройки систем пользователей отличаются, при том что все они в одном языковом регионе. При этом в Delphi по-умолчанию используются настройки системы при загрузке региональных параметров.
Чтобы принудительно загружать из системы настройки нужного языка необходимо до инициализации модуля SysUtils вызвать SetThreadLocale($0419); (для русской языка)
Для этого можно создать модуль, например так:
unit Locale; interface implementation uses Windows; initialization SetThreadLocale($0419); end.
И включить его в файл проекта первым модулем (Для продвинутых кодеров до первого обращения к SysUtils).
Проверить результат можно так:
Caption := FormatDateTime(LongDateFormat + ' ' + LongTimeFormat, Now);
P.S.: Пока писал эту заметку заметил баг в SysUtils.TFormatSettings.TranslateDateFormat.FixDateSeparator (код от XE2) =)
в этой процедуре происходит подмена разделителя дат на слэш '/'
в моем случае разделитель дат точка '.', длинный формат даты 'd MMMM yyyy ''г.'''
в итоге получаю '19 Январь 2013 г**/**' - забавно
Скорее всего функция должна игнорировать текст в кавычках.
Баг уже зарегистрирован в QС
Delphi Оптимальная локализация приложений
При разработке на Delphi часто приходится писать программы для использования в одном языковом регионе, т.е. для пользователей которым нужен только один язык в программе.
Есть разные методы локализации, в том числе подмена указателей в PResStringRec. Этот способ плох лишним использованием памяти и дополнительными действиями в runtime - фактически нелокализованные строки остаются в модуле и никогда не используются.
Оптимальным же способом локализации является подмена модулей с переводом содержащихся в них строк. Например, можно взять стандартный модуль RTLConsts.pas скопировать его в папку проекта и перевести содержимое. В таком случае перевод будет скомпилирован и прилинкован к модулю.
Подмену указателей можно использовать для временной подмены строк. Например, для отображения диалога с нестандартым текстом кнопок. Для этого надо переделать процедуру HookResourceString в функцию:
function HookResourceString(ResStringRec: PResStringRec; NewStr: PChar): PChar; var OldProtect: DWORD; begin VirtualProtect(ResStringRec, SizeOf(ResStringRec^), PAGE_EXECUTE_READWRITE, @OldProtect); Result := PChar(ResStringRec^.Identifier); ResStringRec^.Identifier := Integer(NewStr); VirtualProtect(ResStringRec, SizeOf(ResStringRec^), OldProtect, @OldProtect); end;
Сам код временной подмены:
const sAccept: PChar = '&Accept'; sDecline: PChar = '&Decline'; var SaveYes: PChar; SaveNo: PChar; begin SaveYes := HookResourceString(@SMsgDlgYes, sAccept); SaveNo := HookResourceString(@SMsgDlgNo, sDecline); MessageDlg('Do you accept terms?', mtConfirmation, mbYesNo, 0); HookResourceString(@SMsgDlgYes, SaveYes); HookResourceString(@SMsgDlgNo, SaveNo); MessageDlg('Do you accept terms?', mtConfirmation, mbYesNo, 0); end;
Delphi HInstance
Глобальная переменная SysInit.HInstance инициализируется для exe модуля в SysInit._InitExe вызовом HInstance := GetModuleHandle(nil)
Фактически значение данной переменной - это указатель на адрес в памяти по которому загружен PE модуль.
Используя этот адрес можно, например, получить дату сборки проекта, получив прямой доступ к PE заголовку файла в памяти:
function GetLinkDate: TDateTime; begin Result := FileDateToDateTime (PInteger( PImageNtHeaders( Cardinal(PImageDosHeader(HInstance)._lfanew) + HInstance)^ .OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] .VirtualAddress + HInstance + 4 )^); end;