用微软的安装程序,制作软件安装包,现实安装发布webService,以及自动建立数据库
做安装程序有很多种办吧,本人混混一个,也就只能写些自己的心得给大家分享了,呵呵,更主要是的为了自己也不能忘记这个制作过程.
使用的工具:Vs2005
被安装的程序,一个WebService.
具体步骤如下:
1)先建立一个WebService:
建立步骤非常简单:打开vs2005, File-〉new->Project->LanguageC#->Asp.net WebService
点ok后就能建立一个WebService拉。
系统会帮你生成一个类文件,和asxm的文件,asxm是一个该webservice的访问地址,而cs文件则是具体用于生成dll的类程序。
asxm的具体就是这个格式,而且也只有这句话。
<%@ WebService Language="C#" CodeBehind="CompetenceController.asmx.cs" Class="WEBRP_SERVICE.BLL.Controller.CompetenceController" %>
一个webService的后台代码是一个System.Web.Services.WebService的类,其他的如果你要把一个方法设置为web上共享的方法,你只要在其函数上加上[WebMethod]这个属性就ok了,呵呵,这些代码都是可以由vs2005帮你自动生成。
2)建立一个Web的安装程序
建立步骤也很简单:File-〉new->Project->Other project types->set up and deploy->WebSetup
一个web安装程序,故名思意,就是用来安装web程序的,Webservice当然也是web的一种,因为它是部署在iis里面的,适用的也是soap协议,这些都是基于http的。
安装程序有几个特点:
这个图片是一个安装程序的解图:
其实他生成的只是一个文件,这个文件就是:
途中被选中的那个文件,其他的都是被编译后出来的文件,或者是你自己要定义要求安装的文件。
这个文件的格式可以自己去看看,(我也只是粗略的看了下)大致如下:
他里面定义了您所用到的所有的控件, 大家知道安装程序其实本省并不是一个可以执行的程序,它是需要在misexe.exe这个程序里面执行的,可以说它是个脚本程序。
所以就可以理解为什么只有一个文件就能生成安装程序。
在solution Explorer中选中安装程序,这个它的顶上会出现Propertys,File System Editor,Registry Editor,FileType Editor,User Interface Editor,Custom action Editor luanch condition Editor。
每一个editor都有自己的作用:
Propertys:
这是一个设置本工程的对话框
File System Editor:
这个对话框让我们可以选择,我们需要安装多少程序,需要安装哪个程序的输出目录,可以使主输出,Content, document.等等。
我们这里用到的有,鼠标右击左边的Web Application Folder bin目录,->add-> Project Out put.然后选择你需要添加的哪个程序的主输出。
这里webService 其实只要添加一个webservice的输出dll. 添加进取后webservice的dll就会被安装到虚拟目录的bin目录下。
由于webService还需要地址访问的页面,以及他们的Config文件,而其这些文件是需要Web Application Folder目录下的,所以有两种办法把他们加进来,一个是选择添加content file, 另外就是直接添加File把他们引入。其实效果是一样的。本程序中需要引入的文件就是所有的.asxm文件,和web.config文件(Web Service 的dll需要用到)。
到这里,其实如果您去编译,这个WebService 就可以部署了。
但是我们如果这个WebService 需要用到数据库,而且这个数据库也必须在这个时候一起部署到系统中呢?
那么我们就还必须要做自定义的操作。让自己定义的操作去执行脚本。这样就可以去建立一个完整的安装包了。
要部署数据库需要用到下面的几个功能:
1.Registry Editor这里可以使用,这依靠你的程序,如果您的程序需要写入注册表,那么就可以在这里写入一些代码。本例不用
2.FileType Editor本人不是很了解
3.User Interface Editor :该功能用于定义用户安装的界面,这里是关键之一:
比如实例中的这界面就是自己定义的一个截面。
自定义界面操作如下:
1)进入User Interface Editor
在Install的位置选择add Dialog
选择您需要的界面,加入即可,然后用move up/down 将它调到Installation Address的上面。这个时候界面加进来了,但是如何要从界面中取得参数是一个问题,本文后面讲到。
由于要使用安装数据库,我们有几个选择:
一,使用vbs来实现数据库脚本的安装,这个也没有什么问题。需要用到下面的一个功能.
4 Custom action Editor, 这里可以做用户自己定义的操作,切换到这个界面
在左边的地方,您可以选择在适当的阶段作适当的操作,选择AddCoustom Action
这个Action可以是exe, Vbs, dll等可以执行的程序或者脚本。 你可以使用一个简单的vbs来测以下。
比如打开写字板写入 Msgbox "Hello World!" 然后存成.VBS文件,在此处将他引入近来,那么就可以安装的时候看到一个对话框显示Hello World!能够执行VBS就能搞定所有的问题啦,因为VBS中可以调用Windows几乎所有的功能(只要给足权限)
您也可以使用exe或者dll本例子是用的是一个dll.
话说到这里,我们就要建立一个自定义的dll了,在建立这个之前先把luanch condition Editor说一下:
5. luanch condition Editor,这是一个用来控制安装流程的一个功能,和安装条件的机制。
图中可以看到,所有的被加入的资源,和用户自定义的Action都会有一个Condition的属性,只有在该属性值为true的时候,该资源才能被使用。本例不是用,但是你可以假设写上一些不能为true的表达式.
现在到了本例的自定义Action的DLL了
3)建立一个自定义安装程序, C#(别的语言也可以)的类库程序。
File-〉new->Project->LanguageC#->ClassLibrary
去掉它默认生成的类文件(不去掉也没有关系,呵呵)
然后新建一个Installer的类。
悬在Add->class就可以看到这个界面。
之后会建立一个内容如下的类:这个时候您需要重写一些安装类的方法:
才能在某个阶段作某个事情:
做法如下加入如下的代码,之后代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
namespace WebSetUpCompenent
{
[RunInstaller(true)]
public partial class Installer1 : Installer
{
public Installer1()
{
InitializeComponent();
}
protected override void OnAfterInstall(IDictionary savedState)
{
base.OnAfterInstall(savedState);
}
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
}
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);
}
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
}
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
}
}
如果需要重写方法,就可以实现自己的程序了。
把这个工程的输出也加到前面的安装程序中去,且需要在Action中定义这个dll为一个用户自定义的action, 解图如下:
这样在执行的时候就会去执行这个dll的内容了。
现在回到前面的一个问题,那么安装程序怎么传参数给dll呢.
详细处理如下:
选中自定义加入的TextBox A 然后在其属性对话框中设置,哪些Edit是可见的,或者是不可见的。
最后我们设置如图。切换到Action的画面
注意,选择我们的自定义的Dll,他的属性里面有一个CustomActionData项:
/SqlServerPath=[EDITA1] /LogicDir=[TARGETDIR],这里定义的意思是,我们需要传2个参数给DLL(用valuepair的方式)一个名为SqlServerPath,他的值等于一个被定义为EDITA1的属性地值,请参看TextBox A 然后在其属性对话框,Edit1Property的值为EDITA1。这样Localhost/SQLEXPRESS或者用户从画面输入,就能被传入到dll中(DLL使用Context对象来取得这个参数,稍后介绍)。后面的一个参数,是安装程序内部的参数,它表示安装web程序的物理地址,传入用于去读脚本,当然也可以用dll的放射功能来读去处该dll的物理地址。
处理这些后,把需要执行的SQL脚本也加入到安装包中。
这样安装程序就处理完毕拉,我们继续写dll用户自定义action类库中大代码。
有如下几个问题:
在C#中如何执行脚本:
C#中执行脚本的方式很多,可以自己的研究下,这里使用还是用CMD来执行脚本。
加入一些代码。
最后写成的代码如下:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration.Install;
using System.Collections;
using System.IO;
using System.Diagnostics;
namespace WebSetUpCompenent
{
[RunInstaller(true)]
public partial class WebInstaller : Installer
{
private static string logfile=string.Empty;
public WebInstaller()
{
InitializeComponent();
}
protected override void OnAfterInstall(IDictionary savedState)
{
base.OnAfterInstall(savedState);
}
public override void Install(IDictionary stateSaver)
{
String log = string.Empty;
string cmdstring = "sqlcmd -S" + Context.Parameters["SqlServerPath"] + " -i"+ Context.Parameters["LogicDir"]+ "//CreateDataBase.sql" + " -E";
logfile = Context.Parameters["LogicDir"] + "//InstallLog.txt";
AppendLog("Cmd String:" + cmdstring);
log = RunCmd(cmdstring);
AppendLog(log);
base.Install(stateSaver);
}
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);
}
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
}
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
private string RunCmd(string command)
{
Process p = new Process();
//Process類有一個StartInfo屬性,這個是ProcessStartInfo類,包括了一些屬性和方法,下面我們用到了他的幾個屬性:
p.StartInfo.FileName = "cmd.exe"; //設定程序名
p.StartInfo.Arguments = "/c " + command; //設定程式執行參數
p.StartInfo.UseShellExecute = false; //關閉Shell的使用
p.StartInfo.RedirectStandardInput = true; //重定向標準輸入
p.StartInfo.RedirectStandardOutput = true; //重定向標準輸出
p.StartInfo.RedirectStandardError = true; //重定向錯誤輸出
p.StartInfo.CreateNoWindow = true; //設置不顯示窗口
p.Start(); //啟動
//p.StandardInput.WriteLine(command); //也可以用這種方式輸入要執行的命令
//p.StandardInput.WriteLine("exit"); //不過要記得加上Exit要不然下一行程式執行的時候會當機
return p.StandardOutput.ReadToEnd(); //從輸出流取得命令執行結果
}
private void AppendLog(string text)
{
if (!File.Exists(logfile))
{
using (File.CreateText(logfile)) ;
}
using (StreamWriter sr = File.AppendText(logfile))
{
sr.WriteLine(DateTime.Now.ToLocalTime().ToString() +" : "+ text);
sr.Flush();
}
}
}
}
稍微解释一下:
1)从安装程序取参数的代码为:string cmdstring = "sqlcmd -S" + Context.Parameters["SqlServerPath"] + " -i"+ Context.Parameters["LogicDir"]+ "//CreateDataBase.sql" + " -E";
logfile = Context.Parameters["LogicDir"] + "//InstallLog.txt";
这里用来拼成一个能够执行sqlCmd的指令,(这里是SqlServer 2005写法,2000可能是osql什么的,可以自己去尝试下)
这里还设置了一个log文件,主要是为了记录暗转过程中出现的错误。
2)使用CMD命令的方式为,用Process来创建一个命令行程序,只是不现实出来而已。
p.StartInfo.CreateNoWindow = true; //設置不顯示窗口
3)把cmd的输出取出来:
p.StartInfo.RedirectStandardOutput = true; //重定向標準輸出
当然也可以在命令行中,把结果重定向。
4)取得SQL脚本的地方为:
string cmdstring = "sqlcmd -S" + Context.Parameters["SqlServerPath"] + " -i"+ Context.Parameters["LogicDir"]+ "//CreateDataBase.sql" + " -E";
该指令用集成验证的方法来执行SQL语句,当然你可以写的更复杂,可以实现输入密码,设置主机等等操作。
5)注意,如果程序再安装的过程中出现错误,需要会滚什么的,可以直接调用里面的事件。(调用方式,直到事件和代理的人就ok了)