zoukankan      html  css  js  c++  java
  • Inno_setup制作升级包必须面临的几个问题

    Inno_setup制作升级包必须面临的几个问题

    分类: c/c++/GamingAnyWhere JavaScript linux shell基础知识

            这两天的时间一直在制作应用程序的升级包,期间碰到一些问题这里一并记录下来,相信这是制作升级包必须面临和解决的问题:

    1. 升级包安装程序如何不再产生新的安装、卸载程序

        Inno_setup中AppId是用来标识某个应用程序的唯一标识,因此升级包中的AppId字段应该和原始安装程序的AppId相同。

        CreateUninstallRegKey字段,改值设置为no则安装程序将不会在控制面板的“添加/删除程序”中再创建一个。当这个关键字设置为 no时,UpdateUninstallAppName通常也设置为 no。

        UpdateUninstallAppName如果为 yes, 当添加到一个已存在的卸载记录时,安装程序将以当前的安装程序的 AppName 替换在卸载记录中的 AppName。卸载记录中的 AppName决定了卸载程序显示的标题。如果你的安装程序只是一个升级或附加到一个已存在的程序,并且你不想改变卸载程序的标题,那么你可以设置该值为 no。

    2. 如何检测以前的应用程序正在运行

        判断某个应用程序是否正在运行,这里可以采用两种方式:一种是应用程序的进程是否正在运行;一种是通过窗口名称来检测。采用第一种方式时要引入ISTask.dll文件(它通常可以在Inno_setup安装包里面找到),实例代码如下:

        1) 通过进程检测是否正在运行

             首先确保ISTask.dll文件和脚本文件位于同一目录:

            

            其次确保[Files]段中添加:

           

            最后[Code]段中加入一下函数调用:

           

        2) 通过窗口检测是否正在运行,主要是通过FindWindowByWindowName()函数,下面以检测有道词典是否正在运行为例:

            

        以上两种情况可以依据自己的实际情况来选择,如果你的应用程序窗口固定那么采用第二种检测方式会方便一些;但是如果你无法确定窗口名称或你的窗口名称是会变化的,则采用第一种方式会更好。

    3. 如何修改控制面板里原有程序的版本信息

        制作升级包不得不面对的问题是版本升级,那么像下面所示如何修改控制面板中存在的版本信息是我们不得不面对的问题:

       

        如何修改呢?看看我们的注册表就知道了:

       

        图中标识的就是控制面板中可以看到的所有信息,那么解决方案就是修改注册表中的信息,具体代码如下:

       

       具体涉及的两个操作就是:RegQueryStringValue()查询注册表和RegWriteStringValue()修改注册表,具体使用一看便知。

    4. 如何修改控制面板里原有程序的显示图标

        有了上面的如何修改控制面板里的版本信息,相信你已经猜到了,修改控制面板里应用程序的显示图标也是通过修改注册表来实现的,这里要提到的是:DisplayIcon字段,用来定义控制面板中应用程序图标的显示路径,代码如下:

       

        升级包程序运行之后,控制面板中的信息为:

       

        可以看到应用程序的显示图标和版本信息都已经修改了,再看下注册表里面,添加了DisplayIcon字段,其它信息也已经修改:

       

    5. 如何检测浏览器正在运行

         适用于当前主流浏览器,代码如下:

        

    6. 如何进行文件查找及拷贝

        不管是在安装包制作或升级包制作过程中,通常面临着文件的拷贝,除了[Files]段中的文件拷贝,请看如下的查找及拷贝操作:

       

       FileSearch('rdp.tmp' , ExpandConstant('{app}'))表示查找应用程序安装目录下是否存在rdp.tmp文件,如果存在则返回该文件的绝对路径,如果不存在则返回' '

       FileCopy(ExpandConstant('{tmp} dp.tmp') , ExpandConstant('{app} dp.tmp') , false)是将临时目录下的rdp.tmp文件拷贝到应用程序安装目录下,这里要注意两点:

       1> 第二个参数目标文件,一定要带着最终的文件名,如果只是一个目录的路径,则拷贝操作会出错。

       2> 第三个参数为true代表如果最终文件存在则拷贝操作失败,如果为false则拷贝操作会覆盖原有文件。

    总结:以上就是2天的收获,升级包制作完成。Inno_setup是个比较强大的工具,里面还可以运行cmd命令。

    相关代码:

      1 // 卸载时判断浏览器是否正在运行
      2 function InitializeUninstall(): Boolean;
      3 var
      4     iehWnd, ffhWnd, chrhWnd, b360hWnd, safhWnd, i: Integer;
      5 begin
      6     result:=true;
      7     iehWnd := FindWindowByClassName('IEFrame');
      8     ffhWnd := FindWindowByClassName('MozillaWindowClass');
      9     b360hWnd := FindWindowByClassName('360se6_Frame');
     10     chrhWnd := FindWindowByClassName('Chrome_WidgetWin_1');
     11     safhWnd := FindWindowByClassName('{1C03B488-D53B-4a81-97F8-754559640193}');
     12     i := 0;
     13     
     14     while (iehWnd>0) or (ffhWnd>0) or (b360hWnd>0) or (chrhWnd>0) or (safhWnd>0) do
     15     begin
     16       if i > 0 then
     17       begin
     18          Msgbox('请确保所有浏览器都已关闭!', mbInformation, MB_OK);
     19       end;
     20       
     21       if Msgbox('插件更新程序检测到浏览器正在运行。'  #13#13 '请您先关闭所有浏览器,单击“是”继续更新,否则按“否”退出安装', mbConfirmation, MB_YESNO) = idNO then
     22       begin
     23            Result:=false;
     24            iehWnd :=0;
     25            ffhWnd :=0;
     26            b360hWnd :=0;
     27            chrhWnd :=0;
     28            safhWnd :=0;
     29       end else begin
     30         Result :=true;  //卸载程序继续
     31         iehWnd := FindWindowByClassName('IEFrame');
     32         ffhWnd := FindWindowByClassName('MozillaWindowClass');
     33         b360hWnd := FindWindowByClassName('360se6_Frame');
     34         chrhWnd := FindWindowByClassName('Chrome_WidgetWin_1');
     35         safhWnd := FindWindowByClassName('{1C03B488-D53B-4a81-97F8-754559640193}');
     36       end;
     37       i := i+1;
     38     end;
     39 end;
     40 
     41 
     42 // 检测应用服务是否正在使用  added by houqd 2013/12/17
     43 // 该函数利用FindWindowByWindowName(),只能通过窗口的名字来判断
     44 // 不适合现在的情况,采用另一种方式判断后台进程是否正在进行
     45 function ifRunningDesktop():Boolean;
     46 var
     47    isRunning:Integer;
     48    cycleCount:Integer;
     49 begin
     50     Result:=true;
     51     cycleCount:=0;
     52     isRunning:=FindWindowByWindowName('有道词典');
     53     while isRunning <> 0 do
     54     begin
     55         if cycleCount > 0 then
     56         begin
     57            Msgbox('请确保客户端已关闭!', mbInformation, MB_OK);
     58         end;
     59         if MsgBox('升级程序检测到客户端正在运行。' #13#13 '您必须先关闭客户端然后单击“是”继续安装,或按“否”退出安装!',mbConfirmation, MB_YESNO) = idNO then
     60         begin
     61            Result:=false;
     62            isRunning:=0;
     63         end else begin
     64            Result:=true;
     65            isRunning:=FindWindowByWindowName('VSODesktop');
     66         end;
     67         cycleCount:=cycleCount +1 ;
     68     end;
     69 end;
     70 
     71 // 判断某个进程是否正在运行,利用安装包里面自带的ISTask.dll插件
     72 function RunTask(FileName: string; bFullpath: Boolean): Boolean;
     73 external 'RunTask@files:ISTask.dll stdcall delayload';
     74 
     75 function ifBrowserIsRunning():Boolean;
     76 var
     77    iehWnd, ffhWnd, chrhWnd, b360hWnd, safhWnd, i: Integer;
     78 begin
     79     iehWnd := FindWindowByClassName('IEFrame');
     80     ffhWnd := FindWindowByClassName('MozillaWindowClass');
     81     b360hWnd := FindWindowByClassName('360se6_Frame');
     82     chrhWnd := FindWindowByClassName('Chrome_WidgetWin_1');
     83     safhWnd := FindWindowByClassName('{1C03B488-D53B-4a81-97F8-754559640193}');
     84 
     85     if (iehWnd>0) or (ffhWnd>0) or (b360hWnd>0) or (chrhWnd>0) or (safhWnd>0) then
     86     begin
     87        Result:=true;
     88     end else begin
     89        Result:=false;
     90     end;
     91 end;
     92 
     93 
     94 // 检测vsodesktop进程是否正在运行,即正在打开这vso应用软件
     95 // added by houqd 2013/12/18
     96 function ifVsoIsRunning():Boolean;
     97 var
     98     pstate:Boolean;
     99 begin
    100     Result:= RunTask('VSODesktop.exe', false);
    101 end;
    102 
    103 
    104 // 升级包通过修改注册表,更改控制面板中已安装软件的版本信息
    105 // added by houqd 2013/12/18
    106 function updateVersion():Boolean;
    107 var
    108    ResultStr:String;
    109    nDisplayName:String;
    110    nVersion:String;
    111 begin
    112 
    113    Result:=true;
    114    nDisplayName:='{#PreDisplayName}'+'{#MyAppVersion}';
    115    nVersion:='{#MyAppVersion}';
    116 
    117    // 修改版本信息
    118    if RegQueryStringValue(HKLM,'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1','DisplayName',ResultStr) then
    119    begin
    120       if nDisplayName <> ResultStr then
    121       begin
    122           RegWriteStringValue(HKLM, 'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1', 'DisplayName', nDisplayName);
    123       end;
    124    end;
    125    
    126    if RegQueryStringValue(HKLM,'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1','DisplayVersion',ResultStr) then
    127    begin
    128       if nVersion <> ResultStr then
    129       begin
    130           RegWriteStringValue(HKLM, 'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1', 'DisplayVersion', nVersion)
    131       end;
    132    end;
    133 end;
    134 
    135 // 升级包通过修改注册表,更改控制面板中已安装软件的显示图标
    136 // added by houqd 2013/12/18
    137 function updateDisplayIcon():Boolean;
    138 var
    139   ResultStr:String;
    140   nDisplayIcon:String;
    141   installLocation:String;
    142 begin
    143   Result:=true;
    144   
    145   RegQueryStringValue(HKLM,'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1','InstallLocation',installLocation);
    146   nDisplayIcon:=installLocation+'VSODesktop.exe';
    147   
    148   // 如果DisplayIcon该键值存在则说明它原本就有图标,现在要对比更新
    149   if RegQueryStringValue(HKLM,'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1','DisplayIcon',ResultStr) then
    150   begin
    151      if nDisplayIcon <> ResultStr then
    152      begin
    153         RegWriteStringValue(HKLM, 'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1', 'DisplayIcon', nDisplayIcon)
    154      end;
    155   end else begin
    156         RegWriteStringValue(HKLM, 'SOFTWAREMicrosoftWindowsCurrentVersionUninstall{C77BFCB0-66A4-4D04-82D9-FF74356FA0B1}_is1', 'DisplayIcon', nDisplayIcon)
    157   end;
    158 end;
    159 
    160 rdpFileExsits:=FileSearch('rdp.tmp',ExpandConstant('{app}'));&nbsp;&nbsp;&nbsp; // 如果文件存在则返回绝对路径,如果不存在则返回空
    161 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if rdpFileExsits = '' then
    162 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin
    163 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exec(ExpandConstant('{cmd}'), '/c wmic qfe get hotfixid | find "KB2592687" > '+ExpandConstant('{tmp}
    dp.tmp'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
    164 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileCopy(ExpandConstant('{tmp}
    dp.tmp'),ExpandConstant('{app}
    dp.tmp'),false);
    165 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;
    View Code

             加油,坚持每天的学习,少年!

  • 相关阅读:
    mysql的一些不常用语句
    redis的使用1
    linux理论知识点(用于考试)
    服务器负载均衡数据同步的实现
    解决com.ibatis.sqlmap.client.SqlMapException: There is no statement named in this SqlMap
    cvc-complex-type.2.3: Element 'beans' cannot have character [children]
    Oracle11g服务详细介绍及哪些服务是必须开启的
    Oracle
    oracle 帐号scott被锁定 如何解锁
    记录
  • 原文地址:https://www.cnblogs.com/joean/p/4843122.html
Copyright © 2011-2022 走看看