天天看點

如何注冊java程式為windows服務

最近想找個軟體來控制電腦的關機時間,在網上找了幾個,都是可視化界面的可以設定具體的關機時間的軟體。由于我想編寫的關機程式是運作在别人機器上,隻能讓該機器在晚上17 點到23 點25 分才上網,到了23 點25 分就可以自動關機。為了讓别人感覺不到這個軟體的“存在”(免得使用者自己關閉定時關機軟體),是以我想把關機軟體注冊為服務的方式,運作在背景。這裡介紹下如何利用javaService 軟體把java 程式注冊為windows 服務。

一、  利用javaService 注冊java 程式為windows 服務

[1] 下載下傳javaService

通路網址http://javaservice.objectweb.org/ 下載下傳windows 版本的javaService 檔案,我下載下傳的是JavaService-2.0.10.rar ,目前最新的版本就是“2.0.10 ”。

[2] 安裝javaService

解壓我們下載下傳下來的javaServices 到一個目錄,我是解壓到目錄“D:/software/JavaService-2.0.10 ”下(解壓到任何目錄都可以,最好别解壓到中文目錄,省的出現問題 )

[3] 編寫定時關機代碼,見第二章的定時關機代碼

1)   具體代碼參加第二章,類的名字為:

com.test.timer.TimerShutDownWindows

2)   把編寫後的java 檔案導出為class 的形式,把導出的類放到目錄“D:/software/JavaService-2.0.10/classes/com/test/timer ”下。也就是把導出的com 包放到

“D:/software/JavaService-2.0.10/classes” 目錄下。

[4] 注冊java 程式為windows 服務

進入“D:/software/JavaService-2.0.10 “目錄,執行如下指令:

JavaService.exe -install MyShutDownService "%JAVA_HOME%"/jre/bin/server/jvm.dll -Djava.class.path="%JAVA_HOME%"/lib/tools.jar;D:/software/JavaService-2.0.10/classes -start com.test.timer.TimerShutDownWindows

其中“-install “後面的參數為服務的名稱,“-start ”參數後邊是要啟動的類名,“Djava.class.path ”後面參數中的

“D:/software/JavaService-2.0.10/classe ”位址是我的“TimerShutDownWindows ”類存放的路徑,實際應用中修改為自己的classPath 即可。

  這裡需要注意幾點:

1)   “%JAVA_HOME% ”jdk 目錄,如果沒有配置jdk 目錄,則替換為jdk 的實際絕對位址。

2)   -Djava.class.path 是必須的,因為服務啟動的時候無法通路系統的CLASSPATH 變量,是以必須在這裡聲明;如果jar 比較多,為避免寫的指令過長,我們可以使用“-Djava.ext.dirs=jars 所在目錄”參數。

3)   服務添加之後,可以在指令行中敲入“services.msc ”指令來檢視所有服務,并可以對服務的啟動類型(自動啟動還是手動啟動等)進行修改。

[5] 測試

1)  啟動服務

當我們注冊完服務後,我們可以通過指令“net start MyShutDownService ”來啟動該服務,服務啟動後會在D 盤根目錄生成my_shutdown.log 日志檔案。

2)  關閉服務

如果我們要關閉服務,可以通過指令“net stop MyShutDownService ”來關閉該服務。

3)  删除服務

當我們想删除該服務時,可以使用指令“sc delete MyShutDownService ”來删除該服務。

二、  定時關機代碼

package com.test.timer;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

public class TimerShutDownWindows {

    /* 檢測是否需要關機的時間間隔 */

    private static long m_nDetectInterval = 5000;

    /* 記錄上次檢測的時間,以毫秒為機關 */

    private static long m_lLastMilliSeconds = 0;

    /* 可以使用電腦的最小小時 */

    private static int m_nUsePCMinHour = 17;

    /* 可以使用電腦的最大小時 */

    private static int m_nUseComputerMaxHour = 23;

    /* 如果分鐘超過這個時間,則關機計算機 */

    private static int m_nMinutes = 25;

    /* 記錄日志的檔案的儲存位置 */

    private static String m_sLogFile = "D:" + File.separator

           + "my_shutdown.log";

    /* 記錄目前系統是否已經啟動自動關閉程式 */

    private static boolean bHasShutDownPC = false;

    /**

      * @param args

      */

    public static void main(String[] args) {

       // 1. 單獨開啟一個線程去檢測

       Thread aThread = new Thread(new TimerDetector());

       aThread.start();

    }

      * 定義内部類

      *

      * @author Administrator

    static class TimerDetector implements Runnable {

       /*

         * (non-Javadoc)

         *

         * @see java.lang.Runnable#run()

         */

       public void run() {

           // 1. 擷取日志檔案

           PrintWriter out = null;

           SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

           try {

              out = new PrintWriter(new FileWriter(m_sLogFile, true), true);

           } catch (IOException e1) {

              out = null;

              e1.printStackTrace();

           }

           // 2. 記錄服務啟動時間

           appendLog(out, " 服務啟動時間:" + df.format(new Date()));

           while (true) {

              // 1. 判斷目前系統時間是否被修改過

              boolean bShoudShutDownPC = validateShoudShutDownPC(out);

              if (bShoudShutDownPC) {

                  // 驗證沒通過,強制關機

                  exectueShutDown(out);

              } else {

                  bHasShutDownPC = false;

              }

              // 2. 目前線程休眠下

              try {

                  Thread.sleep(m_nDetectInterval);

              } catch (InterruptedException e) {

                  appendLog(out, e.getMessage());

       }

       /**

         * 驗證目前時間是否是需要關機的時間

         * @return

       private boolean validateShoudShutDownPC(PrintWriter _out) {

           // 1. 判斷是否修改了系統時間

           boolean bHasModifySystemTime = detectModifySytemTime(_out);

           appendLog(_out, "bHasModifySystemTime :" + bHasModifySystemTime);

           if (bHasModifySystemTime) {

              return bHasModifySystemTime;

           // 2. 沒有修改系統時間,則判斷目前時間是否超過了指定的時間

           boolean bShoudSleep = nowIsSleepTime();

           appendLog(_out, "bShoudSleep :" + bShoudSleep);

           if (bShoudSleep) {

              return bShoudSleep;

           return false;

         * 判斷目前時間是否應該休息的時間

       private boolean nowIsSleepTime() {

           // 1. 擷取目前小時和分鐘

           Calendar aCalendar = Calendar.getInstance();

           int nHour = aCalendar.get(Calendar.HOUR_OF_DAY);

           int nMinute = aCalendar.get(Calendar.MINUTE);

           // 2. 判斷目前小時是否在可以使用PC 的時間内, 最大小時為23

           if (nHour < m_nUsePCMinHour) {

              return true;

           // 23 點需要單獨判斷,超過23 點30 就應該休息

           if ((nHour >= m_nUseComputerMaxHour) && (nMinute >= m_nMinutes)) {

           // 3. 非休息時間

         * 判斷是否有人修改了系統時間,如果有人修改了系統時間傳回true ,<BR>

         * 否則傳回false

       private boolean detectModifySytemTime(PrintWriter _out) {

           // 1. 第一次檢測系統時間

           if (m_lLastMilliSeconds == 0) {

              m_lLastMilliSeconds = System.currentTimeMillis();

              return false;

           // 2. 檢測兩次時間的內插補點

           long lInteral = System.currentTimeMillis() - m_lLastMilliSeconds;

           lInteral = Math.abs(lInteral);

           // 3. 判斷兩次的時間間隔, 兩次結果不一定完全等于 m_nDetectInterval ,允許誤差為1 分鐘

           long lMaxInterval = m_nDetectInterval + 60 * 1000;

           appendLog(_out, "lInteral :::" + lInteral);

           appendLog(_out, "lMaxInterval :::" + lMaxInterval);

           if (lInteral > lMaxInterval) {

              // 有人修改了系統時間,強制關機

           // 4. 隻有沒人修改時間才記錄上次檢測時間

           m_lLastMilliSeconds = System.currentTimeMillis();

         * 在指定的流中寫入日志資訊

         * @param _outWriter

         * @param _sAppendContent

       private void appendLog(PrintWriter _outWriter, String _sAppendContent) {

           if (_outWriter == null) {

              return;

           _outWriter.println(_sAppendContent);

         * 執行關機指令

       private void exectueShutDown(PrintWriter _out) {

           if (bHasShutDownPC) {

              SimpleDateFormat df = new SimpleDateFormat(

                     "yyyy-MM-dd HH:mm:ss");

              appendLog(_out, " 系統即将關閉, 目前時間:" + df.format(new Date()));

           appendLog(_out, " 有人修改了系統時間,系統強制關機!");

           // 關機

              Runtime.getRuntime().exec(

                     "shutdown -s -t 120 -c /" 很晚了,該睡覺了,2 分鐘後關閉計算機。/"");

           } catch (IOException e) {

              appendLog(_out, e.getMessage());

           bHasShutDownPC = true;

}