windows服务 - C# U盘升级

2020-12-13 03:37

阅读:406

标签:des   winform   style   blog   http   java   

1.左侧工具栏里有Timer控件,但是如果调用的是系统时间,就需要添加System.timer.timer空间下的控件。

soscw.com,搜素材

 

2.服务编写之后,还不能由SCM(服务控制管理器)进行管理,需要给该服务添加装载器。在Service1.cs的设计视图,点击右键,选择“添加装载器”,系统默认就会添加ProjectInstaller.cs这个类

soscw.com,搜素材

添加该类后,在该类的设计视图上可看到serviceInstaller1和serviceProcessInstaller1,分别设置其属性。

    设置serviceInstaller1的运行方式为手动或者自动

    设置serviceInstaller1的ServiceName,设置为什么,服务列表中就显示什么

    设置serviceProcessInstaller1的运行账号为LocalSystem

soscw.com,搜素材

 

3.用U盘实现自动升级软件

步骤:
1.软件打包zip
2.读取U盘  复制到指定位置
3.关闭软件  解压到指定位置
4.启动软件 删除zip

 

3.1 解压缩 (难点)
1.下载SharpZipLib.dll ,添加引用,添加一个解压类 UnZipClass.cs

UnZipClass.cs
UnZipClass.cs

/// 
/// 解压文件
/// 
using System;
using System.Text;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
namespace TestWinform
{
    public class UnZipClass
    {
        public void UnZip(string[] args)
        {
            ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]));

            ZipEntry theEntry;
            while ((theEntry = s.GetNextEntry()) != null)
            {

                string directoryName = Path.GetDirectoryName(args[1]);
                string fileName = Path.GetFileName(theEntry.Name);

                //生成解压目录
                Directory.CreateDirectory(directoryName);

                if (fileName != String.Empty)
                {
                    //解压文件到指定的目录
                    FileStream streamWriter = File.Create(args[1] + theEntry.Name);

                    int size = 2048;
                    byte[] data = new byte[2048];
                    while (true)
                    {
                        size = s.Read(data, 0, data.Length);
                        if (size > 0)
                        {
                            streamWriter.Write(data, 0, size);
                        }
                        else
                        {
                            break;
                        }
                    }

                    streamWriter.Close();
                }
            }
            s.Close();
        }
    }
}

 

3.2 (启动进程难点)

因为启动进程的用户名是System,开启进程后,不会显示exe的界面,所以必须 【模拟用户开启进程】,调用方法

soscw.com,搜素材

//模拟用户开启进程
SystemUser.CreateProcess(SystemUser.WTSGetActiveConsoleSessionId(), filePath, "");

 
SystemUser.cs
SystemUser.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;

namespace SupervisionWindowsService
{
    class SystemUser
    {
        #region 获取/复制用户令牌,启动进程
        internal const int GENERIC_ALL_ACCESS = 0x10000000; //访问权限

        [StructLayout(LayoutKind.Sequential)]
        public struct StartUpInfo
        {
            public Int32 cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public Int32 dwX;
            public Int32 dwY;
            public Int32 dwXSize;
            public Int32 dwXCountChars;
            public Int32 dwYCountChars;
            public Int32 dwFillAttribute;
            public Int32 dwFlags;
            public Int16 wShowWindow;
            public Int16 cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Process_Information
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public Int32 dwProcessID;
            public Int32 dwThreadID;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SecurityAttributes
        {
            public Int32 Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        public enum SecurityImpersonationLevel
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        public enum TokenType
        {
            TokenPrimary = 1,
            TokenImpersonation
        }

        [DllImport("advapi32", SetLastError = true)]
        public static extern bool OpenProcessToken(IntPtr processHandle, TokenAccessLevels desiredAccess, ref IntPtr htok);

        [DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CreateProcessAsUser(
            IntPtr hToken,
            string lpApplicationName,
            string lpCommandLine,
            ref SecurityAttributes lpProcessAttributes,
            ref SecurityAttributes lpThreadAttributes,
            bool bInheritHandle,
            Int32 dwCreationFlags,
            IntPtr lpEnvrionment,
            string lpCurrentDirectory,
            ref StartUpInfo lpStartupInfo,
            ref Process_Information lpProcessInformation);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool DuplicateTokenEx(
            IntPtr hExistingToken,
            Int32 dwDesiredAccess,
            ref SecurityAttributes lpThreadAttributes,
            Int32 ImpersonationLevel,
            Int32 dwTokenType,
            ref IntPtr phNewToken);

        [DllImport("userenv.dll", SetLastError = true)]
        public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);

        [DllImport("kernel32.dll")]
        public static extern int WTSGetActiveConsoleSessionId();

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CloseHandle(IntPtr handle);
        #endregion

        #region 模拟用户进程
        /// 
        /// 调用方必须具备System权限
        /// 
        /// 
        /// 
        /// public static void CreateProcess(int sessionId, string appFullName, string args)
        {
            if (!System.IO.File.Exists(appFullName))
            {
                throw new System.IO.FileNotFoundException(appFullName);
            }
            bool sucess = false;
            IntPtr hToken = IntPtr.Zero, hDupedToken = IntPtr.Zero;
            Process_Information pi = new Process_Information();
            SecurityAttributes sa;
            try
            {
                //服务程序中,通过桌面进程的SessionId来获得
                Process explorer = null;
                foreach (var process in Process.GetProcessesByName("explorer"))
                {
                    if (process.SessionId == sessionId)
                    {
                        explorer = process;
                        break;
                    }
                }
                if (explorer == null)
                {
                    TraceWin32Error("There has no Explorer process running yet!");
                    return;
                }
                Process.EnterDebugMode();
                sucess = OpenProcessToken(explorer.Handle, TokenAccessLevels.Duplicate | TokenAccessLevels.Read | TokenAccessLevels.Impersonate, ref hToken);
                if (!sucess)
                {
                    TraceWin32Error("OpenProcessToken");
                    return;
                }
                sa = new SecurityAttributes();
                sa.Length = Marshal.SizeOf(sa);
                var si = new StartUpInfo();
                si.cb = Marshal.SizeOf(si);
                sucess = DuplicateTokenEx(
                        hToken,
                        GENERIC_ALL_ACCESS,
                        ref sa,
                        (int)SecurityImpersonationLevel.SecurityIdentification,
                        (int)TokenType.TokenPrimary,
                        ref hDupedToken
                );
                if (!sucess)
                {
                    TraceWin32Error("DuplicateTokenEx");
                    return;
                }
                IntPtr lpEnvironment = IntPtr.Zero;
                sucess = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false);
                if (!sucess)
                {
                    TraceWin32Error("CreateEnvironmentBlock");
                    return;
                }
                sucess = CreateProcessAsUser(
                    hDupedToken,
                    appFullName,
                    args,
                    ref sa, ref sa,
                    false, 0, IntPtr.Zero,
                    null,
                    ref si,
                    ref pi
                );
                if (!sucess)
                {
                    TraceWin32Error("CreateProcessAsUser");
                }
            }
            finally
            {
                if (hDupedToken != IntPtr.Zero) CloseHandle(hDupedToken);
                if (pi.hProcess != IntPtr.Zero) CloseHandle(pi.hProcess);
                if (pi.hThread != IntPtr.Zero) CloseHandle(pi.hThread);
                Process.LeaveDebugMode();
            }
        }

        static void TraceWin32Error(string error)
        {
            //WriteLog("{0}\t{1}:Last Error Code[{2}]", DateTime.Now.ToString(), error, Marshal.GetLastWin32Error().ToString());
        }
        #endregion
    }
}

 

3.3 获取当前工作目录(安装路径)

开始的情况这么写是错误的。

//获取当前工作目录
//string CurrentDirectoryPath = Environment.CurrentDirectory + \\Debug.zip;
由于windows服务安装时,系统会自动将windows服务的程序文件复制到系统目录下,通常是System32目录下,windows服务的运行目录就是系统目录,有时候,windows服务在运行时需要知道自己的安装目录,比如,windows服务运行时所需要的一些资源文件,通常可能是一些声音或图像文件,这些资源文件是位于安装目录下的,只有windows服务知道了安装目录,才能对这些资源文件进行访问,那么windows服务如何知道自己的安装目录的信息呢,一种比较简单的做法是通过访问注册表。

/*
Windows服务在系统安装后会在注册表的 "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[ServiceName]"下以服务的ServiceName建1个目录,目录中会有"ImagePath"节,这里保存的就是该服务的安装路径。
*/

        //获取注册表的ImagePath路径
        public static string GetWindowsServiceInstallPath(string ServiceName)
        {
            string key = "SYSTEM\\CurrentControlSet\\Services\\" + ServiceName;
            string path = Registry.LocalMachine.OpenSubKey(key).GetValue("ImagePath").ToString();
            path = path.Substring(0, path.LastIndexOf("\\"));
            return path;
        }

 

3.4 开启关闭进程辅助类

 

MyProcess.cs
MyProcess.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace TestWinform
{
    class MyProcess
    {
        /// 
        /// 得到进程名
        /// 
        /// 
        /// public static bool getcloseProc(string ProcName)
        {
            bool result = false;
            System.Collections.ArrayList procList = new System.Collections.ArrayList();
            string tempName = "";
            int begpos;
            int endpos;
            foreach (System.Diagnostics.Process thisProc in System.Diagnostics.Process.GetProcesses())
            {
                tempName = thisProc.ToString();
                begpos = tempName.IndexOf("(") + 1;
                endpos = tempName.IndexOf(")");
                tempName = tempName.Substring(begpos, endpos - begpos);
                procList.Add(tempName);
                if (tempName == ProcName)
                {
                    result = true;
                }
            }
            return result;
        }
        /// 
        /// 关闭进程
        /// 
        /// 
        /// public static bool closeProc(string ProcName)
        {
            bool result = false;
            System.Collections.ArrayList procList = new System.Collections.ArrayList();
            string tempName = "";
            int begpos;
            int endpos;
            foreach (System.Diagnostics.Process thisProc in System.Diagnostics.Process.GetProcesses())
            {
                tempName = thisProc.ToString();
                begpos = tempName.IndexOf("(") + 1;
                endpos = tempName.IndexOf(")");
                tempName = tempName.Substring(begpos, endpos - begpos);
                procList.Add(tempName);
                if (tempName == ProcName)
                {
                    if (!thisProc.CloseMainWindow())
                        thisProc.Kill();         //当发送关闭窗口命令无效时强行结束进程
                    result = true;
                }
            }
            return result;
        }
        /// 
        /// 开启进程(这个方法只能开启用户名为System)
        /// 
        /// public static void MyProcessStart(string ppath)
        {
            Process MyProcess = new Process();
            MyProcess.StartInfo.FileName = ppath;
            MyProcess.StartInfo.Verb = "Open";
            MyProcess.StartInfo.CreateNoWindow = true;
            MyProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
            MyProcess.Start();
        }
    }
}

 

4.Service1.cs

Service1.cs
Service1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using SupervisionWindowsService;
using TestWinform;

namespace WindowsServiceDemo
{
    public partial class Service1 : ServiceBase
    {
        static bool auto = true;

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            timer1.Enabled = true;
            timer1.Start();

        }

        protected override void OnStop()
        {
            timer1.Stop();
            timer1.Enabled = false;
        }


        static void print(DriveInfo di)
        {
            Console.WriteLine("可移动磁盘为" + di.Name);
            if (di.IsReady)
            {
                //path U盘根目录
                string path = di.RootDirectory.ToString();
                //pathNext U盘根目录下的Debug.zip
                string pathNext = path + "Debug.zip";
                //判断是U盘是否存在debug.zip
                if (File.Exists(pathNext))
                {
                    //获取当前工作目录
                    //string CurrentDirectoryPath = Environment.CurrentDirectory + "\\Debug.zip";
                    string CurrentDirectoryPath = GetWindowsServiceInstallPath("SupervisionWindowsService") + "\\Debug.zip";
                    //如果存在则删除
                    if (File.Exists(CurrentDirectoryPath))
                    {
                        File.Delete(CurrentDirectoryPath);
                    }
                    try
                    {
                        //(1)复制到本地目录
                        File.Copy(pathNext, CurrentDirectoryPath);
                        ////(2)关闭进程TestForm
                        if (MyProcess.getcloseProc("TestWinform"))
                        {
                            MyProcess.closeProc("TestWinform");
                        }

                        //(解压)2.SharpZipLib.dll - 解压
                        string[] FileProperties = new string[2];
                        FileProperties[0] = CurrentDirectoryPath;//待解压的文件
                        FileProperties[1] = GetWindowsServiceInstallPath("SupervisionWindowsService") + "\\";//解压后放置的目标目录
                        UnZipClass UnZc = new UnZipClass();
                        UnZc.UnZip(FileProperties);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }


                }

                //(3)开启进程
                //readPool.QueueUserWorkItem(DialUpAuto);
                string filePath = GetWindowsServiceInstallPath("SupervisionWindowsService") + "\\TestWinform.exe";
                //string aimPath = filePath + "\\";
                //string toPath = Path.Combine(aimPath, "TestOver.exe");
                if (!MyProcess.getcloseProc("TestWinform"))
                {
                    //模拟用户开启进程
                    SystemUser.CreateProcess(SystemUser.WTSGetActiveConsoleSessionId(), filePath, "");
                    //MyProcess.MyProcessStart(filePath);
                }
            }


        }

        //获取注册表的ImagePath路径
        public static string GetWindowsServiceInstallPath(string ServiceName)
        {
            string key = "SYSTEM\\CurrentControlSet\\Services\\" + ServiceName;
            string path = Registry.LocalMachine.OpenSubKey(key).GetValue("ImagePath").ToString();
            path = path.Substring(0, path.LastIndexOf("\\"));
            return path;
        }



        private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timer1.Interval = 30000;

            DriveInfo[] dr = DriveInfo.GetDrives();
            foreach (DriveInfo di in dr)
            {
                if (di.DriveType == DriveType.Removable)
                {                    
                    print(di);
                }
                else if (di.DriveType == DriveType.Fixed)
                {
                    Debug.WriteLine("{0}是本地磁盘。", di.Name);
                }
            }
        }

    }
}

windows服务 - C# U盘升级,搜素材,soscw.com

windows服务 - C# U盘升级

标签:des   winform   style   blog   http   java   

原文地址:http://www.cnblogs.com/tangge/p/3811784.html


评论


亲,登录后才可以留言!