[原创]自定义参数静默方式安装JDK1.8

摘要:当Java桌面程序开发完成做产品的时候,面对未知的安装环境,通常是编写一些预安装检测脚本/程序,让程序傻瓜化安装以便减少分发出去的产品带来

的未知工作量(安装答疑,操作系统问题引起安装失败等),当然你也可以把安装过程中出现的问题写入文档手册。本文写作的背景是

1.不想让客户知道产品是用Java编写的 

2. 客户懒的帮助文档都不想看

  截至本文编写的时候,JDK官方最新版本为jdk 8u144,本文测试环境在虚拟机Windows XP,使用的版本为jdk-8u144-windows-i586.exe

       Java 安装是使用 Microsoft Window Installer (MSI) 2.0 技术构建的。MSI 包含对静默或无人参与安装的内置支持。

  从Google搜索"java silent install"总结出了一些安装参数  

 /lang=<语言代码> 安装特定语言包

  支持的语言包如下

 

语言  语言代码
英语 (en)1033
法语 (fr)1036            
德语 (de)1031
意大利语 (it)1040
日语 (ja)1041
韩语 (ko)1042
西班牙语 (es)1034
瑞典语 (sv)1053
简体中文 (zh)2052
繁体中文 (zh_TW)1028

经过笔者实测,设置语言代码为1041,即日语。安装命令:

jdk-8u144-windows-i586.exe /lang=1041

安装包界面如下

做对日外包的同学应该习惯于看到这个界面。这样就以日语语言环境安装JDK了。

WEB_JAVA = 1|0 Java浏览器支持 1启用 0禁用
IEXPLORER = 1|0 IE浏览器支持 1启用 0 禁用(jdk1.8命令行实测无效)
SPONSORS= 1|0 绕过赞助商,如浏览器插件,实测发现完整安装了JDK
WEB_JAVA_SECURITY_LEVEL = VH|H|M|L 浏览器中运行的未签名 Java 应用程序的安全级别 非常高|高|中|低
AUTO_UPDATE= 1|0 JDK自动检测更新 1启用 0禁用
NOSTARTMENU= 1|0 创建开始菜单 1禁用 0 启动

当然你也可以安装后在控制面板找到Java设置安全级别

以上为JDK 7u10 release版本起的安装特性,Java早期的时候有一些应用就是通过Web Applet方式发布的,笔者工作早些年的时候一

家做ERP的单位他就是通过浏览器方式发布项目的,现今已经很少看到这样的企业应用,鲜见一些社区里的Demo程序会有Web Applet的示例程序。

 

/L install.log 记录安装日志

常规情况下Oracle公司已经帮我考虑到安装过程中遇到的问题,并且他也有自己的解决方法,这些都封装在安装包里,当然有时候如果需要查看java安装过程的操作,

或者在特殊情况下(静默安装)他都做了什么,或者是为了排错,我们需要记录日志。/L参数便应运而生。

/s 静默安装

此参数不需要赋值,直接带入安装命令行即可,启动后将在后台默默的安装直至安装完成结束。

ADDLOCAL = [[ToolsFeature],[SourceFeature],[PublicjreFeature]] 选择附加组件包各个参数可独立使用也可以组合使用
ADDLOCAL = ["ToolsFeature,SourceFeature,PublicjreFeature"] 安装开发工具/源代码/JRE
ADDLOCAL = ["ToolsFeature,SourceFeature"] 安装开发工具和源代码

 除了以上命令还有很多配置方式或者参数,笔者没有一一测试,笔者最终的安装命令如下:

jdk-8u144-windows-i586.exe /lang=2052 /s /L c:\jdk-install.log INSTALLDIR=c:\embededJDK1.8 ADDLOCAL="ToolsFeature,SourceFeature" WEB_JAVA=0 AUTO_UPDATE=0 NOSTARTMENU=1

命令解释:笔者选择了简体中文静默安装,记录了安装日志到c:\jdk-install.log,JDK安装目录c:\\embededJDK1.8,另外还安装了开发工具和源代码组件包,禁用浏览Java插件,关闭JAVA自动更新,屏蔽了java开始菜单的创建。

安装后效果图如下:

 

从IE浏览器“工具”--"管理加载项"找不到java浏览器插件

开始菜单也没了Java的踪迹

windows注册表启动项也没有java的影子

 

 

 当然文字不是到这里就结束了。

本文最终目的是要发送福利,在下面,笔者用C#写了简单的程序来静默安装JDK。

首先从java官方获得JDK的x86和x64版本分别改名为sdk-x86.bin和sdk-x64.bin

下面奉上代码(考虑客户端实际安装环境,为兼容Windows XP SP及更高版本,代码采用C#2.0 .NET Framework 2.0)

using System;
using System.IO;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Threading;

namespace Starter
{
    class Enterance
    {
        static string JVM_Pattern = string.Empty;
        static bool hasFoundJVM = false;
        static string Target_JDK_FIlE = string.Empty;
        public static void Main(string[] args)
        {
            
            Console.WriteLine("按任意键开始安装xxx综合平台...");
            Console.ReadKey(true);
            Console.Clear();
            
            if(isFileMissed())
            {
                Console.WriteLine("安装文件丢失请联系技术人员");
            }else{                
                doPreInstallCheck();
                if(hasFoundJVM){
                    installJVM(Target_JDK_FIlE);
                }
            }
            
            Console.ReadKey(true);
        }
        
        /// <summary>
        /// 判断主安装程序是否丢失
        /// </summary>
        /// <returns></returns>
        static bool isFileMissed()
        {        
            return !File.Exists("setup.exe");
        }
        
        static String getArch()
        {
             return System.Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE", 
                                                             EnvironmentVariableTarget.Machine);
        }
        
        /// <summary>
        /// 安装预检测
        /// </summary>
        static void doPreInstallCheck(){
            String arch =getArch();
            Architecture type= (Architecture)Enum.Parse(typeof(Architecture),arch);            
            switch(type){
                case Architecture.AMD64:
                case Architecture.IA64:
                case Architecture.x64:
                        Console.WriteLine("发现{0}",EnumUtil.GetEnumDescription(type));
                        JVM_Pattern = "sdk.*x64.*";
                    break;
                case Architecture.x86:
                    Console.WriteLine("发现{0}",EnumUtil.GetEnumDescription(type));
                    JVM_Pattern = "sdk.*x86.*";
                    break;
            }
            string []files = Directory.GetFiles(Environment.CurrentDirectory,"sdk-*.bin");                
            Action<string> action = new Action<string>(matchJVM);
            Array.ForEach(files, action);            
        }
        
         private static void matchJVM(string jdkfile)
        {
             FileInfo fileInfo = new FileInfo(jdkfile);
             bool isMatched = Regex.IsMatch(fileInfo.Name,JVM_Pattern);
             if(isMatched) {
                 hasFoundJVM = true;
                 Target_JDK_FIlE = jdkfile;
             }
             if(Debugger.IsAttached)
                 Console.WriteLine("{0}与当前操作系统匹配的JVM:{1}",fileInfo.Name,isMatched);
        }        
        
        /// <summary>
        /// 安装JVM
        /// </summary>
        /// <param name="fileName">JDK文件名</param>
        static void installJVM(String fileName)
        {
            Console.WriteLine("即将安装程序,等待时间取决你电脑的性能");
            //https://stackoverflow.com/questions/3360555/how-to-pass-parameters-to-threadstart-method-in-thread
            Thread thread =new Thread(new ParameterizedThreadStart(DoSlientInstall));
            thread.Start(fileName);
            Thread.Sleep(5000);//等待安装进程启动
            FileInfo fileInfo = new FileInfo(fileName);
            InstallState state =new InstallState();
            state.processName =fileInfo.Name;
            
            
            Timer timer =new Timer(waitForProcessExitCallBack,state,0,1000);                
            state.tmr = timer;
        
        }
        
        public static void waitForProcessExitCallBack(object target){
            InstallState state = target as InstallState;
            Timer timer = state.tmr;
            Process []allProcceses = Process.GetProcesses();
            bool isJDKProcExit  = true;            
            foreach(Process proc in allProcceses)
            {
                string procName = String.Format("{0}",proc.ProcessName);                
                if(Debugger.IsAttached)
                    Console.WriteLine("{0},{1}, {2}",procName,state.processName,procName.Equals(state.processName));
                if(procName.Equals(state.processName)){                                                    
                    isJDKProcExit = false;
                }                                
            }
            if(isJDKProcExit){
                Console.WriteLine("\r\n安装所需软件使用时间:{0}秒",state.counter);
                timer.Dispose();
            }else{
                Console.Write(state.delims);
                state.counter++;                            
                //Thread.Sleep(1000);
                //
                //timer.Change(1000,1000);
                //timer.Dispose();
            }            
    
        }
        
        //https://stackoverflow.com/questions/24918768/progress-bar-in-console-application

        //https://stackoverflow.com/questions/12354883/how-do-i-gracefully-stop-a-system-threading-timer
        static void DoSlientInstall(object fileName)
        {
            Console.WriteLine("安装进行中,请勿退出...");
            ProcessStartInfo pStartInfo = new ProcessStartInfo();
            pStartInfo.FileName = (String)fileName;
            pStartInfo.Verb = "runas";
            pStartInfo.Arguments = "/lang=2052 /s /L c:\\jdk-install.log INSTALLDIR=c:\\embededJDK1.8 ADDLOCAL=\"ToolsFeature,SourceFeature\" WEB_JAVA=0 AUTO_UPDATE=0 NOSTARTMENU=1";
            pStartInfo.UseShellExecute = false;            
            System.Diagnostics.Process.Start(pStartInfo);
            //https://stackoverflow.com/questions/6050478/how-do-i-create-edit-a-manifest-file
            //System.Diagnostics.Process.Start((String)fileName,"/s");
        }
    }
    //http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Threading/Timer.html
    class InstallState{
        /// <summary>
        /// 时间计数器
        /// </summary>
         public int counter = 0;
         /// <summary>
         /// 进程名
         /// </summary>
         public String processName;
         /// <summary>
         /// 分隔符
         /// </summary>
         public string delims="*";

         public Timer tmr;
    }
}
using System;
using System.ComponentModel;
using System.Reflection;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data;

namespace Starter
{
    /// <summary>
    /// 操作系统架构枚举类
    /// </summary>
    //https://msdn.microsoft.com/en-us/library/aa384274.aspx
    //https://ss64.com/nt/syntax-64bit.html
    public enum Architecture{        
        [Description("64位操作系统")]
        x64 =0,
        [Description("AMD 64位操作系统")]
        AMD64=1,
        [Description("Intel64位操作系统")]
        IA64=2,
        [Description("x86架构操作系统")]
        x86=3
    }
    class EnumUtil{
        public static string GetEnumDescription(Enum enumValue)
        {
            string enumValueAsString = enumValue.ToString();
        
            Type type = enumValue.GetType();
            FieldInfo fieldInfo = type.GetField(enumValueAsString);
            object[] attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
        
            if (attributes.Length > 0)
            {
                DescriptionAttribute attribute = (DescriptionAttribute)attributes[0];
                return attribute.Description;
            }
        
            return enumValueAsString;
        }
    }
}

安装效果图

 

参考资料

Installing With a Configuration File

Java 8 SE Documentation

How do I arrange a silent (unattended) Java installation?

Language IDs

Installing the JDK Silently

转载于:https://www.cnblogs.com/passedbylove/p/7426275.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值