为java应用程序设置开机启动项

思路就是将java应用程序打包成.jar文件,然后转成.exe,通过修改注册表来增加删除启动项,即将安装后的.exe执行文件添加到注册表中;

 

首先将java应用程序打包成.jar文件,可以利用如下代码找到.jar文件的绝对路径,即也可以找到安装后的.exe执行文件

转载:

对于Java程序,无论是未打包的还是打包的JAR或WAR文件,有时候都需要获取它运行所在目录信息,如何做到这一点呢? 

在Java处理的文件系统中,目录的表示方式有两种: 

(1)绝对目录,它以"/"为起始字符,代表从根目录下开始寻找给出的目录,如/c:/java 

(2)相对路径,它以不带“/”的目录名表示,表示以当前Java程序正在运行的目录作为起始目录来寻找给出的目录。如java/classes。在相对路径中,有一些特定的字符,可以代表特的的目录,比如,“.”代表当前目录,“..”代表当前目录的上一级目录。在网上很多给出的例子中,就是利用"."作为目录名,构造File对象的实例,然后通过File对象的方法来获取当前程序运行的目录。 

    这种方法虽然简单,但有时不能正确的得出当前程序的运行目录。原因在于,运行Java程序不一定要进入到该程序的类文件或JAR文件所在的目录,只要在运行时指定了正确的类路径信息,就可以在任何目录中运行Java程序,此时利用这种方法只能得到发出运行命令时所在的目录信息。 

     从上面的分析可以看出,对于很多Java程序,尤其是WEB程序,利用当前路径的“.”表示法,都不能满足要求。那么怎样才能正确的得到运行目录信息呢? 

     在Web程序中,利用Servlet API可以获得一些路径信息,比如HttpServletRequest接口中定义的getRealPath方法,但类似这些方法都依赖于Servlet环境,不便于程序的单元测试。 

    本文提供了一种只使用Java标准API的路径探测方法,就是利用ClassLoader抽象类。 

    利用java.lang.Class的getClassLoader方法,可以获得给定类的ClassLoader实例,它的getResource方法可以获得当前类装载器中的资源的位置,我们可以利用类文件的名称作为要查找的资源,经过处理后就可获得当前Java程序的运行位置信息,其伪代码如下: 
    
    获得Class参数的所在的类名 
    取得该类所在的包名 
    将包名转换为路径 
    利用getResource得到当前的类文件所在URL 
    利用URL解析出当前Java程序所在的路径

 

具体代码如下:

java代码:

Java代码  复制代码
  1. /**-----------------------------------------------------------------------  
  2.     *getAppPath需要一个当前程序使用的Java类的class属性参数,它可以返回打包过的  
  3.     *Java可执行文件(jar,war)所处的系统目录名或非打包Java程序所处的目录  
  4.     *@param cls为Class类型  
  5.     *@return 返回值为该类所在的Java程序运行的目录  
  6.     -------------------------------------------------------------------------*/  
  7.    public static String getAppPath(Class cls){   
  8.        //检查用户传入的参数是否为空   
  9.        if(cls==null)    
  10.         throw new java.lang.IllegalArgumentException("参数不能为空!");   
  11.        ClassLoader loader=cls.getClassLoader();   
  12.        //获得类的全名,包括包名   
  13.        String clsName=cls.getName()+".class";   
  14.        //获得传入参数所在的包   
  15.        Package pack=cls.getPackage();   
  16.        String path="";   
  17.        //如果不是匿名包,将包名转化为路径   
  18.        if(pack!=null){   
  19.            String packName=pack.getName();   
  20.           //此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库   
  21.           if(packName.startsWith("java.")||packName.startsWith("javax."))    
  22.              throw new java.lang.IllegalArgumentException("不要传送系统类!");   
  23.            //在类的名称中,去掉包名的部分,获得类的文件名   
  24.            clsName=clsName.substring(packName.length()+1);   
  25.            //判定包名是否是简单包名,如果是,则直接将包名转换为路径,   
  26.            if(packName.indexOf(".")<0) path=packName+"/";   
  27.            else{//否则按照包名的组成部分,将包名转换为路径   
  28.                int start=0,end=0;   
  29.                end=packName.indexOf(".");   
  30.                while(end!=-1){   
  31.                    path=path+packName.substring(start,end)+"/";   
  32.                    start=end+1;   
  33.                    end=packName.indexOf(".",start);   
  34.                }   
  35.                path=path+packName.substring(start)+"/";   
  36.            }   
  37.        }   
  38.        //调用ClassLoader的getResource方法,传入包含路径信息的类文件名   
  39.        java.net.URL url =loader.getResource(path+clsName);   
  40.        //从URL对象中获取路径信息   
  41.        String realPath=url.getPath();   
  42.        //去掉路径信息中的协议名"file:"   
  43.        int pos=realPath.indexOf("file:");   
  44.        if(pos>-1) realPath=realPath.substring(pos+5);   
  45.        //去掉路径信息最后包含类文件信息的部分,得到类所在的路径   
  46.        pos=realPath.indexOf(path+clsName);   
  47.        realPath=realPath.substring(0,pos-1);   
  48.        //如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名   
  49.        if(realPath.endsWith("!"))   
  50.            realPath=realPath.substring(0,realPath.lastIndexOf("/"));   
  51.      /*------------------------------------------------------------  
  52.       ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径  
  53.        中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要  
  54.        的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的  
  55.        中文及空格路径  
  56.      -------------------------------------------------------------*/  
  57.      try{   
  58.        realPath=java.net.URLDecoder.decode(realPath,"utf-8");   
  59.       }catch(Exception e){throw new RuntimeException(e);}   
  60.       return realPath;   
  61.    }//getAppPath定义结束   
  62.   //-----------------------------------------------------------------  
[java]  view plain copy
  1. /**----------------------------------------------------------------------- 
  2.     *getAppPath需要一个当前程序使用的Java类的class属性参数,它可以返回打包过的 
  3.     *Java可执行文件(jar,war)所处的系统目录名或非打包Java程序所处的目录 
  4.     *@param cls为Class类型 
  5.     *@return 返回值为该类所在的Java程序运行的目录 
  6.     -------------------------------------------------------------------------*/  
  7.    public static String getAppPath(Class cls){  
  8.        //检查用户传入的参数是否为空  
  9.        if(cls==null)   
  10.         throw new java.lang.IllegalArgumentException("参数不能为空!");  
  11.        ClassLoader loader=cls.getClassLoader();  
  12.        //获得类的全名,包括包名  
  13.        String clsName=cls.getName()+".class";  
  14.        //获得传入参数所在的包  
  15.        Package pack=cls.getPackage();  
  16.        String path="";  
  17.        //如果不是匿名包,将包名转化为路径  
  18.        if(pack!=null){  
  19.            String packName=pack.getName();  
  20.           //此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库  
  21.           if(packName.startsWith("java.")||packName.startsWith("javax."))   
  22.              throw new java.lang.IllegalArgumentException("不要传送系统类!");  
  23.            //在类的名称中,去掉包名的部分,获得类的文件名  
  24.            clsName=clsName.substring(packName.length()+1);  
  25.            //判定包名是否是简单包名,如果是,则直接将包名转换为路径,  
  26.            if(packName.indexOf(".")<0) path=packName+"/";  
  27.            else{//否则按照包名的组成部分,将包名转换为路径  
  28.                int start=0,end=0;  
  29.                end=packName.indexOf(".");  
  30.                while(end!=-1){  
  31.                    path=path+packName.substring(start,end)+"/";  
  32.                    start=end+1;  
  33.                    end=packName.indexOf(".",start);  
  34.                }  
  35.                path=path+packName.substring(start)+"/";  
  36.            }  
  37.        }  
  38.        //调用ClassLoader的getResource方法,传入包含路径信息的类文件名  
  39.        java.net.URL url =loader.getResource(path+clsName);  
  40.        //从URL对象中获取路径信息  
  41.        String realPath=url.getPath();  
  42.        //去掉路径信息中的协议名"file:"  
  43.        int pos=realPath.indexOf("file:");  
  44.        if(pos>-1) realPath=realPath.substring(pos+5);  
  45.        //去掉路径信息最后包含类文件信息的部分,得到类所在的路径  
  46.        pos=realPath.indexOf(path+clsName);  
  47.        realPath=realPath.substring(0,pos-1);  
  48.        //如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名  
  49.        if(realPath.endsWith("!"))  
  50.            realPath=realPath.substring(0,realPath.lastIndexOf("/"));  
  51.      /*------------------------------------------------------------ 
  52.       ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径 
  53.        中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要 
  54.        的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的 
  55.        中文及空格路径 
  56.      -------------------------------------------------------------*/  
  57.      try{  
  58.        realPath=java.net.URLDecoder.decode(realPath,"utf-8");  
  59.       }catch(Exception e){throw new RuntimeException(e);}  
  60.       return realPath;  
  61.    }//getAppPath定义结束  
  62.   //-----------------------------------------------------------------  

 

 

该方法既可以用于JAR或WAR文件,也可以用于非JAR文件。但要注意以下2点: 

  1. 不要传递系统的类,作为getAppPath的参数,如java.lang.String.class,当然,也不要传递那些已经位于JDK中的那些类,比如xml相关的一些类等等。
  2. 要传递应该是程序中主要的运行类,不要传递程序中的支持类库中的类文件,也就是那些第三方的类库中的类文件,否则得到的将是那些类库的位置。

 

然后可以通过修改注册表来增加开机启动项:

转载:

需要修改的注册表项 
[HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Run]  开机自动运行程序
[HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/RunOnce] 开机自动运行程序 且 仅运行一次 
[HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/RunServices] 开机自动运行服务

JDK 从1.4开始提供操作 Windows 的 API 是 Preferences,因为这个 API 也是跨平台的,所功能比较弱,在 Win32 下只能用来操作 HKCU/Software/JavaSoft 和 HKLM/Software/JavaSoft 下及子节点的数据。

自由访问注册表其他键的值光用 Java 是做不到的,必然方案就是 JNI,这里我使用的是Windows Registry API Native Interface http://www.trustice.com/java/jnireg/index.shtml 下的 registry-3.1.3.zip(包含源代码)。可以利用它访问、修改、导出注册表项到文件等。解开 registry-3.1.3.zip,在 bin 目录中可以看到两个文件 ICE_JNIRegistry.dll 和 registry.jar,动态库就是本地代码实现。

com.ice.jni.registry.Registry.main() 就是 registry 的示例代码,动态库 ICE_JNIRegistry.dll 也是在这个类的静态块中被加载的,记得要把 ICE_JNIRegistry.dll 放在它能够被加载的位置上,比如你把 registry-3.1.3.zip 解压到 c:/registry-3.1.3,在命令行下你可以进入到这个目录中,并执行。

代码:

Java代码  复制代码
  1. package org.zh.ss.util;   
  2.   
  3. import com.ice.jni.registry.*;   
  4. import java.text.SimpleDateFormat;   
  5.   
  6. /** *//**  
  7.  * java 操作注册表   
  8.  * @author 李志远  
  9.  */  
  10. public class RegeditTool {   
  11.   
  12.     static SimpleDateFormat shortDateFormat = new SimpleDateFormat("yyyy-MM-dd");   
  13.   
  14.     /** *//** */  
  15.     /** *//** Creates a new instance of test */  
  16.   
  17.     // 把信息存储到注册表HKEY_LOCAL_MACHINE下的某个节点的某一变量中,有则修改,无则创建   
  18.     public static boolean setValue(String folder, String subKeyNode,   
  19.             String subKeyName, String subKeyValue) {   
  20.         try {   
  21.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE   
  22.                     .openSubKey(folder);   
  23.             RegistryKey subKey = software.createSubKey(subKeyNode, "");   
  24.             subKey   
  25.                     .setValue(new RegStringValue(subKey, subKeyName,   
  26.                             subKeyValue));   
  27.             subKey.closeKey();   
  28.             return true;   
  29.         } catch (NoSuchKeyException e) {   
  30.             e.printStackTrace();   
  31.         } catch (NoSuchValueException e) {   
  32.             e.printStackTrace();   
  33.         } catch (RegistryException e) {   
  34.             e.printStackTrace();   
  35.         }   
  36.         return false;   
  37.     }   
  38.   
  39.     // 删除注册表中某节点下的某个变量   
  40.     public static boolean deleteValue(String folder, String subKeyNode,   
  41.             String subKeyName) {   
  42.            
  43.         try {   
  44.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE   
  45.                     .openSubKey(folder);   
  46.             RegistryKey subKey = software.createSubKey(subKeyNode, "");   
  47.             subKey.deleteValue(subKeyName);   
  48.             subKey.closeKey();   
  49.             return true;   
  50.         } catch (NoSuchKeyException e) {   
  51.             System.out.println("NOsuchKey_delete");   
  52.         } catch (NoSuchValueException e) {   
  53.             System.out.println("NOsuchValue_delete");   
  54.         } catch (RegistryException e) {   
  55.             e.printStackTrace();   
  56.         }   
  57.         return false;   
  58.     }   
  59.   
  60.     // 删除注册表中某节点下的某节点   
  61.     public static boolean deleteSubKey(String folder, String subKeyNode) {   
  62.         try {   
  63.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE   
  64.                     .openSubKey(folder);   
  65.             software.deleteSubKey(subKeyNode);   
  66.             software.closeKey();   
  67.             return true;   
  68.         } catch (NoSuchKeyException e) {   
  69.             e.printStackTrace();   
  70.         } catch (RegistryException e) {   
  71.             e.printStackTrace();   
  72.         }   
  73.         return false;   
  74.     }   
  75.   
  76.     // 打开注册表项并读出相应的变量名的值   
  77.     public static String getValue(String folder, String subKeyNode,   
  78.             String subKeyName) {   
  79.         String value = "";   
  80.         try {   
  81.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE   
  82.                     .openSubKey(folder);   
  83.             RegistryKey subKey = software.openSubKey(subKeyNode);   
  84.             value = subKey.getStringValue(subKeyName);   
  85.             subKey.closeKey();   
  86.         } catch (NoSuchKeyException e) {   
  87.             value = "NoSuchKey";   
  88.             // e.printStackTrace();   
  89.         } catch (NoSuchValueException e) {   
  90.             value = "NoSuchValue";   
  91.             // e.printStackTrace();   
  92.         } catch (RegistryException e) {   
  93.             e.printStackTrace();   
  94.         }   
  95.         return value;   
  96.     }   
  97.   
  98.     // 测试   
  99.     public static void main(String[] args) {   
  100.         setValue("SOFTWARE""Microsoft//Windows//CurrentVersion//Run""test",   
  101.                 "C://1.exe");   
  102.     }   
  103. }  
[java]  view plain copy
  1. package org.zh.ss.util;  
  2.   
  3. import com.ice.jni.registry.*;  
  4. import java.text.SimpleDateFormat;  
  5.   
  6. /** *//** 
  7.  * java 操作注册表  
  8.  * @author 李志远 
  9.  */  
  10. public class RegeditTool {  
  11.   
  12.     static SimpleDateFormat shortDateFormat = new SimpleDateFormat("yyyy-MM-dd");  
  13.   
  14.     /** *//** */  
  15.     /** *//** Creates a new instance of test */  
  16.   
  17.     // 把信息存储到注册表HKEY_LOCAL_MACHINE下的某个节点的某一变量中,有则修改,无则创建  
  18.     public static boolean setValue(String folder, String subKeyNode,  
  19.             String subKeyName, String subKeyValue) {  
  20.         try {  
  21.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE  
  22.                     .openSubKey(folder);  
  23.             RegistryKey subKey = software.createSubKey(subKeyNode, "");  
  24.             subKey  
  25.                     .setValue(new RegStringValue(subKey, subKeyName,  
  26.                             subKeyValue));  
  27.             subKey.closeKey();  
  28.             return true;  
  29.         } catch (NoSuchKeyException e) {  
  30.             e.printStackTrace();  
  31.         } catch (NoSuchValueException e) {  
  32.             e.printStackTrace();  
  33.         } catch (RegistryException e) {  
  34.             e.printStackTrace();  
  35.         }  
  36.         return false;  
  37.     }  
  38.   
  39.     // 删除注册表中某节点下的某个变量  
  40.     public static boolean deleteValue(String folder, String subKeyNode,  
  41.             String subKeyName) {  
  42.           
  43.         try {  
  44.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE  
  45.                     .openSubKey(folder);  
  46.             RegistryKey subKey = software.createSubKey(subKeyNode, "");  
  47.             subKey.deleteValue(subKeyName);  
  48.             subKey.closeKey();  
  49.             return true;  
  50.         } catch (NoSuchKeyException e) {  
  51.             System.out.println("NOsuchKey_delete");  
  52.         } catch (NoSuchValueException e) {  
  53.             System.out.println("NOsuchValue_delete");  
  54.         } catch (RegistryException e) {  
  55.             e.printStackTrace();  
  56.         }  
  57.         return false;  
  58.     }  
  59.   
  60.     // 删除注册表中某节点下的某节点  
  61.     public static boolean deleteSubKey(String folder, String subKeyNode) {  
  62.         try {  
  63.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE  
  64.                     .openSubKey(folder);  
  65.             software.deleteSubKey(subKeyNode);  
  66.             software.closeKey();  
  67.             return true;  
  68.         } catch (NoSuchKeyException e) {  
  69.             e.printStackTrace();  
  70.         } catch (RegistryException e) {  
  71.             e.printStackTrace();  
  72.         }  
  73.         return false;  
  74.     }  
  75.   
  76.     // 打开注册表项并读出相应的变量名的值  
  77.     public static String getValue(String folder, String subKeyNode,  
  78.             String subKeyName) {  
  79.         String value = "";  
  80.         try {  
  81.             RegistryKey software = Registry.HKEY_LOCAL_MACHINE  
  82.                     .openSubKey(folder);  
  83.             RegistryKey subKey = software.openSubKey(subKeyNode);  
  84.             value = subKey.getStringValue(subKeyName);  
  85.             subKey.closeKey();  
  86.         } catch (NoSuchKeyException e) {  
  87.             value = "NoSuchKey";  
  88.             // e.printStackTrace();  
  89.         } catch (NoSuchValueException e) {  
  90.             value = "NoSuchValue";  
  91.             // e.printStackTrace();  
  92.         } catch (RegistryException e) {  
  93.             e.printStackTrace();  
  94.         }  
  95.         return value;  
  96.     }  
  97.   
  98.     // 测试  
  99.     public static void main(String[] args) {  
  100.         setValue("SOFTWARE""Microsoft//Windows//CurrentVersion//Run""test",  
  101.                 "C://1.exe");  
  102.     }  
  103. }  

 

### 回答1: 如果你想在 macOS 上使用 Java 实现应用程序开机自启动,你需要做以下步骤: 1. 首先,你需要确保你的计算机上已经安装了 Java 环境,并且你已经编写好了你要自动启动的 Java 程序。 2. 然后,你需要打开 macOS 的「用户与群组」设置,选择「登录项」标签。 3. 在「登录项」标签中,你可以看到「自动启动程序」列表,点击「+」号按钮,选择你要自动启动的 Java 程序的执行文件。 4. 最后,你需要将你的 Java 程序加入「自动启动程序」列表中,这样它就会在你的计算机开机时自动启动。 注意:如果你的 Java 程序是由可执行的 JAR 文件生成的,你可能需要在执行文件前面加上 "java -jar" 命令,才能让系统正确地启动你的程序。 ### 回答2: 在macOS中,我们可以使用Java编写一个应用程序,并实现开机自启动的功能。下面是使用Java实现应用程序开机自启动的步骤: 步骤1:创建一个Java应用程序。可以使用Java开发工具,如Eclipse或IntelliJ IDEA,创建一个新的Java项目。在项目中编写我们的应用程序代码。 步骤2:创建一个启动脚本。在macOS中,我们可以使用shell脚本来启动我们的Java应用程序。创建一个文本文件,将以下内容复制粘贴到文件中: ``` #!/bin/sh java -jar /path/to/your/java/application.jar ``` 将`/path/to/your/java/application.jar`替换为你的Java应用程序的路径。 步骤3:将启动脚本添加到用户的登录项中。打开“系统偏好设置” -> “用户与群组” -> “登录项”,将启动脚本拖放到列表中。 步骤4:设置脚本的可执行权限。在终端中,使用以下命令修改脚本的权限: ``` chmod +x /path/to/your/startup/script.sh ``` 将`/path/to/your/startup/script.sh`替换为你的启动脚本的路径。 现在,当你的macOS启动时,你的Java应用程序将自动启动。 需要注意的是,以上步骤仅适用于当前登录的用户。如果你希望所有用户都能够启动应用程序,可以将启动脚本添加到“/Library/LaunchAgents”目录下。 ### 回答3: 要实现 macOS 上的应用程序开机自启动,可以使用Java编写一个小型的启动器程序来实现。 首先,需要创建一个启动器程序,它可以在系统启动时自动运行,并负责启动您的Java应用程序。这个启动器程序可以是一个独立的Java应用程序,可以在系统启动时由操作系统自动运行,或者可以将其作为系统服务运行。 为了实现启动器程序,在Java中可以使用`java.awt.Desktop`类来打开指定的应用程序。可以在启动器程序中使用以下代码来启动您的Java应用程序: ``` import java.awt.Desktop; import java.io.File; import java.io.IOException; public class Launcher { public static void main(String[] args) throws IOException { String appPath = "/Applications/YourApp.app"; // 替换为您的应用程序的路径 File appFile = new File(appPath); if (Desktop.isDesktopSupported()) { Desktop.getDesktop().open(appFile); } } } ``` 请注意,您需要将路径`/Applications/YourApp.app`替换为您的应用程序的准确路径。确保路径是指向您的应用程序的实际位置。 然后,将编译后的启动器程序与您的应用程序一起打包,并将启动器程序添加到您的macOS用户登录项中。这样,当用户登录时,启动器程序将自动运行,并启动您的Java应用程序。 要将启动器程序添加到登录项中,您可以打开“系统偏好设置”,然后选择“用户与群组”。在用户偏好设置中的“登录项”选项中,可以将启动器程序拖动到该列表中,从而实现开机自启动。 这样,在macOS启动时,启动器程序将自动运行,并启动您的Java应用程序,实现应用程序开机自启动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值