杉宫竹苑工作室

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1875|回复: 0

InstallShield 之残留文件删除与快捷方式自定

[复制链接]
发表于 2017-3-1 18:46:32 | 显示全部楼层 |阅读模式

正式会员享受无限制浏览网站功能和高速网盘下载,赶快加入本站吧!

您需要 登录 才可以下载或查看,没有账号?立即注册

x
InstallShield用了好几个月了,其便捷的操作,完善的功能很是让人爱不释手,可是用了几个月也发现了些小问题:偶用的IS12,有时会出现卸载软件后残留开始菜单与桌面图标问题(只是极其个别电脑,但这种现象存在),还有的就是在更改几次安装程序后原安装程序的残留信息,某些情况下会对新生成的安装文件运行产生干扰,因此需要在新安装程序运行时强制删除残留信息(不是卸载,已经卸载过)。现将解决这些小问题的思路整理如下:
1)开始菜单及桌面图标残留
可以用LaunchAppAndWait来运行cmd进行文件夹及文件的删除,也可以用IS自带的DeleteProgramFolder和DeleteFolderIcon进行显示删除,这里记住几个常量以对特殊文件夹路径进行读取
WINSYSDIR或SystemFolder读取%windir%\system32文件夹(如c:\windows\system32)
WINDIR或WindowsFolder读取%windir%文件夹(如c:\windows)
FOLDER_DESKTOP或DesktopFolder读取桌面文件夹
INSTALLDIR或TARGETDIR读取文件安装路径
FOLDER_PROGRAMS或ProgramMenuFolder读取程序菜单文件夹
@PRODUCT_NAME获取安装程序名称
@PRODUCT_GUID获取安装程序的ID
一般来说这几个常量就能够满足我们的操作了,如果还要了解更多,可以在<ISProductFolder>\Script\isrt\Include\SysVars.h和<ISProductFolder> Script\iswi\Include\SysVarsConv.h,记不住?IS的安装文件里面搜.h文件,找一个你知道的关键字,总不会记一个关键字也难吧?
因此DeleteFile ( FOLDER_DESKTOP^@PRODUCT_NAME+".lnk" );和DeleteProgramFolder ( FOLDER_PROGRAMS^@PRODUCT_NAME );这两句话加在OnMaintUIAfter()里就可满足清除残留图标的要求了。
       2)自定义快捷方式
       IS自带有向导来让你指定快捷方式及其图标,但是这样一来必须把你指定的每一个图标作为一个资源强加载到安装程序中,在%windir%\Installer\[ProductCode]文件夹内生成N个EXE或ICO文件,二来也不能根据系统本身的情况作出适当调整,比如你有几个WORD文档,几个TXT文档和几个PDF文档,那么你用指定快捷方式向导的话你就得在上述文件夹内生成N个图标程序,而不管是否它们中几个文件类型是相同的,更别说某些用户系统类对该类文档的解析程序可能不同,它们的文件图标也可能根本跟你指定的不一样。对于这个问题,当然最灵活的方式就是用脚本添加快捷方式了。
完全从脚本添加快捷方式:
       CreateProgramFolder ( @PRODUCT_NAME );
然后AddFolderIcon (szProgramFolder, szItemName, szCommandLine, szWorkingDir,
   szIconPath, nIcon, szShortCutKey, nFlag);
就可以添加快捷方式到相应的位置了,使用时请注意用LongPathToQuote处理有空格的路径。这里有一点麻烦的就是查找已知文件的图标关联,起初我想的是找到相应的解析程序,然后从其应用程序里面提取图标。在IS里面调用一个批处理来获得该EXE路径,以查找PDF相应关联程序为例:
批处理脚本:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. echo "%1"
  4. for /f "tokens=2 delims==" %%i in ('assoc .pdf') do (
  5.        for /f "tokens=2 delims==" %%j in ('ftype %%i') do (
  6.               set "strPath=%%j"
  7.               set strPath=!strPath: "%%1"=!
  8.               echo !strPath!
  9.               echo !strPath!>"%1"
  10.        )
  11. )
复制代码


IS相应脚本:
  1.       szBATFile = SUPPORTDIR^"getPath.bat";
  2.        szTXTFile = FOLDER_TEMP^"PDFRdr.txt";
  3.        LongPathToQuote( szBATFile, TRUE );
  4.        LongPathToQuote( szTXTFile, TRUE );
  5.        LaunchAppAndWait (  szBATFile , szTXTFile , LAAW_OPTION_HIDDEN|LAAW_OPTION_WAIT );
  6.        if ( FindFile ( FOLDER_TEMP , "PDFRdr.txt" , svResult ) = 0 ) then
  7.               OpenFileMode ( FILE_MODE_NORMAL );                  
  8.               OpenFile ( nvFileHandle , FOLDER_TEMP , svResult );
  9.               GetLine ( nvFileHandle , svExePath );
  10.               CloseFile ( nvFileHandle );
  11.        endif;              
  12.        if ( StrCompare ( svExePath , "" ) = 0 ) then
  13.               MessageBox ( "当前未查到有任何PDF阅读软件", SEVERE );
  14.        else
  15.               MessageBox ( svExePath, INFORMATION );
  16.        endif;   
复制代码

将获得的应用程序图径代入AddFolderIcon,作为图标路径。结果发现诸如PDF文档的图标未必就在EXE里面,FoxitReader的图标在EXE文件里,可Adobe的Exe里面只有一个图标,PDF文档图标根本没有,没办法,还只有从注册表一途来查找了:
  1. /*****************************
  2. *取得系统PDF文件关联类型图标
  3. *****************************/
  4. function STRING GetPDFIcon()
  5.     NUMBER nStart, nvType, nvSize;     
  6.     STRING szStart;
  7.     STRING svResult, svValue, svKey;
  8.     STRING svIconPath;
  9.     NUMBER nvIconIndex;
  10. begin
  11.        RegDBSetDefaultRoot ( HKEY_CLASSES_ROOT );
  12.        svKey = ".pdf";
  13.        if ( RegDBKeyExist ( svKey ) = 1 ) then
  14.               RegDBGetKeyValueEx ( svKey , "" , nvType , svValue , nvSize );
  15.               svKey = svValue;
  16.               if ( RegDBKeyExist ( svKey ) = 1 ) then
  17.                   //子键存在,查找DefaultIcon,如果有,读取,如果没有,读取它的Version,再读注册表
  18.                   if ( RegDBKeyExist ( svKey + "\\DefaultIcon" ) = 1 ) then
  19.                             RegDBGetKeyValueEx ( svKey + "\\DefaultIcon" , "" , nvType , svValue, nvSize );
  20.                             return svValue;
  21.                      else
  22.                             //未发现关联类型的DefaultIcon键,则查找其CurVer键,查其版本号
  23.                             if ( RegDBKeyExist ( svKey + "\\CurVer" ) = 1 ) then
  24.                                    RegDBGetKeyValueEx( svKey + "\\CurVer", "" , nvType, svValue, nvSize );
  25.                                    svKey = svValue;
  26.                                    if  ( RegDBKeyExist ( svKey ) = 1 ) then
  27.                                           if ( RegDBKeyExist ( svKey + "\\DefaultIcon" ) = 1 ) then
  28.                                                  RegDBGetKeyValueEx( svKey + "\\DefaultIcon" , "" , nvType, svValue, nvSize );
  29.                                                  return svValue;
  30.                                           else
  31.                                                  return "";
  32.                                           endif; //endif check ICON value
  33.                                    else        
  34.                                           return "";
  35.                                    endif; //endif check CurVer value
  36.                             else
  37.                                    return "";
  38.                             endif; //endif check CurVer Exist
  39.                   endif;  //endif check DefaultIcon Exist
  40.               endif; //end if check .pdf filetype exist
  41.        endif;  //endif check .pdf key exist
  42. end;
复制代码


然后在OnFirstUIAfter()里面调用该函数取得文件关联路径:
  1.       //查找PDF文件关联,并取得关联类型图标
  2.        svDefaultIcon = GetPDFIcon();
  3.        if ( StrCompare ( svDefaultIcon , "" ) != 0 ) then
  4.               nStart = StrFind ( svDefaultIcon , "," );
  5.               if ( nStart > 0 ) then
  6.                      StrSub ( svPDFIconPath , svDefaultIcon , 0 , nStart );
  7.                      StrSub ( svPDFIconIndex , svDefaultIcon , nStart+1 , 10 );
  8.                      //MessageBox ( "图标路径为:" + svPDFIconPath + "   索引号为:" + svPDFIconIndex , INFORMATION );
  9.               endif;
  10.               StrToNum ( nvPDFIconIndex , svPDFIconIndex );
  11.        else                                
  12.               svPDFIconPath = WINSYSDIR^"shell32.dll";
  13.               nvPDFIconIndex = 0;
  14.        endif;
  15.        svResult = "";                    
  16.        nvResult = FindAllFiles ( INSTALLDIR , "*.pdf" , svResult , RESET );
  17.        while ( !nvResult )      
  18.               LongPathToQuote ( svResult , TRUE );
  19.               ParsePath ( svPDFFileName , svResult , FILENAME_ONLY );                    
  20.               AddFolderIcon ( FOLDER_PROGRAMS^@PRODUCT_NAME ,
  21.                      svPDFFileName ,
  22.                      svResult ,
  23.                      "" ,
  24.                      svPDFIconPath , nvPDFIconIndex ,
  25.                      "" ,
  26.                      REPLACE );
  27.               nvResult = FindAllFiles ( INSTALLDIR , "*.pdf" ,svResult , CONTINUE );
  28.        endwhile;
复制代码


最后,添加卸载的快捷方式,就基本上大功告成了。
  1.       //添加卸载快捷方式
  2.        nStart = StrFind ( UNINSTALL_STRING , ".exe" );
  3.        if ( nStart >= 0 ) then
  4.               StrSub ( szUninstPath , UNINSTALL_STRING , 0 , nStart+4 );
  5.               LongPathToQuote ( szUninstPath , FALSE );
  6.               StrSub ( szUninstParam, UNINSTALL_STRING , nStart+4 , 200 );
  7.               LongPathToQuote ( szUninstParam, FALSE );
  8.        endif;
  9.        AddFolderIcon ( FOLDER_PROGRAMS^@PRODUCT_NAME ,
  10.               "卸载" + @PRODUCT_NAME ,
  11.               """ + szUninstPath + """ + szUninstParam ,
  12.               "" ,
  13.               INSTALLDIR^"Uninstall.ico" ,
  14.               0 ,
  15.               "" ,
  16.               REPLACE );
复制代码


       3)残留安装信息的删除
       目前就发现一个IS的安装信息在[ProgramFilesFolder]\InstallShield Installation Information\[ProcuctCode]和[WindowsFolder]\Installer\[ProductCode]里面有相关的文件,于是安装之前先检测此两处文件夹是否存在,清除之,避免残留信息的干扰。
  1. /*****************************
  2. *旧版残留信息清除
  3. *****************************/  
  4. function NUMBER DealOldEdition()   
  5.        STRING szPath;
  6. begin         
  7.        //删除InstallSheild Installation Information信息
  8.        szPath = PROGRAMFILES^"InstallShield Installation Information"^PRODUCT_GUID;
  9.        if ( ExistsDir ( szPath ) = 0 ) then
  10.               if (LaunchAppAndWait( WINSYSDIR^"cmd.exe", "/c rd /s/q ""+szPath+""", LAAW_OPTION_WAIT | LAAW_OPTION_HIDDEN) = 0) then
  11.                      //MessageBox( "删除文件夹"+szPath+"成功", INFORMATION );
  12.               else
  13.                      return 0;
  14.                      //MessageBox( "删除文件夹"+szPath+"失败", INFORMATION );
  15.               endif;
  16.        endif;
  17.        //删除Installer信息
  18.        szPath = WINDIR^"Installer"^PRODUCT_GUID;
  19.        if ( ExistsDir ( szPath ) = 0 ) then
  20.               if (LaunchAppAndWait( WINSYSDIR^"cmd.exe", "/c rd /s/q ""+szPath+""", LAAW_OPTION_WAIT | LAAW_OPTION_HIDDEN) = 0) then
  21.                      //MessageBox( "删除文件夹"+szPath+"成功", INFORMATION );
  22.               else
  23.                      return 0;
  24.                      //MessageBox( "删除文件夹"+szPath+"失败", INFORMATION );
  25.               endif;
  26.        endif;
  27.        return 1;
  28. end;
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SgzyStudio

GMT+8, 2024-5-19 19:54 , Processed in 0.103089 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表