Файл загрузки скрипта Inno из Интернета Async

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

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

не могли бы вы помочь мне с этим или сообщить мне какой-либо другой способ добиться этого?


person Iqbal    schedule 27.07.2011    source источник


Ответы (3)


Посмотрите на загрузчик InnoTools. Он был написан именно для этой цели и показывает прогресс загрузки и т.д..

person Deanna    schedule 27.07.2011
comment
этот загрузчик блокирует вызов, мне нужна неблокирующая функция для загрузки из Интернета. - person Iqbal; 28.07.2011
comment
По какой причине? установщик больше ничего не может сделать, кроме как поддерживать отзывчивость пользовательского интерфейса. - person Deanna; 28.07.2011

Я не уверен, можно ли это сделать. Возможно, вы сможете написать 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
comment
Спасибо, что поделились ценной информацией, не могли бы вы разместить алгоритм или фрагмент кода для поддержки вышеупомянутого способа. Я знаю, как написать расширение dll, на самом деле я создал dll и использовал его в настройке inno раньше. так что я знаю, как это сделать. можете ли вы поделиться или написать фрагмент кода на C++, который более четко описывает описанный выше сценарий. Любая помощь по этому вопросу будет принята с благодарностью. - person Iqbal; 27.07.2011
comment
Привет, я не очень разбираюсь в C++, поэтому надеюсь, что какой-то псевдокод подойдет. Я отредактирую свой ответ. - person Thorsten Dittmar; 27.07.2011
comment
Или вы можете пойти на ответ Дины... ;-) - person Thorsten Dittmar; 28.07.2011
comment
Решение Deanna - это блокирующий вызов для загрузки интернет-файла. Но я хочу добиться асинхронной загрузки (неблокирующей). спасибо за псевдокод, но, насколько я вижу, цикл while в потоке снова блокируется в контексте того, что он находится в функции dll, и я вызываю его из настройки inno. позвольте мне объяснить это, как показано ниже. В настройке inno я вызову функцию загрузки из dll расширения С++. и функция dll создает поток для загрузки файла из Интернета, как показано в приведенном выше коде. но цикл while в потоке блокирует вызов. Мне нужен неблокирующий sol. - person Iqbal; 28.07.2011
comment
Нет, вызов не блокируетсяпоток будет выполняться до завершения загрузки. Но когда в функции, которую вы вызовете из InnoSetup, запускается новая параллельная обработка (=> поток), функция вернется сразу после запуска потока — вот что такое многопоточность :-) - person Thorsten Dittmar; 28.07.2011
comment
это фрагмент кода в dll, который я использую, но этот вызов блокирует extern C void _declspec(dllexport) downloadfile(TCHAR *url, TCHAR *dest) { Mutex mutex; DWORDdwThreadId; ПАРАМЕТРЫ ЗАГРУЗКИ *obj = новые ПАРАМЕТРЫ ЗАГРУЗКИ(); obj-›szURL = URL-адрес; obj-›szFilePath = место назначения; if((hThread = CreateThread(NULL, 0, inetTransfer, (LPVOID)obj, 0,&dwThreadId)) != NULL) { } WaitForSingleObject(hThread, INFINITE); } - person Iqbal; 28.07.2011
comment
Поскольку поток не вернулся к вызывающей стороне (настройка inno) из-за цикла while, функция не вернется немедленно, она заблокирует вызов. причина в том, что я вызываю функцию dll, которая, в свою очередь, создает поток для загрузки файла из Интернета. дайте мне знать, я могу отправить вам код для проверки. - person Iqbal; 28.07.2011
comment
Ты неправ. Причина, по которой ваша реализация блокирует вызов WaitForSingleObject. Удалите это, и ваша реализация тоже не будет блокироваться. Моя реализация не блокируется, так как я не жду завершения потока в функции, вызываемой из InnoSetup. Цикл while блокирует поток (что желательно), но поток выполняется независимо. Итак, еще раз: функция StartDownload запускает поток и возвращается. Метод потока выполняется в цикле while, пока все не будет загружено, но в фоновом режиме, не блокируя InnoSetup. - person Thorsten Dittmar; 28.07.2011
comment
Проблема не в том, что мой демо-код не работает, проблема в том, что ваш код не делает то же самое, что я предлагаю в своем демо-коде :-) Я снова немного меняю свой ответ... - person Thorsten Dittmar; 28.07.2011

Похоже, InnoTools Downloader давно не обновлялся и не поддерживает UNICODE...

Есть еще один многообещающий проект: https://bitbucket.org/mitrich_k/inno-download-plugin Он был обновлен в декабре 2016 года и поддерживает версии InnoSetup ANSI и UNICODE. У него есть примеры и документация в порядке, он даже поддерживает несколько языков, таких как испанский, китайский...

person lmiguelmh    schedule 13.12.2017