最近有个小项目,需求如下:

1:传真机把传真保存为.PDF文件放在某个特定的URI下文件夹中.

2:要监控这个文件夹下的文件变化,也就是有没有新的传真生成.(有新的传真会有新的.PDF文件生成).

3:监控到有新的传真,发邮件通知到相关的监控人员.

4:把新生成的文件上传到SFTP服务器上。

 

由于时间紧,且做得越简单越好.所以后来我决定做个Windows服务来完成这个小项目。

刚开始觉得这个项目应该很简单,不用花太多时间就可以完成的。但在做的过程中还是遇到不少小问题。

现在我把这个过程记下来,以便以后再用到(因为很少写这方面的程序,本人也是第一次写Windows服务程序)和希望能帮助有需要的朋友.

声明有很多内容也是参考网上的。

本人在VS2010下测试通过.

一:创建个解决方案,再创建window service项目,取项目名为ServiceTest

二:在新建好的项目中,找到Service1.cs,右击-->View Code(查看源代码)。在源代码中,OnStart方法是在服务启动时执行的,可以在这里编写服务要执行的业务逻辑代码;OnStop方法是在服务停止 时执行的,一般在这里编写终止服务线程或停止业务逻辑的代码等。

public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
        }

        protected override void OnStop()
        {
        }
    }

三:添加服务安装程序ProjectInstaller。

1)在Service1.cs的设计界面(可双击Service1.cs进入此界面),右击-->Add Installer(添加安装程序);

2)完成第一步,默认项目添加了ProjectInstaller.cs程序;

3)双击编辑文件ProjectInstaller.Designer.cs,更改下面代码:

a:在InitializeComponent方法中,添加代码

  this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;

  ServiceAccount.LocalSystem可以选择不同的类型。

b:在InitializeComponent方法中,修改this.serviceInstaller1.ServiceName为服务类的名 称,默认为Service1,如果项目的服务类的名称更改了,注意一定要修改这个值,如:服务类的名称更为WinServiceTest后,对应修改代码 如下:

  this.serviceInstaller1.ServiceName = "MyFirstService";    //服务类的名称

  this.serviceInstaller1.DisplayName = "My First Service";    //安装后,在window服务管理里显示的名称

  this.serviceInstaller1.Description = "For my first service testing";   //安装后,在window服务管理里显示的描述

    this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;

  ServiceStartMode.Automatic 可以选择不同的类型,有自动启动,手动和禁止三种方式。这里我选择自动启动,往往这类程序都需要自动启动.

四:添加window service安装的批处理命令

 1)在项目添加一个文本文件,更名为install.bat,编辑文件的内容如下:

  %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe .\WindowsServiceSolution.exe
  Net Start MyFirstService
  Pause

  注意:这个Net Start MyFirstService 地方的MyFirstService就是上面这行代码里中设的名子this.serviceInstaller1.ServiceName =      "MyFirstService";

   2)在项目添加一个文本文件,更名为uninstall.bat,编辑文件的内容如下:

  Net Stop MyFirstService
  %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /u WindowsServiceSolution.exe
  Pause

补充说明:

  • 另外,文件install.bat的属性里“Copy to Output Directory”默认为“Do not copy”,编译后,在debug的文件夹里找不到install.bat的,要更改为“Copy always”或者“Copy if newer”才能出现的。uninstall.bat也跟install.bat一样的。
  • Net Stop MyFirstService和Net Stop MyFirstService分别是在卸载和安装时停止和启动服务。
  • Pause是让.bat运行后暂停下可以看到服务的运行结果。

五、实际安装。

  1)编译成功后,在debug文件夹中,双击install.bat完成安装;

  2)安装成功后,在window的服务里,可看到此服务;

  3)双击uninstall.bat可卸载此服务。

 补充说明:也可以不用建install.bat文件,进行可以手动安装。

 a) 运行cmd后进入到InstallUtil.exe路径下运行安装服务,如图。

  再在光标处键入要安装的服务路径运行就行了。

这里我选的版本号为v4.0.30319,你可以选其它版本。

b)可以进入到C:\Windows\System32>下,用SC Create命令安装服务。如果不会SC命令的可以键入SC 回车,看下帮助.如下:

 

 六: 监控.PDF文件,我们可以用FileSystemWatcher这个类来监控,直接上代码吧.
        public void OnCreateFile()
        {
            FileSystemWatcher fileWatcher = new FileSystemWatcher();
            fileWatcher.Path = WatcherDirectory;
            fileWatcher.EnableRaisingEvents = true;
            fileWatcher.Filter = “*.pdf”;
            fileWatcher.Created += new FileSystemEventHandler(PDFFileWatcher_Created);
        }

//注:这样就可以监控.pdf文件了,当有新的.pdf文件创建后就行调用FileWatcher_Created

        void PDFFileWatcher_Created(object sender, FileSystemEventArgs e)
        {
            //log created file name and send mail.
            string createdFileName= e.Name;

    //这里就可以写发邮件的代码了.
        }

七: 发邮件C#代码简单,还是上代码吧,如下:

    MailMessage mailMessage = new MailMessage();

    //mail infomation
            mailMessage.Subject = "Test send mail ";
            mailMessage.From = new MailAddress("发件人邮件地址", "发件人邮件地址");
            mailMessage.Body = "testing";
            mailMessage.BodyEncoding = Encoding.UTF8;
            mailMessage.SubjectEncoding = Encoding.UTF8;
            mailMessage.To.Add("收件人邮件地址");
            mailMessage.IsBodyHtml = true;
            mailMessage.Priority = MailPriority.High;

            //smpt client message.
            SmtpClient smtp = new SmtpClient();
            smtp.Host = "smtp服务器地址";
            smtp.Port = 端口号;
            smtp.EnableSsl = false;
            smtp.UseDefaultCredentials = false;
            smtp.Credentials = new System.Net.NetworkCredential("发件人邮件地址","密码");
            smtp.DeliveryMethod = SmtpDeliveryMethod.Network;

            //send mail.
            smtp.Send(mailMessage);

注:主要问题是在公司里测试时用公司里的SMTP服务器发送时,会遇到很多权限问题.

在这个小项目中害得我花了半天时间测试都没有成功发邮件,找了各种原因,后来问了NSS后才知道现在要申请开通权限(说明一下,以前不用开通的权限的,所以刚开始没有问他们). 所以如果在公司测试不能发邮件时,最好先问问NSS,看看有没有什么权限问题.不要轻易怀疑自己的代码。

八:上传文件到SFTP服务器上

  在网上看了很多类似以下的c#代码,经测试没有成功。总是在GetRequestStream();这个地方抛出异常:没有权限访问。

  而我用WinSCP软件能够连接到SFTP服务上,且能上传,下载文件和一些其它操作. 可是用的是同样的登录名和密码,项目紧也没有多少时间去考虑这个问题了,不知道是不是因为c#的这个程序不支持SFTP.如有知道者请告之,感谢!

       FileInfo fileInf = new FileInfo(filename);

            string uri = ftpURI + fileInf.Name;
            FtpWebRequest reqFTP;
 
            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
            reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
            reqFTP.KeepAlive = false;
            reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
            reqFTP.UseBinary = true;
            reqFTP.ContentLength = fileInf.Length;
            int buffLength = 2048;
            byte[] buff = new byte[buffLength];
            int contentLen;
            FileStream fs = fileInf.OpenRead();
            try
            {
                Stream strm = reqFTP.GetRequestStream();
                contentLen = fs.Read(buff, 0, buffLength);
                while (contentLen != 0)
                {
                    strm.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }
                strm.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                Insert_Standard_ErrorLog.Insert("FtpWeb", "Upload Error --> " + ex.Message);
            }

所以我后来我只能改用WinSCP来上传和下载。

步骤:进入运行 cmd命令

  1)进入到c:\program files\WinSCP3>WinSCP.exe

  

  2)再键入这些参数运行,就可以把文件上传到服务器了

 注:对以上参数解析

/console /command 表示命令运行。

"option batch continue" 批处理一直进行,直到处理结束。

"option confirm off" 不弹出确认。

"open sftp://UserId:Password@SFTPIP:Port" 分别为用户名,密码,sftp ip和端口号。格式固定这样写的。

"option transfer binary" 以二进制方式传送。

"put d:\sourcefolder test" d:\sourcefolder要上传的文件路径;test为SFTP服务器上目标文件夹,如果test省略,刚在SFTP上生成与sourcefolder同名的文件夹. 如果d:\sourcefolder换成d:\sourcefolder\filename.*这样的格式,就会上传特定的文件到服务器的当出目录。

"close" 关闭连接。

"exit"  退出。

 

代码整合一下,就实现了文件的监控,发邮件,上传到SFTP服务器整功能了。

 

总节:虽然是小项目,但是要注意的地方也不少。特别是对像我这样初次做这类程序的人,做好了也不容易。

希望对和我有相同需求的朋友,有所帮助!

posted on 2013-04-17 17:52  Albert Fei  阅读(1699)  评论(0编辑  收藏  举报