Задать вопрос
@DeeUs

Как реализовать использование одной dll библиотеки двумя программами одновременно?

Здравствуйте!
Пишу программку для обновления другой программы.
Как это всё работает:
1) В основной программе присутствует кнопка "Проверить обновление", при нажатии на которую выполняется запрос к серверу(сайт), где лежит текстовый файл (в нем написана актуальная версия) и архив с обновлением.(файл - это временное решение для теста).
2) Программа сравнивает текущую версию (константа в коде или запись в реестре) с ответом сервера и если версии отличаются - запускает другую программу - обновлятор. (!)
3) Обновлятор скачивает архив с сервера
4) Если архив скачался успешно - завершаем основную программу и распаковываем архив
5) Если архив распаковался успешно - запускаем основную программу и удаляем архив, после чего обновлятор закрывается(!)

Программы работают с сервером по https, поэтому с основным exe'шником и exe'шником обновлятора лежат libeay32.dll и ssleay32.dll (все в одной папке)
Так вот одна программа не работает пока запущена другая - и мне кажется из-за того, что в первой уже задействованы эти библиотеки.
По отдельности вроде все работает, но возникает затык на моментах, когда одна программа должна запустить другую.

В голову пришла мысль положить обновлятор с копиями этих библиотек в отдельной папке update, но мне кажется это не решение не совсем правильным.

Что я делаю не так и как надо делать правильно?
Спасибо.

UPD: Приложу код
На форме ничего нет кроме единственного прогресс-бара для отображения хода загрузки (из не визуальных компонентов: IdSSLIOHandlerSocketOpenSSL1, IdHTTP1, IdAntiFreeze1)
код обновлятора

//Сама программа (Project > View Source)
uses
  Vcl.Forms,
  Vcl.Dialogs,
  Windows,
  Registry,
  System.Classes,
  System.SysUtils,
  Unit1 in 'Unit1.pas' {Form1},
  IdMultipartFormData,
  IdBaseComponent,
  IdComponent,
  IdTCPConnection,
  IdTCPClient,
  IdHTTP,
  IdHashMessageDigest,
  IdSSLOpenSSL,
  IdSSL,
  IdIOHandler,
  IdIOHandlerSocket,
  IdIOHandlerStack;

{$R *.res}
Var HM :THandle;

function Check: boolean;
begin
  HM:=OpenMutex(MUTEX_ALL_ACCESS, false, 'Proj');
  Result:=(HM<>0);
  if HM=0 then HM:=CreateMutex(nil, false, 'Proj');
end;

function checkUpdate: boolean;
var
  Stream: TIdMultipartFormDataStream;
  HTTPClient: TidHTTP;
  response: WideString;
  cur_ver: string;
  Reg: TRegistry;
begin
  Reg:=TRegistry.Create;
  Reg.RootKey := HKEY_CURRENT_USER;
  Reg.OpenKey('\SOFTWARE\'+app_name_tech, true);
  result:=false;
  if reg.ValueExists('AppVer') then cur_ver := Reg.ReadString('AppVer');

  HTTPClient := TidHTTP.Create;
  try
    Stream := TIdMultipartFormDataStream.Create;
    Stream.AddFormField('query_type', 'update');
    Stream.AddFormField('v', cur_ver);
    response:= HTTPClient.Post(app_serv+'/updater.php  ', Stream); // Отправим запрос
    result:=StrToBool(response);
    HTTPClient.Disconnect;
    //FreeAndNil(response);
  finally
    Stream.Free;
    HTTPClient.Free;
  end;

end;

begin
  If Check then //проверка не запущена ли уже программа
    exit;
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  if CheckUpdate() then
  begin
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end
  else
  begin
    ShowMessage('Обновление не требуется');
  end;
end.

// далее Unit1

function UnZipFile(sourceFile, destPath: String): Boolean;
var
 ZipFile: TZipFile;
begin
  ZipFile := TZipFile.Create;
  try
    if ZipFile.IsValid(sourceFile) then begin
       ZipFile.ExtractZipFile(sourceFile, destPath);
       ZipFile.Close;
       result:= true;
    end;
  finally
    ZipFile.Free;
  end;
end;

procedure save_in_dir(dir, url: string; MyHTTP: TIdHTTP);
var
 MyStream: TMemoryStream;
 fname: string;
begin
 MyStream := TMemoryStream.Create;
 fname := url;
 // Получаем имя файла из url. Имя файла - текст за последним включением "/"
 while Pos('/', fname) <> 0 do
 begin
  Delete(fname, 1, Pos('/', fname));
 end;
 // Сам процесс сохранения файла
 MyHTTP.Get(url, MyStream);
 MyHTTP.Disconnect;
 MyStream.SaveToFile(dir + '\' + fname);
 MyStream.Free;
end;

procedure TForm1.FormActivate(Sender: TObject); 
// тут странный момент - форма "не успевает" отобразиться (я пробовал и OnCreate и OnShow), то есть за время работы программы появляются только всплывающие окна описанные ниже.
var
 Reg: TRegistry;
 Stream: TMemoryStream;
begin
  root_dir := ExtractFilePath(ParamStr(0));
  save_in_dir(root_dir, app_serv + '/update/update.zip', IdHTTP1);
  // когда скачалось
  if progressbar1.position=progressbar1.max then //(как по другому определить завершение загрузки не знаю)
  begin
    Application.Messagebox('Загрузка обновления прошла успешно.', 'Загрузка обновления..', mb_iconinformation or mb_ok);
    if FileExists(root_dir+'update.zip') then //есть ли файл
    begin
       try
        //вырубаем основную программу 
        KillProcess(root_dir+'main.exe');//KillTask('main.exe');  //этот момент проверить не могу, так как не получается запустить "одновременно 2 программы". При запуске в режиме отладки тут ошибок не возникало)
      except
        on e:Exception do ShowMessage('Не удалось вырубить основную программу');//ShowMessage(E.ClassName+' ошибка с сообщением : '+E.Message);
      end;
      //распаковать архив
      if UnZipFile(root_dir+'update.zip', root_dir) then
      begin
        //удалить архив
        DeleteFile(root_dir+'update.zip');
        //прописать новую версию
        Reg:=TRegistry.Create;
        Reg.RootKey := HKEY_CURRENT_USER;
        Reg.OpenKey('\SOFTWARE\'+app_name_tech, true);
        Reg.WriteString('app_ver', app_ver);
        ShowMessage('Обновление установлено!');
        //запустить основное приложение
        try
          ShellExecute(0, PChar('open'), PChar(root_dir+'main.exe'), nil, nil, SW_SHOWDEFAULT);
        except
          on e:Exception do ShowMessage(E.ClassName+' ошибка с сообщением : '+E.Message);
        end;
        //закрыть обновлятор
        //Application.Destroy;
        halt;
      end
      else
      begin
        ShowMessage('Не удалось обновиться! Не удалось распаковать архив');
      end;
    end
    else//если файла нет
    begin
      ShowMessage('Не удалось обновиться! Архив не найден');
    end;
  end;
end;

procedure TForm1.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin
  ProgressBar1.Position:=AWorkCount;
end;

procedure TForm1.IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Int64);
begin
  ProgressBar1.Max:=AWorkCountMax;
end;

  • Вопрос задан
  • 188 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
HemulGM
@HemulGM Куратор тега Delphi
Delphi Developer, сис. админ
Библиотеки могут и должны использоваться разными программами одновременно, это их назначение. Дело в другом.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы