折腾笔记[33]-使用uiautomation自动重复读取图片(被控程序为.net框架)

news/2025/10/22 21:14:21/文章来源:https://www.cnblogs.com/qsbye/p/19158988

摘要

基于python使用uiautomation自动操作.net程序.读取目录中png以及查找与其对应的json数据输入软件和点击按钮.

实现

1. 简化版的被控程序(靶点窗口)

配置文件:

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net8.0-windows</TargetFramework><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings><UseWPF>true</UseWPF></PropertyGroup><ItemGroup><PackageReference Include="TZ.HMI.Common.UI" Version="1.0.0.1" /></ItemGroup><ItemGroup><None Update="处理中.png"><CopyToOutputDirectory>Always</CopyToOutputDirectory></None></ItemGroup></Project><?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><PropertyGroup /><ItemGroup><ApplicationDefinition Update="App.xaml"><SubType>Designer</SubType></ApplicationDefinition></ItemGroup><ItemGroup><Compile Update="JsonImportWindow.xaml.cs"><SubType>Code</SubType></Compile></ItemGroup><ItemGroup><Page Update="JsonImportWindow.xaml"><SubType>Designer</SubType></Page><Page Update="MainWindow.xaml"><SubType>Designer</SubType></Page></ItemGroup>
</Project>

界面:

<Window x:Class="MockWpf.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="OCR自动核对" Height="450" Width="800"><Grid><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/></Grid.RowDefinitions><!-- 顶部按钮区域 --><StackPanel Orientation="Horizontal" Grid.Row="0" Margin="10" HorizontalAlignment="Left"><Button Name="btnLoadImage" Content="读取图片" Width="100" Height="30" Margin="5"/><Button Name="btnOpenFolder" Content="打开文件夹" Width="100" Height="30" Margin="5"/><Button Name="btnPrevImage" Content="上一张" Width="100" Height="30" Margin="5"/><Button Name="btnNextImage" Content="下一张" Width="100" Height="30" Margin="5"/><Button Name="btnDebug" Content="调试" Width="100" Height="30" Margin="5"/><Button Name="btnMesImport" Content="Mes导入" Width="100" Height="30" Margin="5"/></StackPanel><!-- 图片显示区域 --><Image Name="imgDisplay" Grid.Row="1" Margin="10" Stretch="Uniform"/></Grid>
</Window><Window x:Class="MockWpf.JsonImportWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Json导入" Height="300" Width="500"WindowStartupLocation="CenterOwner"><Grid Margin="10"><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><TextBox x:Name="txtJson"Grid.Row="0"TextWrapping="Wrap"AcceptsReturn="True"ScrollViewer.HorizontalScrollBarVisibility="Auto"ScrollViewer.VerticalScrollBarVisibility="Auto"FontFamily="Consolas"/><Button x:Name="btnOk"Grid.Row="1"Content="确认"Width="80" Height="28"HorizontalAlignment="Right"Margin="0,10,0,0"Click="BtnOk_Click"/></Grid>
</Window>

代码:

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Media.Imaging;namespace MockWpf
{public partial class MainWindow : Window{private List<string> imageFiles = new List<string>();private int currentIndex = -1;public MainWindow(){InitializeComponent();btnOpenFolder.Click += BtnOpenFolder_Click;btnLoadImage.Click += BtnLoadImage_Click;btnPrevImage.Click += BtnPrevImage_Click;btnNextImage.Click += BtnNextImage_Click;btnDebug.Click += BtnDebug_Click;btnMesImport.Click += BtnMesImport_Click;}private void BtnMesImport_Click(object sender, RoutedEventArgs e){var w = new JsonImportWindow { Owner = this };if (w.ShowDialog() == true)          // 用户点了“确认”{string json = w.JsonText;// TODO: 在这里写真正的 Json 解析/导入逻辑// MessageBox.Show($"已获取到 Json 内容(长度 {json.Length})\n{json}");}}private void BtnDebug_Click(object sender, RoutedEventArgs e){// 新窗口var win = new Window{Owner = this,Width = 600,Height = 400,WindowStartupLocation = WindowStartupLocation.CenterOwner,WindowStyle = WindowStyle.ToolWindow,ResizeMode = ResizeMode.NoResize,Title = "提示"};// 图片控件var img = new System.Windows.Controls.Image{Stretch = System.Windows.Media.Stretch.Uniform};try{img.Source = new BitmapImage(new Uri("./处理中.png", UriKind.Relative));}catch { /* 图片不存在则留空 */ }win.Content = img;win.Show();// 3 秒后自动关闭var timer = new System.Windows.Threading.DispatcherTimer{Interval = TimeSpan.FromSeconds(3)};timer.Tick += (_, __) =>{timer.Stop();win.Close();};timer.Start();}private void BtnOpenFolder_Click(object sender, RoutedEventArgs e){var dialog = new System.Windows.Forms.FolderBrowserDialog();if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK){var folderPath = dialog.SelectedPath;imageFiles = new List<string>(Directory.GetFiles(folderPath, "*.jpg"));imageFiles.AddRange(Directory.GetFiles(folderPath, "*.png"));imageFiles.AddRange(Directory.GetFiles(folderPath, "*.bmp"));if (imageFiles.Count > 0){currentIndex = 0;LoadImage(imageFiles[currentIndex]);}else{MessageBox.Show("未找到图片文件");}}}private void BtnLoadImage_Click(object sender, RoutedEventArgs e){OpenFileDialog openFileDialog = new OpenFileDialog{Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp",Title = "选择图片"};if (openFileDialog.ShowDialog() == true){LoadImage(openFileDialog.FileName);}}private void BtnPrevImage_Click(object sender, RoutedEventArgs e){if (imageFiles.Count == 0) return;currentIndex = (currentIndex - 1 + imageFiles.Count) % imageFiles.Count;LoadImage(imageFiles[currentIndex]);}private void BtnNextImage_Click(object sender, RoutedEventArgs e){if (imageFiles.Count == 0) return;currentIndex = (currentIndex + 1) % imageFiles.Count;LoadImage(imageFiles[currentIndex]);}private void LoadImage(string path){try{var bitmap = new BitmapImage();bitmap.BeginInit();bitmap.UriSource = new Uri(path);bitmap.CacheOption = BitmapCacheOption.OnLoad;bitmap.EndInit();imgDisplay.Source = bitmap;}catch (Exception ex){MessageBox.Show($"加载图片失败: {ex.Message}");}}}
}using System;
using System.Windows;namespace MockWpf
{public partial class JsonImportWindow : Window{public string JsonText => txtJson.Text;public JsonImportWindow(){InitializeComponent();}// 点击“确认”后把对话框结果设为 OK,主窗口就能取到 JsonTextprivate void BtnOk_Click(object sender, RoutedEventArgs e){DialogResult = true;// 关闭窗口Close();}}
}

2. python脚本

pyproject.toml

[project]
name = "exp18-pyloid-pyautogui"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = ["comtypes>=1.4.12","onnxruntime>=1.22.1","pillow>=11.3.0","psutil>=7.0.0","pyautogui>=0.9.54","pyinstaller>=6.15.0","pyloid>=0.24.8","pyperclip>=1.9.0","pyscreeze>=1.0.1","pywin32>=311","rapidocr>=3.4.0","uiautomation>=2.0.29",
]

脚本:

# -*- coding: utf-8 -*-
import uiautomation as auto
import win32api, win32con, win32gui, win32console, time, sys, os
import datetime
import pyperclipCANDIDATE_TITLES = ['靶点窗口', 'OCR自动核对']
TASKS            = ['Mes导入']
DEFAULT_IMG_DIR  = r'D:\AppTest\测试工作空间'# ---------------- 日志 ----------------
class _RealTimeTee:def __init__(self, log_path: str):# 行缓冲,保证实时落盘self.file = open(log_path, 'a', encoding='utf-8', buffering=1)# 防御:无控制台时退化为只写文件self.console = sys.__stdout__ if sys.__stdout__ is not None else Noneself._write_header(log_path)def _write_header(self, log_path: str):head = f'日志文件:{os.path.abspath(log_path)}\n'self.file.write(head)if self.console:self.console.write(head)def write(self, data: str):self.file.write(data)if self.console:self.console.write(data)self.flush()def flush(self):self.file.flush()if self.console:self.console.flush()def close(self):self.flush()self.file.close()# --------------------------------------------------
# 日志:仅提供 printLog 函数,不替换 sys.stdout
# --------------------------------------------------
_log_file = None          # 全局日志句柄def init_log(log_path: str):"""初始化日志文件,写入头信息"""global _log_file_log_file = open(log_path, 'a', encoding='utf-8', buffering=1)header = f'日志文件:{os.path.abspath(log_path)}\n'printLog(header, end='')          # 屏幕_log_file.write(header)        # 文件def printLog(*args, **kwargs):"""同时打印到屏幕并写入日志"""if _log_file is None:raise RuntimeError('请先调用 init_log() 初始化日志')# 构造输出字符串sep  = kwargs.get('sep', ' ')end  = kwargs.get('end', '\n')msg  = sep.join(map(str, args)) + endprint(msg, end='')             # 屏幕_log_file.write(msg)           # 文件_log_file.flush()def close_log():"""程序结束前关闭日志句柄"""global _log_fileif _log_file:_log_file.close()_log_file = None# ---------------- 控制台工具 ----------------
def alloc_console():if win32console.GetConsoleWindow() == 0:win32console.AllocConsole()sys.stdout = open('CONOUT$', 'w', encoding='utf-8')sys.stdin  = open('CONIN$',  'r', encoding='utf-8')sys.stderr = sys.stdoutdef show_console(visible=True, topmost=False):hwnd = win32console.GetConsoleWindow()if not hwnd:returnwin32gui.ShowWindow(hwnd,win32con.SW_SHOW if visible else win32con.SW_MINIMIZE)if topmost:win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST,0, 0, 0, 0,win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)# ---------------- 鼠标/高亮 ----------------
def highlight_rect(rect, sec=3):left, top, right, bottom = map(int, (rect.left, rect.top,rect.right, rect.bottom))hdc = win32gui.GetDC(0)pen = win32gui.CreatePen(win32con.PS_SOLID, 10, win32api.RGB(255, 0, 0))old_pen = win32gui.SelectObject(hdc, pen)win32gui.SelectObject(hdc, win32gui.GetStockObject(win32con.NULL_BRUSH))for _ in range(int(sec * 5)):win32gui.Rectangle(hdc, left, top, right, bottom)time.sleep(0.1)win32gui.SelectObject(hdc, old_pen)win32gui.ReleaseDC(0, hdc)def real_click(rect):x = int((rect.left + rect.right) / 2)y = int((rect.top + rect.bottom) / 2)win32api.SetCursorPos((x, y))win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)time.sleep(0.02)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)def deep_click(ctrl):rect = ctrl.BoundingRectanglehighlight_rect(rect, 1)sub = ctrl.GetFirstChildControl()while sub:if sub.ControlType in [auto.ButtonControl, auto.TextControl,auto.CustomControl] \and abs(sub.BoundingRectangle.left - rect.left) <= 5 \and abs(sub.BoundingRectangle.top  - rect.top)  <= 5:printLog('  将点击子控件:', sub.Name)rect = sub.BoundingRectanglebreaksub = sub.GetNextSiblingControl()real_click(rect)# ---------------- 业务逻辑 ----------------
def find_window():for ttl in CANDIDATE_TITLES:w = auto.WindowControl(searchDepth=1, Name=ttl)if w.Exists(0.5):printLog('已找到窗口:', ttl)return wreturn Nonedef click_button(win, name):for tp in ['ButtonControl', 'CustomControl', 'TextControl']:btn = getattr(win, tp)(Name=name)if btn.Exists():printLog('找到按钮:', name)deep_click(btn)return TrueprintLog('未找到按钮:', name)return Falsedef wait_disappear(ctrl: auto.Control, timeout: int = 10):for _ in range(int(timeout * 10)):if not ctrl.Exists(0.05):returntime.sleep(0.1)raise RuntimeError(f'等待 {ctrl.Name} 消失超时')# ---------------- 单次完整流程 ----------------
def single_flow(win: auto.WindowControl, png_path: str, json_path: str) -> float:import win32gui as wgimport win32con as wcimport win32api as wat0 = time.perf_counter()img_name = os.path.basename(png_path)# 1. 读取图片(键盘版,原逻辑不变)t1 = time.perf_counter()if not click_button(win, '读取图片'):raise RuntimeError('未找到【读取图片】按钮')def _find_open_dialog():lst = []def enum_cb(hwnd, _):if wg.GetClassName(hwnd) == '#32770' and wg.IsWindowVisible(hwnd):lst.append(hwnd)return Truewg.EnumWindows(enum_cb, None)return lst[0] if lst else Nonefor _ in range(30):h_dlg = _find_open_dialog()if h_dlg:breaktime.sleep(0.1)else:raise RuntimeError('等待文件选择器超时')if wg.IsIconic(h_dlg):wg.ShowWindow(h_dlg, wc.SW_RESTORE)wg.SetForegroundWindow(h_dlg)# Alt+Nwa.keybd_event(wc.VK_MENU, 0, 0, 0); time.sleep(0.02)wa.keybd_event(0x4E, 0, 0, 0);       time.sleep(0.02)wa.keybd_event(0x4E, 0, wc.KEYEVENTF_KEYUP, 0); time.sleep(0.02)wa.keybd_event(wc.VK_MENU, 0, wc.KEYEVENTF_KEYUP, 0); time.sleep(0.2)# Ctrl+A 并输入路径wa.keybd_event(wc.VK_CONTROL, 0, 0, 0); time.sleep(0.02)wa.keybd_event(0x41, 0, 0, 0);          time.sleep(0.02)wa.keybd_event(0x41, 0, wc.KEYEVENTF_KEYUP, 0); time.sleep(0.02)wa.keybd_event(wc.VK_CONTROL, 0, wc.KEYEVENTF_KEYUP, 0); time.sleep(0.1)auto.SendKeys(png_path); time.sleep(0.1)# Alt+Owa.keybd_event(wc.VK_MENU, 0, 0, 0); time.sleep(0.02)wa.keybd_event(0x4F, 0, 0, 0);       time.sleep(0.02)wa.keybd_event(0x4F, 0, wc.KEYEVENTF_KEYUP, 0); time.sleep(0.02)wa.keybd_event(wc.VK_MENU, 0, wc.KEYEVENTF_KEYUP, 0)for _ in range(50):if not wg.IsWindow(h_dlg):breaktime.sleep(0.1)else:raise RuntimeError('文件对话框仍未关闭')t1 = time.perf_counter() - t1# 2. Mes 导入 —— 采用“参考代码”剪贴板方案t2 = time.perf_counter()if not click_button(win, 'Mes导入'):raise RuntimeError('未找到【Mes导入】按钮')# 等待 Json 导入窗口json_dlg = auto.WindowControl(searchDepth=2, Name='Json导入')if not json_dlg.Exists(3):raise RuntimeError('等待 Json导入 窗口超时')# 读取 json 内容try:with open(json_path, 'r', encoding='utf-8') as f:json_txt = f.read()json_ok = Trueexcept Exception as e:json_txt = ''json_ok = FalseprintLog('[警告] 读取 json 失败:', e)# 找到编辑框并聚焦edit_j = json_dlg.EditControl(foundIndex=1)if not edit_j.Exists():# 某些版本用 Custom 包了一层edit_j = json_dlg.CustomControl(foundIndex=1).EditControl(foundIndex=1)edit_j.SetFocus()# 参考代码做法:全选 + 剪贴板写入 + Ctrl+Vauto.SendKeys('{Ctrl}A'); time.sleep(0.05)pyperclip.copy(json_txt); time.sleep(0.05)auto.SendKeys('{Ctrl}V'); time.sleep(0.1)# 确定按钮ok_btn = json_dlg.ButtonControl(Name='确认')if ok_btn.Exists():deep_click(ok_btn)else:json_dlg.SendKeys('{Enter}')wait_disappear(json_dlg, 5)t2 = time.perf_counter() - t2# 3. 调试(原逻辑不变)t3 = time.perf_counter()if not click_button(win, '调试'):raise RuntimeError('未找到【调试】按钮')t3 = time.perf_counter() - t3# 4. 等待提示窗(原逻辑不变)t4 = time.perf_counter()tip = auto.WindowControl(searchDepth=2, SubName='提示')if tip.Exists(1):wait_disappear(tip, 15)t4 = time.perf_counter() - t4total = time.perf_counter() - t0printLog(f'[{img_name}]  读取图片:{t1:.2f}s  'f'Mes导入:{t2:.2f}s  调试:{t3:.2f}s  等待提示:{t4:.2f}s  'f'json成功:{json_ok}  总耗时:{total:.2f}s')return total# ---------------- 主流程 ----------------
def main():alloc_console()show_console(visible=True, topmost=True)# ---- 生成唯一日志文件名 ----log_name = datetime.datetime.now().strftime(r'自动测试_%Y%m%d_%H%M%S.log')init_log(log_name)          # 初始化日志# 询问图片文件夹img_dir = input(f'请输入图片文件夹路径(直接回车使用默认值):\n{DEFAULT_IMG_DIR}\n> ').strip()if not img_dir:img_dir = DEFAULT_IMG_DIRprintLog('使用文件夹:', img_dir)tasks = []for fn in sorted(os.listdir(img_dir)):if fn.lower().endswith('.png'):json_fn = fn[:-4] + '.json'json_path = os.path.join(img_dir, json_fn)if os.path.isfile(json_path):tasks.append((os.path.join(img_dir, fn), json_path))else:printLog(f'[跳过] {fn} 未找到同名 json')if not tasks:printLog('文件夹内没有可执行的 png/json 对!')show_console(visible=True, topmost=True)input('按回车键退出…')returntotal_cnt = len(tasks)printLog(f'\n共发现 {total_cnt} 组待执行任务,即将开始自动化…\n')show_console(visible=False)win = find_window()if not win:printLog('未找到任何候选窗口:', CANDIDATE_TITLES)show_console(visible=True, topmost=True)input('按回车键退出…')returndone = 0sum_time = 0.0try:for png, json_ in tasks:done += 1cost = single_flow(win, png, json_)sum_time += costprintLog(f'[总进度] 已执行 {done}/{total_cnt} 张  累计耗时 {sum_time:.2f} s')except Exception as e:printLog('\n[异常] 流程中断:', e)finally:show_console(visible=True, topmost=True)printLog(f'\n全部任务执行完毕! 成功 {done}/{total_cnt} 张  总耗时 {sum_time:.2f} s')input('按回车键退出…')if __name__ == '__main__':main()

打包:

uv run pyinstaller -F -w auto_test.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/943743.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软工第三次作业——结对项目

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13470github项目地址 h…

数据分析工具Pandas

View Post数据分析工具Pandas1、Pandas的数据结构分析 (1)Series:是一个类似一维数组的对象,它能够保存任何类型的数据,主要由一组数据和与之相关的索引两部分分构成;为了能方便地操作Series对象中的索引和数据,…

switch的简单运用

switch 分支语法 switch 分支结构用于在多个可能的情况下选择一种情况进行处理。以下是 switch 分支结构的基本语法:switch(变量表达式){case 常量1:语句;break;case 常量2:语句;break;case 常量3:语句;break;...case …

科学计算库Numpy

View Post科学计算库Numpy1、认识Numpy数组对象 Numpy中最重要的一个特点就是其N维数组对象,即ndarray对象,该对象可以执行一些科学计算。点击查看代码 #导入库 import numpy as np2、创建Numpy数组 (1)最简单的创…

实用指南:基于蜣螂优化的LSTM深度学习网络模型(DBO-LSTM)的一维时间序列预测算法matlab仿真

实用指南:基于蜣螂优化的LSTM深度学习网络模型(DBO-LSTM)的一维时间序列预测算法matlab仿真2025-10-22 21:02 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !import…

10.22总结

1.今天学习了数据库增添数据 2.明天准备学习删除数据 3.今天不太熟悉

AutoGen框架入门:5个核心概念搭建智能体协作系统

AutoGen 是微软研究院开源的多智能体 AI 系统框架。这个框架的设计思路很简单——让多个 AI 智能体(加上人类参与)在对话中完成复杂任务的协作和推理。 你甚至可以把它理解成一个团队聊天室,智能体们在里面讨论、争…

使用google上colab编辑器

1.先下载google,并注册google账号 手机注册失败时,可以在浏览器设置中把浏览器语言改为中文,重新注册即可 2.登录google drive 网址:https://drive.google.com/drive/my-drive 3.在google drive 中加载 Colab Noteb…

英语_阅读_The power of curiosity_待读

The power of curiosity 好奇心的力量 Curiosity is one of the most powerful forces that drive human progress. 好奇心是推动人类进步最强大的力量之一。 It is the desire to learn, explore and understand the …

20251022周三日记

20251022周三日记今日: 1.昨晚很不爽啊,越想越来气,最终想到无欲则刚,好死不如赖活着。 2.早上起床来趟实验室把电脑拿起来去上课,拜托陈和隋帮忙听CSC,感觉确实都是给博士的,可以先从语言入手。低能伦理课配ge…

goden-eye 靶场

开启靶场 端口探测 nmap nmap -sS -sV -T5 -A IP开启的80http与25端口, 访问一下80端口让我们访问/sev-home/ 这个页面登录 登录页面我们可以选择暴力破解 爆破资源太少,先试着获取一下敏感信息 f12有这样一个页面,有一…

20232424 2025-2026-1 《网络与系统攻防技术》实验二实验报告

20232424 2025-2026-1 《网络与系统攻防技术》实验二实验报告 1.实验内容 1.使用netcat在windows物理机获取远程主机kali的Shell,cron启动任务 2.使用socat在kali获取物理主机的Shell, 启动任务计划 3.使用MSF meterp…

记录docker desktop wsl2奔溃的查询思路

错误 无规律的间接性出现奔溃信息 There was a problem with WSL An error occurred while running a WSL command. Please check your WSL configuration and try again.running wslexec: An error occurred while ru…

股票操作统计分析报告 - 2025年10月22日

股票操作统计分析报告body { font-family: "Microsoft YaHei", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: rgba(51, 51, 51, 1); max-width: 1000px; margin: …

软工结对作业

软件工程结对作业项目 内容所属课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/作业要求 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13470作业目标 完成…

20232419 2025-2026-1《网络与系统攻防技术》实验二实验报告

一、实验内容 由于在不同的网络条件下多次尝试,因此IP会有所不同 (1)使用netcat获取主机操作Shell,cron启动某项任务(任务自定) PS:cron是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程 (2)使…

dfs模板(p1036)

P1036 [NOIP 2002 普及组] 选数 题目描述 已知 \(n\) 个整数 \(x_1,x_2,\cdots,x_n\),以及 \(1\) 个整数 \(k\)(\(k<n\))。从 \(n\) 个整数中任选 \(k\) 个整数相加,可分别得到一系列的和。例如当 \(n=4\),\(k…

leetcode477. 汉明距离总和

leetcode477. 汉明距离总和477. 汉明距离总和🤡过不了的暴力解:class Solution {public int totalHammingDistance(int[] nums) {int n = nums.length,res = 0;for(int i = 0;i < n;++i){for(int j = i + 1;j &l…

Java中的修饰符

在 Java 中,修饰符(Modifiers)是用来修改类、方法、变量、构造器等定义的关键字。它们主要分为两大类:访问修饰符和非控制修饰符。 以下是 Java 中所有修饰符的详细分类和说明: 一、 访问修饰符 (Access Modifier…