乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【轉(zhuǎn)】Windows服務(wù)如何啟動(dòng)帶UI界面的外部程序及啟動(dòng)服務(wù)時(shí)傳遞命令行參數(shù)

       行走在理想邊緣 2022-09-27 發(fā)布于四川

      【目標(biāo)】定時(shí)檢測特定應(yīng)用是否運(yùn)行,如沒運(yùn)行則啟動(dòng)它:

      方法1:創(chuàng)建Windows任務(wù)計(jì)劃程序(外部程序?qū)嵗堰\(yùn)行時(shí)則忽略):


      最后一步就是指定運(yùn)行程序(起始路徑設(shè)置為外部程序的所在路徑很重要,否則可能無法因找不到程序無法啟動(dòng)):


      方法2:創(chuàng)建Windows服務(wù)來啟動(dòng)外部程序(外部程序編寫需要有自己判斷實(shí)例是否已存在,存在則退出,保持單實(shí)例):

      但是通常應(yīng)用程序的帶UI界面的,遺憾的是Windows服務(wù)是不支持運(yùn)行UI界面程序的,譬如下面方式運(yùn)行帶UI界面的應(yīng)用則發(fā)現(xiàn)打不開

      //打開程序的地址
      var fileName = path;
      //判斷文件是否存在,如果不存在,返回 false
      Console.WriteLine(File.Exists(fileName));
      
      ProcessStartInfo startInfo = new ProcessStartInfo();
      startInfo.FileName = fileName;
      Process process = new Process();
      process.StartInfo = startInfo;
      process.Start();

      這里就需要用到“繞過UAC以最高權(quán)限”來啟動(dòng):

      自Vista操作系統(tǒng)之后,微軟考慮到安全因素,在系統(tǒng)管理員賬戶和標(biāo)準(zhǔn)用戶之間創(chuàng)出了UAC(用戶賬戶控制)。當(dāng)標(biāo)準(zhǔn)用戶啟動(dòng)需管理員權(quán)限的操作時(shí)要彈框讓用戶確認(rèn),這樣可防止惡意軟件或間諜軟件隨意修改系統(tǒng)造成破壞。

      但對(duì)于必須要通過最高權(quán)限運(yùn)行交互進(jìn)程來說就造成問題,微軟API接口提供CreateProcessAsUser函數(shù)用于在后臺(tái)服務(wù)程序中啟動(dòng)前臺(tái)進(jìn)程,但啟動(dòng)時(shí)要請(qǐng)求UAC權(quán)限(由于后臺(tái)服務(wù)是最高權(quán)限啟動(dòng),其創(chuàng)建的子進(jìn)程也繼承最高權(quán)限),這時(shí)后臺(tái)UAC窗口無法顯示在前臺(tái)界面上,造成程序永遠(yuǎn)等待無法啟動(dòng)。

      vista之后,微軟會(huì)為每個(gè)登錄用戶分配一個(gè)會(huì)話,后臺(tái)服務(wù)在系統(tǒng)啟動(dòng)時(shí)最先啟動(dòng),分配的會(huì)話ID為0,其后每登錄一個(gè)用戶會(huì)話ID加1:

      問題來了,由于有會(huì)話隔離,我們無法在一個(gè)會(huì)話程序中直接啟動(dòng)另一會(huì)話的程序。但微軟有一個(gè)特殊的進(jìn)程,對(duì)于每個(gè)會(huì)話會(huì)有一個(gè)對(duì)應(yīng)的進(jìn)程,這個(gè)進(jìn)程就是winlogin.exe:

      winlogin進(jìn)程的作用

      Winlogon.exe進(jìn)程是微軟公司為其Windows操作系統(tǒng)定義的一個(gè)非常重要的系統(tǒng)核心進(jìn)程,被稱為“Windows登陸應(yīng)用程序”,它會(huì)隨著系統(tǒng)啟動(dòng)而啟動(dòng)并一直運(yùn)行。通常情況下此進(jìn)程應(yīng)該是安全的,并且只占用很少的CPU及內(nèi)存資源,如果資源占用過多則很有可能被病毒“劫持”。

      請(qǐng)不要嘗試將本進(jìn)程終止(也無法在任務(wù)管理器將其終止)或?qū)⒋诉M(jìn)程從系統(tǒng)中刪除,這會(huì)導(dǎo)致你的系統(tǒng)無法正常運(yùn)行。因?yàn)閃inlogon.exe進(jìn)程為系統(tǒng)提供了有以下4項(xiàng)重要的功能:
        1、在登錄系統(tǒng)時(shí)加載的用戶配置文件,以及執(zhí)行注銷用戶與鎖定計(jì)算機(jī);
        2、負(fù)責(zé)處理Ctrl+Alt+Del快捷鍵(SAS)的功能;
        3、監(jiān)控鍵盤和鼠標(biāo)使用情況來決定什么時(shí)候啟動(dòng)屏幕保護(hù)程序;
        4、檢驗(yàn)Windows操作系統(tǒng)激活密鑰是否為合法許可;

      可以發(fā)現(xiàn)winlogin進(jìn)程是后臺(tái)服務(wù)進(jìn)程,但所屬登錄用戶會(huì)話,那是不是可以通過這個(gè)進(jìn)程來達(dá)到我們繞過UAC的限制啟動(dòng)前臺(tái)交互程序呢?沒錯(cuò)!?。?/span>

      有了winlogin進(jìn)程,我們可以在后臺(tái)服務(wù)中先查詢到winlogin進(jìn)程信息,獲取其訪問令牌,最后通過CreateProcessAsUser將進(jìn)程啟動(dòng)到活動(dòng)登錄用戶當(dāng)前活動(dòng)會(huì)話。由于和前臺(tái)界面所屬同一會(huì)話,啟動(dòng)后的程序便可以進(jìn)行交互。
      下面為有心人寫好的代碼(ApplicationLoader.cs):

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Security;
      using System.Diagnostics;
      using System.Runtime.InteropServices;
      
      namespace CheckProcService
      {
          /// <summary>
          /// Class that allows running applications with full admin rights. In
          /// addition the application launched will bypass the Vista UAC prompt.
          /// </summary>
          public class ApplicationLoader
          {
              #region Structures
      
              [StructLayout(LayoutKind.Sequential)]
              public struct SECURITY_ATTRIBUTES
              {
                  public int Length;
                  public IntPtr lpSecurityDescriptor;
                  public bool bInheritHandle;
              }
      
              [StructLayout(LayoutKind.Sequential)]
              public struct STARTUPINFO
              {
                  public int cb;
                  public String lpReserved;
                  public String lpDesktop;
                  public String lpTitle;
                  public uint dwX;
                  public uint dwY;
                  public uint dwXSize;
                  public uint dwYSize;
                  public uint dwXCountChars;
                  public uint dwYCountChars;
                  public uint dwFillAttribute;
                  public uint dwFlags;
                  public short wShowWindow;
                  public short 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 uint dwProcessId;
                  public uint dwThreadId;
              }
      
              #endregion
      
              #region Enumerations
      
              enum TOKEN_TYPE : int
              {
                  TokenPrimary = 1,
                  TokenImpersonation = 2
              }
      
              enum SECURITY_IMPERSONATION_LEVEL : int
              {
                  SecurityAnonymous = 0,
                  SecurityIdentification = 1,
                  SecurityImpersonation = 2,
                  SecurityDelegation = 3,
              }
      
              #endregion
      
              #region Constants
      
              public const int TOKEN_DUPLICATE = 0x0002;
              public const uint MAXIMUM_ALLOWED = 0x2000000;
              public const int CREATE_NEW_CONSOLE = 0x00000010;
      
              public const int IDLE_PRIORITY_CLASS = 0x40;
              public const int NORMAL_PRIORITY_CLASS = 0x20;
              public const int HIGH_PRIORITY_CLASS = 0x80;
              public const int REALTIME_PRIORITY_CLASS = 0x100;
      
              #endregion
      
              #region Win32 API Imports
      
              [DllImport("kernel32.dll", SetLastError = true)]
              private static extern bool CloseHandle(IntPtr hSnapshot);
      
              [DllImport("kernel32.dll")]
              static extern uint WTSGetActiveConsoleSessionId();
      
              [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
              public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
                  ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
                  String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
      
              [DllImport("kernel32.dll")]
              static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);
      
              [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
              public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
                  ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
                  int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
      
              [DllImport("kernel32.dll")]
              static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
      
              [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
              static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
      
              #endregion
      
              /// <summary>
              /// Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt
              /// </summary>
              /// <param name="applicationName">The name of the application to launch</param>
              /// <param name="procInfo">Process information regarding the launched application that gets returned to the caller</param>
              /// <returns></returns>
              public static bool StartProcessAndBypassUAC(string applicationName, string currentDirectory, out PROCESS_INFORMATION procInfo)
              {
                  uint winlogonPid = 0;
                  IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
                  procInfo = new PROCESS_INFORMATION();
      
                  // obtain the currently active session id; every logged on user in the system has a unique session id
                  uint dwSessionId = WTSGetActiveConsoleSessionId();
      
                  // obtain the process id of the winlogon process that is running within the currently active session
                  Process[] processes = Process.GetProcessesByName("winlogon");
                  foreach (Process p in processes)
                  {
                      if ((uint)p.SessionId == dwSessionId)
                      {
                          winlogonPid = (uint)p.Id;
                      }
                  }
      
                  // obtain a handle to the winlogon process
                  hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
      
                  // obtain a handle to the access token of the winlogon process
                  if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
                  {
                      CloseHandle(hProcess);
                      return false;
                  }
      
                  // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
                  // I would prefer to not have to use a security attribute variable and to just 
                  // simply pass null and inherit (by default) the security attributes
                  // of the existing token. However, in C# structures are value types and therefore
                  // cannot be assigned the null value.
                  SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
                  sa.Length = Marshal.SizeOf(sa);
      
                  // copy the access token of the winlogon process; the newly created token will be a primary token
                  if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
                  {
                      CloseHandle(hProcess);
                      CloseHandle(hPToken);
                      return false;
                  }
      
                  // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
                  // the window station has a desktop that is invisible and the process is incapable of receiving
                  // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user 
                  // interaction with the new process.
                  STARTUPINFO si = new STARTUPINFO();
                  si.cb = (int)Marshal.SizeOf(si);
                  si.lpDesktop = @"winsta0\default"; // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop
      
                  // flags that specify the priority and creation method of the process
                  int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
      
                  // create a new process in the current user's logon session
                  bool result = CreateProcessAsUser(hUserTokenDup,        // client's access token
                                                  null,                   // file to execute
                                                  applicationName,        // command line
                                                  ref sa,                 // pointer to process SECURITY_ATTRIBUTES
                                                  ref sa,                 // pointer to thread SECURITY_ATTRIBUTES
                                                  false,                  // handles are not inheritable
                                                  dwCreationFlags,        // creation flags
                                                  IntPtr.Zero,            // pointer to new environment block 
                                                  currentDirectory,       // name of current directory 
                                                  ref si,                 // pointer to STARTUPINFO structure
                                                  out procInfo            // receives information about new process
                                                  );
      
                  // invalidate the handles
                  CloseHandle(hProcess);
                  CloseHandle(hPToken);
                  CloseHandle(hUserTokenDup);
      
                  return result; // return the result
              }
      
          }
      }

      然后創(chuàng)建一個(gè)服務(wù)類(CheckProcRunningService.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.Threading.Tasks;
      
      namespace CheckProcService
      {
          public partial class CheckProcRunningService : ServiceBase
          {
              public CheckProcRunningService()
              {
                  InitializeComponent();
              }
      
              private const int _MIN_INTERVAL = 60000;
              protected override void OnStart(string[] args)
              {
                  CommandLineArguments arguments = new CommandLineArguments(args);
                  ConfigHelper.Arguments = arguments;
      
                  System.Threading.ThreadStart job = new System.Threading.ThreadStart(StartJob);
                  System.Threading.Thread thread = new System.Threading.Thread(job);
                  thread.Start();
                  EventLog.WriteEntry(this.ServiceName, string.Format("CheckProcRunningService -period:{0} -procfilename:{1}", this.Period.ToString(), this.ProcFileName), EventLogEntryType.Information);
                  return;
              }
      
              private static int? _period;
              public int Period
              {
                  get
                  {
                      if (!_period.HasValue)
                      {
                          int period = _MIN_INTERVAL;
                          //EventLog.WriteEntry(this.ServiceName, string.Format("-period:{0}", ConfigHelper.Arguments.Parameters.ContainsKey("Period")), EventLogEntryType.Warning);
                          if (ConfigHelper.Arguments.Parameters.ContainsKey("Period"))
                              int.TryParse(ConfigHelper.Arguments.Parameters["Period"], out period);
                          _period = period;
                      }
                      return _period.Value;
                  }
              }
      
              private static string _procfilename;
              public string ProcFileName
              {
                  get
                  {
                      if (string.IsNullOrWhiteSpace(_procfilename))
                      {
                          string fn = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "trayicondemo.exe");
                          if (ConfigHelper.Arguments.Parameters.ContainsKey("ProcFileName"))
                              fn = ConfigHelper.Arguments.Parameters["ProcFileName"];
                          _procfilename = fn;
                      }
                      return _procfilename;
                  }
              }
      
              protected override void OnStop()
              {
                  if (_timer != null) _timer.Dispose();
              }
      
              private Timer _timer;
              private void StartJob()
              {
                  try
                  {
                      EventLog.WriteEntry(this.ServiceName, string.Format("Starting on {0} Paramters[Period: {1} ProcFileName:{2}]", DateTime.Now, this.Period.ToString(), this.ProcFileName), EventLogEntryType.Information);
      
                      _timer = new Timer(new TimerCallback(ExecCheckRunJob));
                      _timer.Change(0, this.Period);
                  }
                  catch (Exception ex)
                  {
                      EventLog.WriteEntry(this.ServiceName, ex.Message, EventLogEntryType.Warning);
                  }
              }
      
              private void ExecCheckRunJob(object state)
              {
                  //string errMsg = string.Empty;
                  //ProcessHelper.ExecBatch(fn, false, false, false, "", ref errMsg);
      
                  // the name of the application to launch;
                  // to launch an application using the full command path simply escape
                  // the path with quotes, for example to launch firefox.exe:
                  //      String applicationName = "\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\"";
                  //string fn = "cmd.exe";
      
                  // launch the application
                  ApplicationLoader.PROCESS_INFORMATION procInfo;
                  string currentDirectory = Path.GetDirectoryName(this.ProcFileName);
                  ApplicationLoader.StartProcessAndBypassUAC(this.ProcFileName, currentDirectory, out procInfo);
              }
          }
      }

      覆寫方法OnStart提供了命令行參數(shù)來指定檢測頻率(間隔多少毫秒,應(yīng)用程序全路徑),命令行參數(shù)輔助類(CommandLineUtility.cs)代碼如下:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Collections.Specialized;
      using System.Text.RegularExpressions;
      
      namespace CheckProcService
      {
          /// <summary>
          /// 命令行參數(shù)類
          /// 測試參數(shù)如下:-param0 -param1 value1 --param2 value2 /param3 value3 =param4 value4 :param5 value5 -param6=param6 -param7:param7 -param8.1 "1234" -param8.2 "1 2 3 4" -param9.1 '1234' -param9.2='1 2 3 4'
          /// 各參數(shù)項(xiàng)測試內(nèi)容如下:
          /// -param0,只有參數(shù)項(xiàng)
          /// -param1 value1,有參數(shù)項(xiàng),有參數(shù)值
          /// --param2 value2,用--標(biāo)記參數(shù)項(xiàng)開頭
          /// /param value3,用/標(biāo)記參數(shù)項(xiàng)開頭
          /// =param4 value4,用=標(biāo)記參數(shù)項(xiàng)開頭
          /// :param5 value5,用:標(biāo)記參數(shù)項(xiàng)開頭
          /// -param6=param6,用=標(biāo)記參數(shù)項(xiàng)與參數(shù)值的關(guān)系
          /// -param7:param7,用:標(biāo)記參數(shù)項(xiàng)與參數(shù)值的關(guān)系
          /// -param8.1 "1234",用""指定參數(shù)
          /// -param8.2 "1 2 3 4",用""指定參數(shù)(含空格)
          /// -param9.1 '1234',用''指定參數(shù)
          /// -param9.2='1 2 3 4',用''指定參數(shù)(含空格)
          /// </summary>
          public class CommandLineArguments
          {
              // Variables
              private StringDictionary _parameters;
      
              // Constructor
              public CommandLineArguments(string[] Args)
              {
                  Parameters = new StringDictionary();
                  Regex spliter = new Regex(@"^-{1,2}|^/|=|:",
                      RegexOptions.IgnoreCase | RegexOptions.Compiled);
      
                  Regex remover = new Regex(@"^['""]?(.*?)['""]?$",
                      RegexOptions.IgnoreCase | RegexOptions.Compiled);
      
                  string parameter = null;
                  string[] parts;
      
                  // Valid parameters forms:
                  // {-,/,--}param{ ,=,:}((",')value(",'))
                  // Examples: 
                  // -param1 value1 --param2 /param3:"Test-:-work" 
                  //   /param4=happy -param5 '--=nice=--'
                  foreach (string txt in Args)
                  {
                      // Look for new parameters (-,/ or --) and a
                      // possible enclosed value (=,:)
                      parts = spliter.Split(txt, 3);
      
                      switch (parts.Length)
                      {
                          // Found a value (for the last parameter 
                          // found (space separator))
                          case 1:
                              if (parameter != null)
                              {
                                  if (!Parameters.ContainsKey(parameter))
                                  {
                                      parts[0] =
                                          remover.Replace(parts[0], "$1");
      
                                      Parameters.Add(parameter, parts[0]);
                                  }
                                  parameter = null;
                              }
                              // else Error: no parameter waiting for a value (skipped)
                              break;
      
                          // Found just a parameter
                          case 2:
                              // The last parameter is still waiting. 
                              // With no value, set it to true.
                              if (parameter != null)
                              {
                                  if (!Parameters.ContainsKey(parameter))
                                      Parameters.Add(parameter, "true");
                              }
                              parameter = parts[1];
                              break;
      
                          // Parameter with enclosed value
                          case 3:
                              // The last parameter is still waiting. 
                              // With no value, set it to true.
                              if (parameter != null)
                              {
                                  if (!Parameters.ContainsKey(parameter))
                                      Parameters.Add(parameter, "true");
                              }
      
                              parameter = parts[1];
      
                              // Remove possible enclosing characters (",')
                              if (!Parameters.ContainsKey(parameter))
                              {
                                  parts[2] = remover.Replace(parts[2], "$1");
                                  Parameters.Add(parameter, parts[2]);
                              }
      
                              parameter = null;
                              break;
                      }
                  }
                  // In case a parameter is still waiting
                  if (parameter != null)
                  {
                      if (!Parameters.ContainsKey(parameter))
                          Parameters.Add(parameter, "true");
                  }
              }
      
              // Retrieve a parameter value if it exists 
              // (overriding C# indexer property)
              public string this[string param]
              {
                  get
                  {
                      return (Parameters[param]);
                  }
              }
      
              public StringDictionary Parameters
              {
                  get { return _parameters; }
                  set { _parameters = value; }
              }
          }
      
          public class ConfigHelper
          {
              public static CommandLineArguments Arguments { get; set; }
          }
      }

      服務(wù)安裝類(Installer.cs)如下:

      using Microsoft.Win32;
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Configuration.Install;
      using System.Linq;
      using System.Threading.Tasks;
      
      namespace CheckProcService
      {
          [RunInstaller(true)]
          public partial class ServiceInstaller : Installer
          {
              public ServiceInstaller()
              {
                  InitializeComponent();
      
                  this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
                  this.serviceProcessInstaller1.Password = null;
                  this.serviceProcessInstaller1.Username = null;
                  //this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
                  //this.serviceProcessInstaller1.Password = "Bronzepen1o3$";
                  //this.serviceProcessInstaller1.Username = "guoshaoyue@hissoft.com";
      
                  this.serviceInstaller1.ServiceName = "procsvcl";
                  this.serviceInstaller1.DisplayName = "Check Compiler Manager Running";
                  this.serviceInstaller1.Description = "Check compiler process running, otherwise run it immediately.";
                  this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
              }
      
              protected override void OnAfterInstall(IDictionary savedState)
              {
                  base.OnAfterInstall(savedState);
      
                  //設(shè)置允許服務(wù)與桌面交互
                  RegistryKey rk = Registry.LocalMachine;
                  string key = @"SYSTEM\CurrentControlSet\Services\" + this.serviceInstaller1.ServiceName;
                  RegistryKey sub = rk.OpenSubKey(key, true);
                  int value = (int)sub.GetValue("Type");
                  sub.SetValue("Type", value | 256);
              }
          }
      }

      主程序如下(Program.cs):

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.ServiceProcess;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace CheckProcService
      {
          static class Program
          {
              /// <summary>
              /// 應(yīng)用程序的主入口點(diǎn)。
              /// </summary>
              static void Main()
              {
                  ServiceBase[] ServicesToRun;
                  ServicesToRun = new ServiceBase[]
                  {
                      new CheckProcRunningService()
                  };
                  ServiceBase.Run(ServicesToRun);
              }
          }
      }

      部署服務(wù)代碼如下:

      net stop procsvcl
      
      C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /u "F:\GitHub\PycharmProjects\PyQtTest\dist\CheckProcService.exe"
      pause
      
      C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe "F:\GitHub\PycharmProjects\PyQtTest\dist\CheckProcService.exe"
      pause
      
      sc start procsvcl /period:300000 /procfilename:"F:\GitHub\PycharmProjects\PyQtTest\dist\trayicondemo.exe"

      通過測試我們把命令行參數(shù)傳遞進(jìn)去了:

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多