首页蓝耳朵|小小蓝耳朵广州图书馆外文室英语儿童读物资源介绍网佛教青年之友旧版收集永硕E盘Phonics Short Vowels Game 
用InstallShield 2010做C#写的windows服务的安装包续:服务控制程序的安装和卸载
所属栏目:winform  时间:2011-03-17 18:39  作者:狼子

用InstallShield 2010做C#写的windows服务的安装包:http://www.nnllok.cn/Read.aspx?cid=8&id=526

2003年11月9日 星期日 02:32:06根据CSDN文集整理的《InstallShield内部库函数全集》在永硕E盘的“学习->Installshield”下有下载,是chm文件,带索引和全文检索

InstallShield InstallScript: Uninstallation:http://www.installsite.org/pages/en/isp_uninst.htm
这个页面里有Avoid Maintenance Mode in IS6,去掉重复执行setup.exe文件时显示的那个维护对话框,带修改、维护、卸载的那个

很多服务都带一个服务控制程序,可以对服务做各种设置和操作的,像停止服务、开始服务,或者设置服务运行需要用到的参数,在安装的时候,这个控制程序也要安装进去,卸载的时候,也要同时卸载

先讲安装

安装的时候好简单,就是再多加一个Components,右击Components,使用New Component菜单,再展开的Files里,添加控制程序文件就可以了

控制程序一般都要设置快捷方式,这里讲一下啰,进入Project Assistant标签,进入Application Shortcuts,在这里可以添加快捷方式:
1.Create an uninstallation shortcut,这个是添加一个卸载的快捷方式
2.Shortcuts,这个是添加指向应用程序的快捷方式

这些快捷方式添加完,也可以进入Installation Designer标签后,进入Components里,在对应Component下的Shortcuts里设置快捷方式在开始菜单里的文件夹名称

如果有多个快捷方式是放在不同的Component下的,在System Configuration -> Shortcuts里直接设置,会更方便

嗯,我用Project Assistant标签添加卸载的快捷方式,是因为不用手动设置卸载的各种属性。。。熟悉属性的话,可以直接在Component里设置的

安装好简单,没的好讲的,下面讲卸载

is里,卸载的时候,不会检测服务控制程序是不是正在运行,有时候,一个控制程序正在后台运行,用卸载的时候,可以不退出这个程序,就直接卸载掉的,这里我想不明白,为什么控制程序在运行的时候,在我的电脑里不可以手动删除控制程序文件,就是,卸载就可以把这个文件删除掉呢?文件被删除掉了,文件还在运行。。。我想是不是因为控制程序好小,运行的时候是在高速缓存里呢?就是,就算是在缓存里,文件还是被锁定的啊,我想不明白为什么卸载可以卸掉一个锁定的文件

就是,想不明白也要解决这个问题啊,对不对?

要解决这个问题,就要在卸载前判断控制程序是不是在运行,一个控制程序运行的时候,是在锁定状态的,所以可以借判断文件是不是在锁定状态来判断程序有没有在运行

要知道一个文件是不是锁定状态,就要知道这个文件的完整路径,安装的时候,一般是可以允许用户自定义安装路径的,所以安装程序是不知道控制程序的最终路径的

所以,要在安装时,先把安装路径写入注册表,再在卸载时,从注册表读取这个路径,再判断文件是不是在锁定状态

下面是操作步骤,全部都在Installation Designer下进行:

1.添加注册表项

 进入System Configuration->Registry,如图设置注册表项

 

 这里,我准备把我的安装路径写在这里:HKEY_LOCAL_MACHINE\SOFTWARE\RbTest,其中RbTest是我自己的程序注册项文件项

 这里的操作有不明白的,可以看这里:http://www.nnllok.cn/myBlog/archives/2006/2757.html

2011-03-19 14:57记录:下面的第2步是2011-03-17用的方法,在6.02版,动态写入注册表项时,如果是要写入安装路径,可以用<TARGETDIR>,那天我测试过,不可以,这个字符串被直接写进注册表项了,所以我用了代码写

就是,现在知道,在2010版里,写注册表时,可以用[INSTALLDIR]写安装路径

还有就是,如果只需要写安装路径,可以直接勾选一个设置的,具体看最下面的图

2.动态写入注册项的键值

 ①编写函数
  进入Behavior and Logic,点击InstallScript,在右侧,右击Files,选择New Script File,如图:

  

  右击这个脚本,选择Edit Script,进入脚本编辑器后,添加以下函数:

2011-03-19 13:01记录:这个函数的缺点在没有判断是卸载还是安装,所以在写入注册表项时,是只要函数被执行了,就写,我在设置action的时候,设置成After WriteRegistryValues,所以修改了注册表项后,包括写入和删除,都会执行这个函数,所以会导致卸载程序时,注册表项会在删除后重新建立,导致留下注册表项删除

要判断是安装状态,使用:if !MAINTENANCE then

///////////////////////////////////////////////////////
///NNLL 20100317 1402 安装结束时把安装路径写入注册表///
///////////////////////////////////////////////////////
export prototype SetInstallDir(HWND);
function SetInstallDir(hMSI)
 number nType,nSize;
 string szKey,szNumName,szNumValue,szClass;
begin
 //设置根是HKEY_LOCAL_MACHINE
  RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);
  
  //注册安装路径
  szKey = "SOFTWARE\\RbTest\\";
  szNumName = "installDir";
  szNumValue = TARGETDIR;
  nType = REGDB_STRING;
  szNumValue = TARGETDIR;
 nSize = -1;
 if RegDBSetKeyValueEx(szKey, szNumName, nType, szNumValue, nSize) < 0 then
  MessageBox("设置注册表项失败", WARNING);
 endif;
end;

 ②添加函数调用
  进入Behavior and Logic,点击Custom Actions and Sequences,在右侧右击Custom Actions,选择Custom Action Wizard,如图

 

  进入Wizard后,第1步是Basic Information,这里只要在Name输入你的脚本描述就可以了,我输入的是“SetInstallPath”

  第2步是Action Type,这里的Type,选择:Run InstallScript code

  第3步是Action Parameters,这里的Source选择要调用的函数,我上面在脚本里添加的函数名是SetInstallDir,所以我从下拉菜单里选择的是“SetInstallDir”

  第4-5步选择默认

  第6步是Insert into Sequence,这里是设置你的action要在什么时候调用的,在Install Exec Sequence里选择:After WriteRegistryValues

  后面的全部默认就可以了

  这样子的设置是要在写入了注册表项后执行这个action,执行时调用SetInstallDir函数,这个函数呢,会写入一个注册表键值记录安装路径

3.在卸载时通过判断文件有没有锁定,判断控制程序是不是正在运行

 ①编写函数,在上面的脚本文件里,再加入一个函数:

2011-03-19 15:05记录:以下函数是在2011-03-16写的,在2011-03-17修改完毕,用的方法是读取自定义注册表项的方法,缺点在没有判断当前是在安装还是在卸载,要做这个判断用:if MAINTENANCE then,具体看最后
/////////////////////////////////////////////////////////
///NNLL 20110316 1540 卸载时先检查控制器程序有没有运行///
/////////////////////////////////////////////////////////
export prototype CheckIfExeRuning(HWND);
function CheckIfExeRuning(hMSI)
 string szKey, szName, svValue, szReferenceFile;
 number nType, nSize, nContinue;
begin
 RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);
 szKey = "SOFTWARE\\RbTest\\";
 szName = "installDir";
 nType = REGDB_STRING;
  nSize = -1;
 if RegDBGetKeyValueEx (szKey, szName, nType, svValue, nSize) = 0 then
  //从注册表读取程序安装路径
  szReferenceFile = svValue + "P___Control.exe";
  
  //检查控制程序是不是被锁定的,如果程序正在运行,是锁定状态的
  while (Is( FILE_LOCKED, szReferenceFile ))
   if AskYesNo("服务控制程序P___Control.exe正在运行,要继续卸载请先退出该程序后单击“YES”。\n要退出卸载请单击“NO”", YES) = 0 then
    abort;
   endif;
  endwhile;
 else
  MessageBox("获取程序安装路径失败,请自行确认服务控制程序P___Control.exe是否已退出", WARNING);
 endif;
end;

 ②添加函数调用,操作和上面的相同,就是到第6步Insert into Sequence时,Install Exec Sequence要选择:After StopServices

  因为前面讲安装服务的时候,已经设置过is在卸载时自动暂停服务了,所以这里可以在暂停服务后做判断


通过上面的三个步骤后,卸载时控制程序如果正在运行,就会弹出一个提示,要求用户退出程序后再继续了,安装和卸载到这里全部搞完

 

----------------------------------------------------

以下是2011-03-19记录:

1.写注册表

①自定义注册表路径,在System Configuration -> Registry下如图操作,[INSTALLDIR]可以动态写入安装路径:

②如果只需要写入安装路径,不需要写入别的信息的,可以不用自定义注册表路径的,在Organization -> Components里如下图设置:

勾选上这个后,is会在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\FileName.exe下面写入FileName.exe的安装路径

这个方法是星星告诉我的,我差一点点和星星吵架了。。。因为如果我没有发现我写注册表的方法没有判断安装还是卸载,会导致卸载完也会重复写入注册项,如果我没有为了解决这个问题,从Shortcuts的设置里想到[INSTALLDIR],没有把这个bug告诉星星,没有告诉星星我的解决办法,星星就不会告诉我他用的是这个办法。。。我写这个is的东西,是为了星星写的,他看完,知道更简单的办法,没有告诉我,星星说以为我什么都知道,我怎么可能什么都知道呢?我好多都不懂,我从来不知道注册表里app path里是记录安装路径的,如果我知道这个注册表,我会想到is肯定会有这样子的快捷设置,我会找,就是,我不知道。。。就是,妈妈说这个是我的计算机基础的问题,不是星星的问题,因为星星不知道我连最基本的东西都不懂。。。


所以。。。好久好久以前,小狮说过的话,基础是最重要的

做了这个设置后,System Configuration -> Registry下会自动生成下图注册表项:

 

2.在卸载时检测控制程序是否正在运行,对应上面的设置,函数最终修改如下:

/////////////////////////////////////////////////////////
///NNLL 20110317 1445 卸载时先检查控制器程序有没有运行///
/////////////////////////////////////////////////////////
export prototype CheckIfExeRuning(HWND);
function CheckIfExeRuning(hMSI)
 string szKey, szName, svValue, szReferenceFile;
    number nType, nSize;
begin
 if MAINTENANCE then
  RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);
  szKey = "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\P___Control.exe";
  szName = "";
  nType = REGDB_STRING;
   nSize = -1;
  if RegDBGetKeyValueEx (szKey, szName, nType, svValue, nSize) = 0 then
   //从注册表读取程序安装路径
   szReferenceFile = svValue;
  
   //检查控制程序是不是被锁定的,如果程序正在运行,是锁定状态的
      while (Is( FILE_LOCKED, szReferenceFile ))
    if AskYesNo("服务控制程序P___Control.exe正在运行,要继续卸载请先退出该程序后单击“YES”。\n要退出卸载请单击“NO”", YES) = 0 then
     abort;
    endif;
   endwhile;
  else
   MessageBox("获取程序安装路径失败,请自行确认服务控制程序P___Control.exe是否已退出", WARNING);
  endif;
 endif;
end;

 

小楼宝宝的涂鸦花花(Imitater)的博客起名称骨测字