Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Delphi'de Inno Setup | Sorgulu Uninstall İşlemi
#1
Herkese hayırlı geceler,


Uzun zamandır bir şeyler yazmıyordum, Inno hakkında geçenlerde birkaç bilgi öğrendim bunları sizinle paylaşmak isterim. Inno setup bildiğiniz üzere bir uygulama paketleme yazılımıdır. Inno setup yazılımı Delphi ile ilişiği(Embarcadero eklentisi ile) ve script yazımında ki Delphi ile hemen hemen aynı diyebiliriz. Inno setup yazılımının bir diğer güzel özelliği script ile setup yazılımınıza istediğiniz özelliği ekleyebiliyorsunuz. Bu yazımda sizlere örnek teşkil etmesi açısından bir senaryo ve çözümünü sunacağım.

Senaryo: Kullanıcı uygulamayı yükledi sonrasında kaldırma işlemi yapmak istedi fakat uygulamamız çalışıyordu ve kaldırma işleminde sadece kurulumda tanımlı olan dosyalar silindi ve uygulama dosyası kaldı. Birde uygulamamızın her bilgisayar açılışında açıldığını düşünürsek; dosya olmayınca otomatikman her açılışta uygulama bazlı hatalar çıkacaktır.

Çözüm Senaryosu: Uygulama kaldırma işlemi yapılmadan önce; uygulamanın açık olup olmadığı kontrol edilir. Açık ise kapatılması istenir. Kullanıcı kapatmadığı sürece kaldırma işlemi engellenir.

Öncellikle gerekli olan bazı kütüphaneler gerekecek. Bu kütüphanemizin ismi psvince.dll. Bu kütüphane dosyamızı ilk olarak setup dosyamızı "load" edeceğiz. Sonrasında ise gerekli çağırım ve kodlar ile işlemlerimizi tamamlayacağız. 


Exclamation Exclamation psvince.dll load edebilmek için ilk önce files bölümüne eklemelisiniz veya normal kurulum wizard penceresinde seçebilirsiniz ama yine de kod ile nasıl eklenir onu anlatayım kısaca;

Inno Setup bölüm algılama syntax biçimi diyeyim "[]" dizi şeklinde gruplandırarak işlemleri gerçekleştirir. Örneğin kod için [Code], uygulama runtime olayı için [Run] veya dosyalar için ise [Files] tümleçlerin altına yazılır. Bizde psvince.dll için script sayesinde direkt ekleme sağlayacağız.

[Files]
Source: psvince.dll; DestDir: {app}
Source: psvince.dll; flags: dontcopy



Idea  İki adet const değeri belirterek işlemlerimize başlıyoruz: 

const

ProgramName = 'UygulamaAdi';
ProgramExeName = 'UygulamaAdi.exe';

Idea  Sonra belirli prosedürler ile uninstall.exe için geçerli olan mesaj yapımızı hazırlıyoruz:

  ProgramRunningOnUninstallMessage = ProgramName + '  adlı uygulama şu anda çalışıyor. ' + #13 + #13 +
     'Lütfen uygulamayı kapatın ve "Yeniden Dene" butonuna basınız.';

 UninstallationCanceledMessage = 'Kaldırılma işlemi iptal edildi.';

Exclamation Sonraki işlem önemli hem setup.exe hemde uninstall.exe için "load" işlemi gerçekleştireceğiz çünkü setup.exe ile paketlenip uygulama yüklendikten sonra sanırsam uninstall.exe psvinvce.dll
ihtiyaç durumunda uygulama klasöründe referans edinebilsin. Zaten script üzerinden bu durumu kolayca görebiliyoruz.

function IsModuleLoadedI(modulename: String ):  Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall setuponly';

function IsModuleLoadedU(modulename: String ):  Boolean;
external 'IsModuleLoaded@{app}\psvince.dll stdcall uninstallonly' ;
 
Exclamation Tabi IsModuleLoaded fonksiyonu önceden tanımlı. Daha doğrusu bu fonksiyonun Install için mi Uninstall için mi geçerli olduğu bu fonksiyon ile belirtilmesi kolaylaştırlımış ve işlem devamlılığı sağlanmış.

function IsModuleLoaded( modulename: String; isUninstallation: Boolean ): Boolean;
begin
 if isUninstallation then
   Result := IsModuleLoadedU( modulename )
 else
   Result := IsModuleLoadedI( modulename );
end;

Idea Şimdi aşağıdaki fonksiyon ile mesaj buttonları, mesaj türü ayarlanıyor. Tabi bundan önce while ile modül load ediliyor. Fonksiyonun result değerine baktığımızda ise zaten eğer "false" değeri ile birazdan vereceğim  InitializeSetup fonksiyonuyla - yani bir nevi benzetecek olursak Delphi'de create olayı gibi. -  aşağıdaki kodu tetikleyeceğiz.  

function UygulamaKaldirmaIptal( 
             message: String; 
             isUninstallation: Boolean ): Boolean;
var
 ButtonPressed : Integer;
begin
 ButtonPressed := IDRETRY;

 while IsModuleLoaded( ProgramExeName, isUninstallation ) and ( ButtonPressed <> IDCANCEL ) do
 begin
   ButtonPressed := MsgBox( message , mbError, MB_RETRYCANCEL );    
 end;

 Result := Not IsModuleLoaded( ProgramExeName, isUninstallation );
end;

Idea Bundan sonra artık "Initialize" fonksiyonuna gerekli tanımları yapıp işlemlerimizi tamamlamak.

function InitializeUninstall(): Boolean;
begin
 Result := UygulamaKaldirmaIptal( ProgramRunningOnUninstallMessage, True );

 UnloadDLL(ExpandConstant('{app}\psvince.dll'));

 if not Result then
 begin
   MsgBox( UninstallationCanceledMessage, mbInformation, MB_OK );
 end;  
end;

Bu şekilde uygulama kaldırılmadan önce size sorgulama yaptıracaktır.

qvyMXZ.png

Exclamation Bu şekilde uygulama kapatılmadığı sürece bu mesaj "yeniden dene" butonuna bassa bile tekrarlayacaktır. 


Idea Scriptin bütün hali aşağıda yer almaktadır:

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "UygulamaAdi"
#define MyAppVersion "BETA"
#define MyAppPublisher "Halil Han Badem, Developer"
#define MyAppExeName "UygulamaAdi.exe"
#define MyAppCopyright "Developer by Halil Han Badem"

[Setup]
AppId={{A3D45299-0E0E-4E4C-8482-54E88F52B7B0}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName={pf}\{#MyAppName}
DisableProgramGroupPage=yes
LicenseFile=C:\Users\Windows_User\Desktop\Licen.txt
InfoBeforeFile=C:\Users\Windows_User\Desktop\Info.txt
OutputDir=C:\Users\Windows_User\Desktop
OutputBaseFilename=UygulamaAdi_beta_setup
SetupIconFile=C:\Users\Windows_User\Desktop\UygulamaKlasoru\img\icon.ico
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler: Default.isl"
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
Name: "turkish"; MessagesFile: "compiler:Languages\Turkish.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1

[Files]
Source: "C:\Users\Windows_User\Desktop\UygulamaKlasoru\UygulamaAdi.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: psvince.dll; DestDir: {app}
Source: psvince.dll; flags: dontcopy

[Icons]
Name: "{commonprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon



[UninstallDelete]
Type: filesandordirs; Name: "{app}"


[Code]

const

ProgramName = 'UygulamaAdi';
ProgramExeName = 'UygulamaAdi.exe';

 ProgramRunningOnUninstallMessage = ProgramName + '  adlı uygulama şu anda çalışıyor. ' + #13 + #13 +
     'Lütfen uygulamayı kapatın ve "Yeniden Dene" butonuna basınız.';
 UninstallationCanceledMessage = 'Kaldırılma işlemi iptal edildi.';


function IsModuleLoadedI(modulename: String ):  Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall setuponly';

function IsModuleLoadedU(modulename: String ):  Boolean;
external 'IsModuleLoaded@{app}\psvince.dll stdcall uninstallonly' ;


function IsModuleLoaded( modulename: String; isUninstallation: Boolean ): Boolean;
begin
 if isUninstallation then
   Result := IsModuleLoadedU( modulename )
 else
   Result := IsModuleLoadedI( modulename );
end;


function PromptUntilProgramClosedOrInstallationCanceled( 
             message: String; 
             isUninstallation: Boolean ): Boolean;
var
 ButtonPressed : Integer;
begin
 ButtonPressed := IDRETRY;

 while IsModuleLoaded( ProgramExeName, isUninstallation ) and ( ButtonPressed <> IDCANCEL ) do
 begin
   ButtonPressed := MsgBox( message , mbError, MB_RETRYCANCEL );    
 end;

 Result := Not IsModuleLoaded( ProgramExeName, isUninstallation );
end;


function InitializeSetup(): Boolean;
begin
 Result := PromptUntilProgramClosedOrInstallationCanceled( ProgramRunningOnInstallMessage, False );

 if Not Result then
 begin
   MsgBox( InstallationCanceledMessage, mbInformation, MB_OK );
 end;
end;


function InitializeUninstall(): Boolean;
begin
 Result := PromptUntilProgramClosedOrInstallationCanceled( ProgramRunningOnUninstallMessage, True );

 UnloadDLL(ExpandConstant('{app}\psvince.dll'));

 if not Result then
 begin
   MsgBox( UninstallationCanceledMessage, mbInformation, MB_OK );
 end;  
end;



[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: runascurrentuser nowait postinstall skipifsilent


Referans Linkler:
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. 
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.


Umarım bu makale işinize yarar niteliğinde olur. 

Saygılarımla,
İyi çalışmalar.
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Cevapla
#2
Paylaşım için çok teşekkürler.
Amaç, bilginin de/aklın da zekat'ını vermek.
Cevapla
#3
(09-08-2018, Saat: 01:58)hi_selamlar Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Paylaşım için çok teşekkürler.

İlginiz için ben teşekkür ederim Smile
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Cevapla
#4
Merhaba,

Bahsettiğiniz yöntem bana çok doğru bir yöntem gibi gelmedi. Ayrıca, eğer paketlenecek programı da biz yazmışsak bunun daha kolay ve pratik bir yolu var Smile Detaylı bilgiyi aşağıdaki adresten okuyabilirsiniz:

Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.

Özeti: Uygulamanıza bir Mutex tanımlayın. Bunun için program çalıştığında (ben DPR dosyasına, daha main form bile açılmadan önce yazıyorum) aşağıdaki satırı çalıştırın:

CreateMutex(nil, False, 'MyProgramsMutexName');

Inno setup'da da [Setup] kısmına aşağıdaki satırı ekleyin:
AppMutex=MyProgramsMutexName

Bu kadar Smile Artık kurulum programınız, porgramınızın çalıştığını tespit edecek olursa önce onun kapatılmasını isteyecek.

Daha detaylı bilgi için yukarıdaki bağlantıya bakabilirsiniz. O da yetmezse hızlıca bir test uygulaması ve setup programı hazırlayın. Sonuçta en fazla 10 dakika sürecektir Big Grin

İyi çalışmalar
Cevapla
#5
Teşekkürler detaylı anlatımınız için
Cevapla
#6
(09-08-2018, Saat: 10:11)Bahadir.Alkac Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Merhaba,

Bahsettiğiniz yöntem bana çok doğru bir yöntem gibi gelmedi. Ayrıca, eğer paketlenecek programı da biz yazmışsak bunun daha kolay ve pratik bir yolu var Smile Detaylı bilgiyi aşağıdaki adresten okuyabilirsiniz:

Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.

Özeti: Uygulamanıza bir Mutex tanımlayın. Bunun için program çalıştığında (ben DPR dosyasına, daha main form bile açılmadan önce yazıyorum) aşağıdaki satırı çalıştırın:

CreateMutex(nil, False, 'MyProgramsMutexName');

Inno setup'da da [Setup] kısmına aşağıdaki satırı ekleyin:
AppMutex=MyProgramsMutexName

Bu kadar Smile Artık kurulum programınız, porgramınızın çalıştığını tespit edecek olursa önce onun kapatılmasını isteyecek.

Daha detaylı bilgi için yukarıdaki bağlantıya bakabilirsiniz. O da yetmezse hızlıca bir test uygulaması ve setup programı hazırlayın. Sonuçta en fazla 10 dakika sürecektir Big Grin

İyi çalışmalar

Teşekkür ederim hocam, peki bu yol ile örneğin çıkacak olan uyarıyı kendimize göre ayarlayabiliyor muyuz?

(09-08-2018, Saat: 10:15)frmman Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Teşekkürler detaylı anlatımınız için

 Ben teşekkür ederim hocam Smile
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Cevapla
#7
Mesaj metnini değiştirebilirsiniz (dil dosyası ile yapılabilir), ama kurulum programının tepkisini değiştirmek (örneğin programı kapat ya da gerekirse bilgisayarı yeniden başlat vs gibi) mümkün mü ve mümkünse nasıl yapılır bilmiyorum. Daha fazlasına ihtiyaç varsa sizin çözümünüzden ziyade CreateMutex fonksiyonunu inno script içinden çağırmak, hata olduğu zaman da istediğiniz tepkiyi vermek daha doğru olur.
Cevapla
#8
(09-08-2018, Saat: 10:24)Bahadir.Alkac Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Mesaj metnini değiştirebilirsiniz (dil dosyası ile yapılabilir), ama kurulum programının tepkisini değiştirmek (örneğin programı kapat ya da gerekirse bilgisayarı yeniden başlat vs gibi) mümkün mü ve mümkünse nasıl yapılır bilmiyorum. Daha fazlasına ihtiyaç varsa sizin çözümünüzden ziyade CreateMutex fonksiyonunu inno script içinden çağırmak, hata olduğu zaman da istediğiniz tepkiyi vermek daha doğru olur.

Haklısınız hocam, araştırmalarımda mutex konusuna değinmemişlerdi. Hem sizin çözüm hemde benim çözüm kişilere alternatif olur en azından. Verdiğiniz güzel bilgilerden dolayı çok teşekkür ederim.  Blush 

Not: Müdahale konusunu araştırayım, olursa dediğiniz yöntem daha güzel olacaktir Smile
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Cevapla
#9
O zaman mesajı değiştirme konusunda da ben yardımcı olayım:
InnoSetup'ın dil dosyaları kurulum klasörü içinde Languages klasörü altında isl uzantılı dosyalardır. Default olarak ise kurulum klasörü içindeki Default.isl kullanılır.
Bunun içindeki mesajlar, yukarıda örneği de verilen InnoSetup'ın bazı durumlarda bize gösterdiği, yada kurulum penceresi üzerinde gözüken mesajlardır.
Bunlarda değişiklik yapmak isterseniz script içinde [Messages] bölümü oluşturmalısınız.
Yukarıda bahsedilen mesajın ismi UninstallAppRunningError'dır ve isl dosyasında şu şekilde tanımlanmıştır:
UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.

Buna Messages kısmında bir değer verirseniz sizin verdiğiniz değer gözükür.
There's no place like 127.0.0.1
WWW
Cevapla
#10
(09-08-2018, Saat: 10:31)SimaWB Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.O zaman mesajı değiştirme konusunda da ben yardımcı olayım:
InnoSetup'ın dil dosyaları kurulum klasörü içinde Languages klasörü altında isl uzantılı dosyalardır. Default olarak ise kurulum klasörü içindeki Default.isl kullanılır.
Bunun içindeki mesajlar, yukarıda örneği de verilen InnoSetup'ın bazı durumlarda bize gösterdiği, yada kurulum penceresi üzerinde gözüken mesajlardır.
Bunlarda değişiklik yapmak isterseniz script içinde [Messages] bölümü oluşturmalısınız.
Yukarıda bahsedilen mesajın ismi UninstallAppRunningError'dır ve isl dosyasında şu şekilde tanımlanmıştır:
UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.

Buna Messages kısmında bir değer verirseniz sizin verdiğiniz değer gözükür.
Konu bütünlüğü bakimindan güzel oldu hocam. Hem sizlere hemde @Bahadir.Alkac çok teşekkür ederim. Smile
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Delphi'de Indy SMTP ile e-mail gönderme. (GMail, Yandex, Yahoo vb.) csunguray 15 3.234 26-06-2019, Saat: 13:59
Son Yorum: csunguray
  Delphi LZW Algoritması narkotik 2 702 14-06-2019, Saat: 09:19
Son Yorum: frmman
  Delphi ve Protocol Buffers SimaWB 6 813 28-05-2019, Saat: 10:20
Son Yorum: klavye
  Delphi'de BreakPoint (durma noktası) işaretinin yanlış satırda görünmesi csunguray 1 601 17-12-2018, Saat: 00:40
Son Yorum: Bay_Y
  Delphi IDE'sine Eklenti Yapmak - 2 SimaWB 27 4.632 04-12-2018, Saat: 10:25
Son Yorum: ssahinoglu



Konuyu Okuyanlar: 1 Ziyaretçi