经过测试,发现了些问题,修改下代码。
声明:
本篇文章主要记录如何使用 Java查询Windows电脑的进程,并解析结果,显示于浏览器上。
使用SpringBoot没有写前端框架,简单的生成一个Table显示在浏览器上。后续有空,就写个前端,使用仪表盘显示。
内容:
代码主要使用了dos的几个命令:
查找进程列表命令:tasklist
根据pid删除进程命令:tasklist /f /pid 123456
查询当前系统的内存命令:wmic ComputerSystem get TotalPhysicalMemory
代码:
查询进程代码:
public static List<List<String>> taskList(){
try{
Process p = Runtime.getRuntime().exec("taskList");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(),"gbk"));
List<String> keys = new ArrayList<>();
List<String> values = new ArrayList<>();
String line = "";
int i = 0;
Pattern titlePattern = Pattern.compile("[\u4e00-\u9fa5|a-zA-Z0-9]*");
List<Integer> list = new ArrayList<>();
while((line = br.readLine())!=null){
if("".equals(line))
continue;;
if(i==0){
Matcher m = titlePattern.matcher(line);
while(m.find()){
String group = m.group(0);
if("".equals(group))
continue;
keys.add(group);
}
}else if(i>1){
values.add(line);
}else{
int k = 0;
list.add(0,0);
for(int j=0;j<line.length();j++){
if(line.charAt(j)=='='){
list.set(k,list.get(k)+1);
}else{
k++;
list.add(k,0);
}
}
}
i++;
}
List<String> parseValues = new ArrayList<>();
for (String value : values) {
int start = 0;
int l = 0;
for (int k : list) {
int n = 0;
if(value.endsWith("暂缺") && l == 4)
n = 2;
//这若是含有暂缺两字,就会出现问题,比其他的少了两个字符。所以会出现数组越界。
String v = value.substring(start, start + k);
if(v.endsWith("K")){
String memory = v.replaceAll(",", "").replaceAll("K", "").trim();
v = Integer.parseInt(memory)/1024 + "MB";
}
parseValues.add(v);
start = start + k + 1;
l++;
}
}
int start = 0 ,end = parseValues.size();
int le = keys.size();
List<List<String>> rtnl = new ArrayList<>();
while(end>0){
List<String> s = parseValues.subList(start,start + le);
rtnl.add(s);
start = start + le;
end-=le;
}
rtnl.sort(new MemorySortCompare());
rtnl.set(0,keys);
return rtnl;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
根据命令查询出内容,再针对内容进行解析,将每个每列进行匹配。
分为了标题与数据两块,并根据占用内存进行倒序排列,代码如下:
static class MemorySortCompare implements Comparator{
@Override
public int compare(Object o1, Object o2) {
List<String> l = (List<String>)o1;
List<String> l1 = (List<String>)o2;
String s = l.get(4);
String s1 = l1.get(4);
//2021年2月12日修改;
//同样的,将含有暂缺的数据都放到最后
if("暂缺".equals(s))
s = "-1";
if("暂缺".equals(s1))
s1 = "-1";
String s2 = s.replaceAll(",",
"").replaceAll("MB", "").trim();
String s3 = s1.replaceAll(",", "").replaceAll("MB", "").trim();
int m = Integer.parseInt(s2);
int m1 = Integer.parseInt(s3);
return Integer.compare(m1, m);
}
}
查询内存代码:
public static String showMemory(){
String exec = "wmic ComputerSystem get TotalPhysicalMemory";
try{
Process p = Runtime.getRuntime().exec(exec);
Scanner scanner = new Scanner(p.getInputStream(),"gbk");
int i = 0;
String memorys= "";
Pattern pattern = Pattern.compile("[0-9]*");
while(scanner.hasNextLine()){
memorys = scanner.nextLine().trim();
if(memorys.length() > 0 && pattern.matcher(memorys).matches())
break;
i++;
}
return memorys;
}catch(Exception e){
e.printStackTrace();
}
return "";
}
因为改代码查出来后数据规则不统一,只能根据不同的逻辑进行匹配。
主要为了获取内存,所以正则匹配0-9就行了。
关闭进程代码:
@RequestMapping("/close")
public String close(HttpServletRequest request){
String pid = request.getParameter("PID");
try{
Runtime.getRuntime().exec("taskkill /f /pid "+pid);
}catch(Exception e){
e.printStackTrace();
}
return "已成功终止PID为"+pid+"的进程!";
}
访问当前进程接口后,会将数据绘制成表格,然后点击关闭进程按钮,就可以根据PID关闭进程。
绘制表格代码:
public static String processRender(List<List<String>> l){
if(l.isEmpty())
return null;
String table = "<table>";
String memory = TaskList.showMemory();
double d = Double.parseDouble(memory);
d = d/1024/1024/1024;
DecimalFormat df = new DecimalFormat("0.00");//格式化小数
table += "<tr><td>当前电脑的内存为:"+df.format(d)+"G</td></tr>";
String headTr = "<tr>";
List<String> heads = l.get(0);
StringBuilder headTd = new StringBuilder();
for (String s : heads) {
headTd.append("<td>").append(s).append("</td>");
}
headTd.append("<td>占用率</td>");
headTd.append("<td>操作</td>");
headTr += headTd+"</tr>";
StringBuilder tr = new StringBuilder();
for (int i=1;i<l.size();i++) {
List<String> ls = l.get(i);
StringBuilder td = new StringBuilder();
String pid = "";
String curMemory = "";
int k = 0;
for (String s : ls) {
td.append("<td>").append(s).append("</td>");
if(k==1){
pid = s;
}
if(k==4)
curMemory = s;
k++;
}
curMemory = curMemory.replace("MB", "");
double d1 = d*1024;
Matcher m = PatternUtil.matchChinese(curMemory, "[\u4e00-\u9fa5]");
if(!m.find()){
td.append("<td>").append(df.format(((Double.parseDouble(curMemory))/d1)*100)).append("%</td>");
}else{
td.append("<td>0.00%</td>");
}
td.append("<td>").append("<a target='_blank' href='/close?PID=").append(pid).append("'>关闭进程</a>").append("</td>");
tr.append("<tr>").append(td).append("</tr>");
}
table+=headTr;
table+=tr;
table += "</table>";
return table;
}
同时显示了内存以及计算每个进程所占用内存的占用率。
点击关闭进程后就会跳转到另一个页面(现在懒得写那么多前端)
这样QQ.exe就被关闭了。