2016-12-09 36 views
2

Чтобы проверить, когда запущена база данных (SQL Anywhere) и готова к отправке запросов, я выводил окно сообщения базы данных в файл журнала (текста), а затем пытаюсь чтобы прочитать это, используя LoadStringFromFile, и затем я ищу конкретный текст, используя Pos. Проблема в том, что это не удается (я полагаю), поскольку файл используется.Inno Setup LoadStringFromFile не работает, когда файл открыт в другом процессе

Exec(strInstallPath + '\Bin32\dbeng17.exe', '-n ' + strEngineName + ' "' + strInstallPath + '\Database\Olympus.db" -n ' + strDatabaseName + ' -gdall -xtcpip -ti0 -c25p -ot "' + strTempPath + '\dbeng.log"', '', SW_HIDE, 
    ewNoWait, intResultCode); 
    if not LoadStringFromFile(strTempPath + '\dbeng.log', astrDatabaseEngineLog) then 
    begin 
     Log('Loading string from file failed.'); 
    end; 

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

if not FileCopy(strTempPath + '\dbeng.log', strTempPath + '\dbengcopy.log', False) then 
    begin 
     Log('File copy failed.'); 
    end; 

Есть ли способ прочитать из файла, который используется, или другим способом сделать это?

ответ

1

Используйте TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone).

В версии Unicode Inno Setup его использование сложно из-за плохого интерфейса класса.

function BufferToAnsi(const Buffer: string): AnsiString; 
var 
    W: Word; 
    I: Integer; 
begin 
    SetLength(Result, Length(Buffer) * 2); 
    for I := 1 to Length(Buffer) do 
    begin 
    W := Ord(Buffer[I]); 
    Result[(I * 2)] := Chr(W shr 8); { high byte } 
    Result[(I * 2) - 1] := Chr(Byte(W)); { low byte } 
    end; 
end; 

function LoadStringFromLockedFile(const FileName: string; var S: AnsiString): Boolean; 
var 
    Buffer: string; 
    Stream: TFileStream; 
begin 
    Result := True; 
    try 
    Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone); 
    try 
     SetLength(Buffer, Stream.Size div 2); 
     Stream.ReadBuffer(Buffer, Stream.Size); 
     S := BufferToAnsi(Buffer); 
    finally 
     Stream.Free; 
    end; 
    except 
    Result := False; 
    end; 
end; 

код основан на TLama's code публикуемую в Read bytes from file at desired position with Inno Setup.

+1

Я принимаю это как ответ, так как он напрямую отвечает на вопрос, который я задал. Однако в этом случае ответ Graeme Perrow на самом деле гораздо более изящный и простой способ сказать, когда база данных запускается и принимает запросы в SQL Anywhere. –

+1

Я поддержал другой ответ, чтобы компенсировать. Благодарю. –

2

При создании сервера баз данных используйте утилиту dbspawn, предназначенную для этой цели. Вы запускаете dbspawn вместе с командой dbeng/dbsrv, которую хотите запустить, и она запускает сервер для вас. Утилита dbspawn не возвращается до тех пор, пока сервер базы данных не будет запущен, не запущен и не готов принять запросы, поэтому нет необходимости в догадках и нет необходимости читать файл журнала консоли.

Я не знаю, какую версию SQL Anywhere вы используете, но вот documentation for v17. Он должен быть таким же в любой другой версии.

+2

Я принял ответ Мартина Прикрила, поскольку он непосредственно обращается к вопросу кодирования, который я задал, и будет наиболее уместным для других людей, которые ищут ответ на этот вопрос. Тем не менее, я действительно использовал ваш ответ для своего решения. Это именно то, что мне нужно в этом конкретном случае. Мое решение было обходным решением, которое я придумал, не зная об этой удобной маленькой утилите. Благодарю. Upvoted. –