最近想找個軟體來控制電腦的關機時間,在網上找了幾個,都是可視化介面的可以設定具體的關機時間的軟體。由於我想編寫的關機程式是運行在別人機器上,只能讓該機器在晚上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; } /** * 判斷目前時間是否應該休息的時間 * * @return */ 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)) { return true; } // 3. 非休息時間 return false; } /** * 判斷是否有人修改了系統時間,如果有人修改了系統時間返回true ,<BR> * 否則返回false * * @return */ 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) { // 有人修改了系統時間,強制關機 return true; } // 4. 只有沒人修改時間才記錄上次檢測時間 m_lLastMilliSeconds = System.currentTimeMillis(); return false; } /** * 在指定的流中寫入日誌資訊 * * @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())); return; } appendLog(_out, " 有人修改了系統時間,系統強制關機!"); // 關機 try { Runtime.getRuntime().exec( "shutdown -s -t 120 -c /" 很晚了,該睡覺了,2 分鐘後關閉電腦。/""); } catch (IOException e) { appendLog(_out, e.getMessage()); } bHasShutDownPC = true; } } } |