Я не уверен, можно ли это сделать. Возможно, вы сможете написать DLL-расширение с двумя функциями:
Один порождает новый поток для загрузки (передавая URL-адрес загрузки и имя временного файла), а другой вы можете регулярно вызывать, чтобы проверить, завершена ли загрузка или произошла ошибка.
Затем вы вызовете первую функцию при запуске установки (убедитесь, что загрузка не начинается при удалении). Вызовите второй метод, когда вам потребуется загруженный файл. В какой-то момент вам нужно будет дождаться завершения загрузки.
Кроме того, если подумать, была бы полезна еще одна функция для отмены потока загрузки, чтобы вы могли отреагировать на отмену установки.
См. этот вопрос, чтобы найти подсказки о том, как вызывать функция в DLL из Pascal Script.
EDIT
Чтобы было более понятно, что я ожидаю от функций, я пытаюсь составить некоторый псевдокод (может быть немного похож на C# ;-) ):
// This is a global variable for the thread
Thread globalDownloadThread = null;
bool threadFinished = false;
bool threadShouldFinish = false;
void StartDownload(string url, string outputFile)
{
globalDownloadThread = new Thread(DownloadThreadMethod);
globalDownloadThread.Start(url, outputFile);
}
void DownloadThreadMethod(string url, string outputFile)
{
bool downloadComplete = false;
bool downloadErrors = false;
while (!threadShouldFinish && !downloadComplete && !downloadErrors)
{
// Download a bit of the file
// Save to the output file
// Store errors
if (error)
downloadErrors = true;
else if (noMoreBytesToDownload)
// When we're done...
downloadComplete = true;
}
threadFinished = true;
}
void CancelThread()
{
threadShouldFinish = true;
globalDownloadThread.Join(); // Wait for thread to finish!
}
bool IsThreadDone()
{
return threadFinished;
}
В Inno Setup сначала вызовите метод StartDownload
. Если установка отменяется после вызова StartDownload
(только тогда есть поток!), вызовите CancelThread
.
В тот момент, когда вам нужно убедиться, что файл был загружен, многократно вызывайте IsThreadDone
, пока он не вернет true.
Конечно, это должно быть приправлено механизмами блокировки, и здесь нет реальных сообщений об ошибках, но я надеюсь, вы поняли, что я имел в виду.
EDIT 2
Я переведу часть моего псевдокода на C++ из того, что вы разместили в комментариях.
HANDLE hThread = 0;
DWORD dwThreadId = 0;
DWORD dwThreadResult = 0;
extern "C" bool _declspec(dllexport) downloadfile(TCHAR *url, TCHAR *dest)
{
DOWNLOADPARAM *obj = new DOWNLOADPARAM();
obj->szURL = url;
obj->szFilePath = dest;
if ((hThread = CreateThread(NULL, 0, inetTransfer, (LPVOID)obj, 0,&dwThreadId)) == NULL)
{
return FALSE;
}
return TRUE;
}
extern "C" bool _declspec(dllexport) isThreadDone()
{
DWORD res = WaitForSingleObject(hThread, 10);
if (res == WAIT_OBJECT_0)
return TRUE;
// Set error flag depending on other values of res
dwThreadResult = res;
return FALSE;
}
extern "C" DWORD _declspec(dllexport) isThreadErrored()
{
return dwThreadResult;
}
Не имеет значения, есть ли цикл while
в вашей функции inetTransfer
или нет — скорее всего, вам даже понадобится какой-нибудь цикл! Функция downloadfile
создает поток и возвращает результат. Другие функции используются для проверки успешности завершения потока.
person
Thorsten Dittmar
schedule
27.07.2011