C# Windows 服务安装并运行服务

来源:互联网 发布:淘宝可以用花呗吗 编辑:程序博客网 时间:2024/06/05 00:36

开发目的:C#开发windows服务,并制作安装包。安装过程中配置系统参数。

功能描述:服务监控一个文件目录和其子目录,如果里面有新增rar的文件,就记录其信息。待到设定的时间,使用FTP上传功能,上传到FTP服务器。

代码示例:

1、文件目录监控类:

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading;namespace FTPUploadComponent{    /// <summary>    /// 监控目录 FileSystemWatcher    /// </summary>    public class DirectoryWatcher : IDisposable    {        private FileSystemWatcher _fsw = null;        private FTPConfigSection _ftpSection = null;        private FTPWatcherItem _ftpWtchItem = null;        private FTPLog _ftpLog = null;        public DirectoryWatcher(FTPConfigSection ftpCfgSection)        {            if (_fsw == null)            {                _ftpSection = ftpCfgSection;                _ftpWtchItem = _ftpSection.WatcherCollection[0];                _ftpLog = new FTPLog(_ftpSection.LogCollection);            }        }        public void SetWatcherDir()        {            _fsw = new FileSystemWatcher(_ftpWtchItem.WatcherDir, _ftpWtchItem.WatcherFileType);            _fsw.IncludeSubdirectories = _ftpWtchItem.WatcherSubDir;            _fsw.EnableRaisingEvents = true;            _fsw.Created += new FileSystemEventHandler(DirectoryWatcher_Created);            while (true)            {                //一直运行,防止线程停止,对要监视的目录失效                Thread.Sleep(1000*60*24);            }        }        protected void DirectoryWatcher_Created(object sender, FileSystemEventArgs e)        {            string fileName = e.Name.Substring(e.Name.LastIndexOf('\\')+1);            try            {                Thread.Sleep(_ftpWtchItem.WatcherWaitIntival);                //ftpUpload.FTPUpLoadFile(e.Name);                //写记录日志                _ftpLog.LogOpeFlag = OpeFlag.Record;                _ftpLog.LogContent = string.Format("{0}|{1}", e.FullPath, fileName);                _ftpLog.WriteFtpLog();            }            catch (Exception ex)            {                //写失败记录                _ftpLog.LogOpeFlag = OpeFlag.Error;                _ftpLog.LogContent = string.Format("FTP upload file failed.Time is {0}.Rerson is {1}. FilePath:<#{2}#>",                                                 DateTime.Now.ToString("yyyy-MM-dd HH:mi:ss"),                                                 ex.Message,                                                 e.FullPath);                _ftpLog.WriteFtpLog();            }        }        public void Dispose()        {            if (!_fsw.Equals(null))            {                _fsw.Dispose();            }        }    }}

代码中只对监控目录的新增文件经行处理。如果有新增文件则由DirectoryWatcher_Created方法处理。

参数FTPConfigSection是自定的FTP配置文件对应的操作类。

2、FTP上传类:

using System;using System.Net;using System.IO;using System.Threading;namespace FTPUploadComponent{    public class AsynchronousFtpUpLoader:IDisposable    {        private FTPUploadItem _ftpUpItem = null;        private string _ftpUri = "";        private FtpWebRequest _request = null;        private ManualResetEvent _waitObject = null;        private FTPLog _ftpLog = null;        public FTPLog FtpLog        {            set { _ftpLog = value; }        }        public AsynchronousFtpUpLoader(FTPUploadItem ftpUpItem,string fileName)        {            _ftpUpItem = ftpUpItem;            _ftpUri = string.Format(@"{0}:{1}/{2}", _ftpUpItem.FTPHost, _ftpUpItem.FTPPort,fileName);            if (_request == null)            {                _request = CreateFtpWebRequest();            }        }        private FtpWebRequest CreateFtpWebRequest()        {            if (_request != null) return _request;            Uri target = new Uri(_ftpUri);            _request = (WebRequest.Create(target)) as FtpWebRequest;            _request.Proxy = null;            _request.UseBinary = true;            _request.KeepAlive = false;            _request.Method = WebRequestMethods.Ftp.UploadFile;            _request.Credentials = new NetworkCredential(_ftpUpItem.FTPUserName, _ftpUpItem.FTPPwd);            return _request;        }        public void BeginGetRequest(string ftpUploadFileName)        {            string fileName = ftpUploadFileName;            FtpState state = new FtpState();            state.Request = _request;            state.FileName = fileName;            _waitObject = state.OperationComplete;            _request.BeginGetRequestStream(                new AsyncCallback(EndGetStreamCallback),                state            );            _waitObject.WaitOne();            if (state.OperationException != null)            {                //失败日志                _ftpLog.LogOpeFlag = OpeFlag.Error;                _ftpLog.LogContent = string.Format("FTP upload file failed.Time is {0}.Rerson is {1}. FilePath:<#{2}#>",                                               DateTime.Now.ToString("yyyy-MM-dd HH:mi:ss"),                                               state.OperationException.Message,                                               ftpUploadFileName);                _ftpLog.WriteFtpLog();            }            else            {                //成功日志                _ftpLog.LogOpeFlag = OpeFlag.Success;                _ftpLog.LogContent = string.Format("FTP upload file Success.Time is {0}.FilePath:<#{1}#>",                                               DateTime.Now.ToString("yyyy-MM-dd HH:mi:ss"),                                               ftpUploadFileName);                _ftpLog.WriteFtpLog();            }        }        private static void EndGetStreamCallback(IAsyncResult ar)        {            FtpState state = (FtpState)ar.AsyncState;            Stream requestStream = null;            // End the asynchronous call to get the request stream.            try            {                requestStream = state.Request.EndGetRequestStream(ar);                // Copy the file contents to the request stream.                const int bufferLength = 2048;                byte[] buffer = new byte[bufferLength];                int count = 0;                int readBytes = 0;                FileStream stream = File.OpenRead(state.FileName);                do                {                    readBytes = stream.Read(buffer, 0, bufferLength);                    requestStream.Write(buffer, 0, readBytes);                    count += readBytes;                }                while (readBytes != 0);                // IMPORTANT: Close the request stream before sending the request.                requestStream.Close();                stream.Close();                stream.Dispose();                // Asynchronously get the response to the upload request.                state.Request.BeginGetResponse(                    new AsyncCallback(EndGetResponseCallback),                    state                );            }            // Return exceptions to the main application thread.            catch (Exception e)            {                state.OperationException = e;                state.OperationComplete.Set();                return;            }        }        private static void EndGetResponseCallback(IAsyncResult ar)        {            FtpState state = (FtpState)ar.AsyncState;            FtpWebResponse response = null;            try            {                response = (FtpWebResponse)state.Request.EndGetResponse(ar);                response.Close();                state.StatusDescription = response.StatusDescription;                // Signal the main application thread that                 // the operation is complete.                state.OperationComplete.Set();            }            // Return exceptions to the main application thread.            catch (Exception e)            {                state.OperationException = e;                state.OperationComplete.Set();            }        }        public void Dispose()        {            if (_request != null)            {                _request.Abort();                _request = null;            }            if (_waitObject != null)            {                _waitObject.Close();                _waitObject.Dispose();            }        }    }}


采用异步上传。参考MSDN中FtpWebRequest类用法。

其中URI指定的时候,格式是:ftp://地址/文件。如果不是这个格式,在异步获取读取文件流是报指定格式不正确错误。

以上监控类和上传类完成,下面就开始做安装包。

制作安装包步骤:

1、在解决方案中新建安装项目FTPUploadServiceSetUp

2、在新建的安装项目FTPUploadServiceSetUp中添加项目输出


项目输出选择为主输出 。项目选择要运行的服务类。

3、为打包的安装程序添加需要的文件

在应用目录中添加程序运行需要的dll、exe和配置文件。上图FTPUploadComponent.dll文件是封装的类库,FTPUploadConfigs.config是FTP上传需要配置的参数设置,InstallUtil.exe是安装服务需要的组件,uninstall.bat是卸载服务需要的批处理文件。

4、添加用户界面

添加后就可以自定义安装过程中的自定义界面。

上图中Textboxes(B),是获取FTP配置数据。Textboxes(C) 是配饰要监控的目录文件和配置。

右键Textboxes(B)属性,如下图,就可以配置配置参数

5、添加自定安装类

新建类库SetUpLib,在类库中添加Installer Class类。

6、重复第二步,把新增的自定义类,在安装项目中添加为主输出。

7、配置自定义类参数

右键安装项目,在视图中添加自定义操作。之后,在安装项,右键添加自定操作,选择刚才项目主输出添加的内容。

右键自定义操作属性,可以看到CustomActionData属性。这个属性就是获取从自定义界面获取到的值。

CustomActionData是用空格隔开的键值对。

具体使用参见http://msdn.microsoft.com/zh-cn/library/2w2fhwzz(v=vs.80).aspx

8、自定安装类获取自定义界面输入的数据

查看,安装类代码,可以看到该类继承了 System.Configuration.Install.Installer类。此类中定义了安装前,安装后要实现的内容,此例中,我们只重写了OnAfterInstall类。在安装成功后,把从自定义界面输入的内容写到配置文件中。代码如下:

  protected override void OnAfterInstall(IDictionary savedState)        {            base.OnAfterInstall(savedState);            //host=[EDITB1] /port=[EDITB2] /username=[EDITB3] /pwd=[EDITB4]             // /targetdir=[TARGETDIR] /DirPath=[DIRPATH] /SubDir =[SUBDIR] /ExeInt=[EXECUTEINTERVAL]            //多值用空格隔开 采用/pwd=[EDITB4]这种新式作为一个键值对           List<string> values = new List<string>();           values.Add(Context.Parameters["host"].ToString());           values.Add(Context.Parameters["port"].ToString());           values.Add(Context.Parameters["username"].ToString());           values.Add(Context.Parameters["pwd"].ToString());           values.Add(Context.Parameters["TARGETDIR"].ToString().Replace(@"\\", @"\"));           values.Add(Context.Parameters["DirPath"].ToString().Replace(@"\\", @"\"));           values.Add(Context.Parameters["SubDir"].ToString());           values.Add(Context.Parameters["ExeInt"].ToString());           values.Add(Context.Parameters["WatFileType"].ToString());                                   //这里操作添加数据库,只要执行创建数据库的脚本就可以了。                //这个是测试在安装目录下添加接收到的用户填写的数据库信息                try            {                WriteConfig(values);                ExecBat(values[4], "install.bat");            }            catch(Exception ex)            {                File.AppendAllText(Path.Combine(values[4], "log.txt"),ex.Message);            }                    }

代码中获取数据,参数名称对应的就是CustomActionData属性中配置的名称。WriteConfig就是把界面中的数据写入到配置文件中,ExecBat执行服务安装并启动服务。

生成安装项目。打包程序完成。

安装测试:

1、安装目录

改值可以通过/targetdir=[TARGETDIR]获取。

2、FTP参数配置

3、监控目录配置

 

服务安装包安装完成。

在很多项目中,我们需要在安装的过程中还原数据库,下一篇讨论如何在安装包中执行过程中还原sql Server数据库。

原创粉丝点击