刚写的一个自动编译、混淆、打包jar的代码,做个记录
用到的NuGet:
<?xml version="1.0" encoding="utf-8"?>
<packages><package id="DotNetZip" version="1.10.1" targetFramework="net45" /><package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
</packages>
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ApiCloudModulePackage
{class Program{static string tempPath;static ToolConfig toolConfig;static void Main(string[] args){tempPath = Path.GetTempPath() + Guid.NewGuid().ToString("N") + "\\";if (Directory.Exists(tempPath) == false){Directory.CreateDirectory(tempPath);}toolConfig = Newtonsoft.Json.JsonConvert.DeserializeObject<ToolConfig>( File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "projects.json") );try{foreach (ProjectConfig project in toolConfig.projects){//compile jarjarProject(project);}Console.Write("需要现在生成模块的zip文件吗?[y/n]:");while(true){var keyResult = Console.ReadKey();if (keyResult.Key == ConsoleKey.Y){ Console.WriteLine("\r\n");//make zip file from module folderforeach (var moduleFolder in toolConfig.modules){makeZip(getPathFromConfig(moduleFolder));Console.WriteLine("打包输出:" + moduleFolder + ".zip");}break;}else if (keyResult.Key == ConsoleKey.N){Process.GetCurrentProcess().Kill();}}Console.WriteLine("打包完成! 按任意键退出");}catch(Exception ex){Console.WriteLine(ex.Message);}try{Directory.Delete(tempPath, true);}catch{}Console.ReadKey();}static void makeZip(string folder){string zipfilepath = Path.GetDirectoryName(folder) + "\\" + Path.GetFileName(folder) + ".zip";if (File.Exists(zipfilepath))File.Delete(zipfilepath);using (ZipFile zip = new ZipFile(zipfilepath)){string root = Path.GetFileName(folder);zip.AddDirectoryByName(root);zip.AddDirectory(folder , root);zip.Save();}}static void jarProject(ProjectConfig project){Console.WriteLine("正在编译" + project.sourceFolder);string srcPath = getPathFromConfig(project.sourceFolder);//create temp folderstring tempFolder = tempPath + Guid.NewGuid().ToString("N") + "\\";string classTempFolder = tempFolder + Guid.NewGuid().ToString("N") + "\\";string jarDstFolder = tempFolder + "jar\\";string proguardFolder = tempFolder + "jar\\";if (Directory.Exists(jarDstFolder) == false){Directory.CreateDirectory(jarDstFolder);}if (Directory.Exists(classTempFolder) == false){Directory.CreateDirectory(classTempFolder);}List<string> javaFiles = new List<string>();getFiles(javaFiles, srcPath , "*.java");//copy java files to temp folderstring encoding = null;foreach( string javafile in javaFiles ){if(encoding == null){var encode = GetFileEncodeType(javafile);if(encode == System.Text.Encoding.UTF8){encoding = "utf-8";}else{encoding = "GBK";}}File.Copy(javafile, tempFolder + Path.GetFileName(javafile) , true);}StringBuilder libJars = new StringBuilder();StringBuilder proguardJars = new StringBuilder();if (!string.IsNullOrEmpty(project.libPath)){List<string> jarList = new List<string>();Program.getFiles(jarList, Program.getPathFromConfig(project.libPath), "*.jar");if (jarList.Count > 0){libJars.Append(" -cp ");foreach (string jarfile in jarList){libJars.Append('"');libJars.Append(jarfile);libJars.Append('"');libJars.Append(';');proguardJars.Append(" -libraryjars ");proguardJars.Append('"');proguardJars.Append(jarfile);proguardJars.Append('"');}}}ProcessStartInfo proStartInfo = new ProcessStartInfo("javac");// -source 1.6 -target 1.6 表示按照jdk1.6标准编译,默认是1.8,太高了,eclipse使用时会出错,因为eclipse项目里面设置的是1.6proStartInfo.Arguments = $"-Xlint:unchecked -Xlint:deprecation -source 1.6 -target 1.6 -encoding {encoding} -bootclasspath {AppDomain.CurrentDomain.BaseDirectory}android.jar {libJars} -d {classTempFolder} {tempFolder}*.java";proStartInfo.UseShellExecute = false;Process process = Process.Start(proStartInfo);process.WaitForExit();if(true){//build jar, jar file actually is zip fileusing (ZipFile zip = new ZipFile($"{jarDstFolder}result.jar")){zip.AddDirectory(classTempFolder);var content = @"Manifest-Version: 1.0
Created-By: 1.8.0_40 (Oracle Corporation)";byte[] bs = System.Text.Encoding.UTF8.GetBytes(content);zip.AddEntry("META-INF/MANIFEST.MF", bs);zip.Save();}}else{这里是利用jar程序生成jar文件//List<string> classFiles = new List<string>();//getFiles(classFiles, tempFolder, "*.class");//foreach (string classfile in classFiles)//{// File.Copy(classfile, jarDstFolder + Path.GetFileName(classfile), true);//}//proStartInfo = new ProcessStartInfo("jar");//proStartInfo.Arguments = $"cvf {jarDstFolder}result.jar {jarDstFolder}*.class";//proStartInfo.UseShellExecute = false;//process = Process.Start(proStartInfo);//process.WaitForExit();}if(!string.IsNullOrEmpty(project.proguardConfigFile)){Console.WriteLine("正在混淆代码...");process = Process.Start(new ProcessStartInfo("java"){Arguments = $"-jar proguard.jar @{project.proguardConfigFile} -injars {proguardFolder}result.jar -outjars {proguardFolder}result2.jar -libraryjars android.jar {proguardJars}",UseShellExecute = false});process.WaitForExit();if (!File.Exists(string.Format("{0}result2.jar", proguardFolder))){throw new Exception(project.sourceFolder + "代码混淆出错");}File.Delete( $"{proguardFolder}result.jar");File.Move($"{proguardFolder}result2.jar", $"{proguardFolder}result.jar");}if (File.Exists($"{jarDstFolder}result.jar") == false)throw new Exception("编译"+ project.sourceFolder +"失败!");//copy jar to destinationforeach ( var dstpath in project.buildDestinations ){string destination = getPathFromConfig(dstpath);File.Copy($"{jarDstFolder}result.jar", destination, true);Console.WriteLine($"Maked {destination}");}}static System.Text.Encoding GetFileEncodeType(string filename){using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read)){System.IO.BinaryReader br = new System.IO.BinaryReader(fs);Byte[] buffer = br.ReadBytes(2);if (buffer[0] >= 0xEF){if (buffer[0] == 0xEF && buffer[1] == 0xBB){return System.Text.Encoding.UTF8;}else if (buffer[0] == 0xFE && buffer[1] == 0xFF){return System.Text.Encoding.BigEndianUnicode;}else if (buffer[0] == 0xFF && buffer[1] == 0xFE){return System.Text.Encoding.Unicode;}else{return System.Text.Encoding.Default;}}else{return System.Text.Encoding.Default;}}}static string getPathFromConfig(string path){if (path[1] == ':')return path.Replace("/", "\\");else{return AppDomain.CurrentDomain.BaseDirectory + path.Replace("/", "\\");}}static void getFiles(List<string> result, string folder , string pattern){var files = Directory.GetFiles(folder, pattern);result.AddRange(files);var dirs = Directory.GetDirectories(folder);foreach( var dir in dirs ){getFiles(result, dir , pattern);}}}
}