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

开发目的: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数据库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值