当前位置: 首页 > news >正文

SAP GUI Scripting - 如何判断组件是否存在

总体来说,SAP Scripting 与 BDC 类似,因为是屏幕录制,就可能碰到不同的情况,比如每个录入的数据不同,可能出现一个对话框,或者出现一个状态栏消息。这种任何有变化的情况,在 Scripting 中没有考虑到,就会导致操作失败。本文以导入 MR21 物料价格为例,演示如何处理组件/控件不存在的情况。

基于连续性,如何使用 SAP SAP Scripting 的要点,请参考本人之前的博文:

SAP Scripting Tracker基本使用技巧-CSDN博客
SAP Scripting Tracker基本使用技巧(续)_sap tracker-CSDN博客
SAP Scripting Tracker基本使用技巧 - VBA 示例-CSDN博客

首先使用 SAP Scripting Tracker 基于 Basic 录制 MR21 修改物料价格,得到下面的代码:

session.findById("wnd[0]").resizeWorkingPane(116, 39, vbFalse)
session.findById("wnd[0]/tbar[0]/okcd").text = "MR21"
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/ctxtMR21HEAD-BUDAT").text = "2024.12.31"
session.findById("wnd[0]/usr/ctxtMR21HEAD-BUKRS").text = "3600"
session.findById("wnd[0]/usr/ctxtMR21HEAD-WERKS").text = "3601"
session.findById("wnd[0]/usr/txtMR21HEAD-XBLNR").setFocus
session.findById("wnd[0]/usr/txtMR21HEAD-XBLNR").caretPosition = 0
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/ctxtCKI_MR21_0250-MATNR[0,0]").text = "20000239"
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/ctxtCKI_MR21_0250-MATNR[0,0]").caretPosition = 8
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").text = "100"
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").setFocus
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").caretPosition = 3
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").setFocus
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").caretPosition = 4
session.findById("wnd[0]/tbar[0]/btn[11]").press

录制过程中,为方便后续对代码的理解,可以在关键点插入空行,或插入空行并加上注释。因为最终需要从 Excel 的单元格导入数据,所以接下来对代码进行微调,将写死的部分替换为单元格。我一般先定义一个起始的单元格,然后其他单元格都替换为基于起始单元格的 offset:

Dim leftCell As Range
Set leftCell = Sheet1.Range("A" & i)session.findById("wnd[0]").resizeWorkingPane(116, 39, vbFalse)
session.findById("wnd[0]/tbar[0]/okcd").text = "MR21"
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/ctxtMR21HEAD-BUDAT").text = leftCell.Offset(0, 2).Value ' 过账日期
session.findById("wnd[0]/usr/ctxtMR21HEAD-BUKRS").text = leftCell.Value              ' 公司代码
session.findById("wnd[0]/usr/ctxtMR21HEAD-WERKS").text = leftCell.Offset(0, 1).Value ' 工厂
session.findById("wnd[0]/usr/txtMR21HEAD-XBLNR").setFocus
session.findById("wnd[0]/usr/txtMR21HEAD-XBLNR").caretPosition = 0
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/ctxtCKI_MR21_0250-MATNR[0,0]").text = leftCell.Offset(0, 3).Value  ' 物料编码
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/ctxtCKI_MR21_0250-MATNR[0,0]").caretPosition = 8
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").text = leftCell.Offset(0, 4).Value  '新价格
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").setFocus
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").caretPosition = 3
session.findById("wnd[0]").sendVKey(0)session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").setFocus
session.findById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").caretPosition = 4
session.findById("wnd[0]/tbar[0]/btn[11]").press

正常情况下,这个脚本就可以用了。本来 MR21 是一个表格式界面,可以处理多条记录,但 Scripting 是通过位置索引来表达某个单元格,因为项目物料不是很多,所以采取简单的方式,每一条记录保存之后再录入下一个物料,就解决了这个问题。

但物料本身的数据存在差异,录入的时候会碰到不同的情况,比如有些物料本身已经有将来或当前的价格,有些物料在修改的时候,如果新价格等于老价格,SAP就会在状态栏有一个提示:对于XXX物料,价格没有变化。对这种的情况,如果不处理,VBA 会抛出异常,所以需要处理。

我们先来讲怎样通过 Scripting Tracker 查看这个控件。在查看之前,需要制造出抛出异常的情景。

然后刷新 Scripting Tracker,显示控件的 ID:


有了这个 ID 之后,我们可以通过两个方法来处理,推荐的是第二个方法。

方法1

Dim msg As String
On Error Resume Next
msg = session.FindById("/app/con[0]/ses[0]/wnd[1]/usr/txtMESSTXT1") '价格没有修改对话框
If Err.Number = 0 ThenleftCell.Offset(0, 5).Value = session.FindById("/app/con[0]/ses[0]/wnd[1]/usr/txtMESSTXT1").Text
End If

方法2

第二个参数为 False。

Public Function FindById( _ByVal Id As String, _Optional ByVal Raise As Variant _
) As GuiComponent

在对象的子对象中搜索给定的 ID。如果参数是完全限定的 ID,函数将首先检查容器对象的 ID 是否是 ID 参数的前缀。如果是这种情况,这个前缀将被截断。如果找不到具有给定 ID 的后代,除非将可选参数 raise 设置为 False,否则函数将引发异常。(Search through the object’s descendants for a given id. If the parameter is a fully qualified id, the function will first check if the container object’s id is a prefix of the id parameter. If that is the case, this prefix is truncated. If no descendant with the given id can be found the function raises an exception unless the optional parameter raise is set to False.)

API 可以参考:GuiContainer Object | SAP Help Portal

If Not session.FindById("/app/con[0]/ses[0]/wnd[1]/usr/txtMESSTXT1", False) Is Nothing Then '价格没有修改对话框leftCell.Offset(0, 5).Value = session.FindById("/app/con[0]/ses[0]/wnd[1]/usr/txtMESSTXT1").Text
Else' 读取返回值leftCell.Offset(0, 5).Value = session.FindById("wnd[0]/sbar").Text
End If

最后给出 Excel 界面和完整的代码。

SapSesion.bas

Option ExplicitPublic Function GetSession() As ObjectDim SapGuiAuto As ObjectDim app As SAPFEWSELib.GuiApplicationDim connection As SAPFEWSELib.GuiConnectionDim session As SAPFEWSELib.GuiSessionIf app Is Nothing ThenSet SapGuiAuto = GetObject("SAPGUI")Set app = SapGuiAuto.GetScriptingEngineEnd IfIf connection Is Nothing ThenSet connection = app.Children(0)End IfIf session Is Nothing ThenSet session = connection.Children(0)End IfSet GetSession = session
End FunctionPublic Sub returnEasyAccess(sess As Object)sess.FindById("wnd[0]/tbar[0]/okcd").Text = "/n"sess.FindById("wnd[0]").SendVKey (0)
End Sub'Public Sub test()
'    Dim s As Object
'    Set s = GetSession
'
'    returnEasyAccess s
'End Sub

DataImport.bas

Option ExplicitPublic Sub DataImport()Dim session As ObjectSet session = GetSession' 确认If Not msgbox("脚本将对当前打开的SAP系统进行更改物料价格更改,请不要随意点击执行。是否继续?", vbYesNo + vbExclamation) = vbYes ThenExit SubEnd IfDim pwd As Stringpwd = InputBox("请输入密码")If pwd = "" ThenExit SubEnd IfIf pwd <> "stonestone" Thenmsgbox "密码不正确"Exit SubEnd IfCall returnEasyAccess(session)'==================================' 执行'==================================Dim i As LongFor i = 4 To Sheet1.UsedRange.CountIf Sheet1.Range("A" & i).Value = "EOF" Then Exit Sub' 每次先回到Easy Access 界面Call returnEasyAccess(session)Dim leftCell As RangeSet leftCell = Sheet1.Range("A" & i)session.FindById("wnd[0]").Maximize' 功能代码'=======================================================================session.FindById("wnd[0]/tbar[0]/okcd").Text = "MR21"session.FindById("wnd[0]").SendVKey (0)session.FindById("wnd[0]/usr/ctxtMR21HEAD-BUDAT").Text = leftCell.Offset(0, 2).Value ' 过账日期session.FindById("wnd[0]/usr/ctxtMR21HEAD-BUKRS").Text = "3600"                      ' 公司代码session.FindById("wnd[0]/usr/ctxtMR21HEAD-WERKS").Text = leftCell.Offset(0, 1).Value ' plantsession.FindById("wnd[0]/usr/ctxtMR21HEAD-WERKS").SetFocussession.FindById("wnd[0]/usr/ctxtMR21HEAD-WERKS").CaretPosition = 4session.FindById("wnd[0]").SendVKey (0)session.FindById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/ctxtCKI_MR21_0250-MATNR[0,0]").Text = leftCell.Offset(0, 3).Value  ' 物料编码session.FindById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/ctxtCKI_MR21_0250-MATNR[0,0]").CaretPosition = 8session.FindById("wnd[0]").SendVKey (0)'如果物料有将来价格则存在对话框If Not session.FindById("wnd[1]/tbar[0]/btn[0]", False) Is Nothing Thensession.FindById("wnd[1]/tbar[0]/btn[0]").PressEnd Ifsession.FindById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").Text = leftCell.Offset(0, 4).Value  '新价格session.FindById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").SetFocussession.FindById("wnd[0]/usr/tabsMR21_TABSTRIP/tabpTAB1/ssubMR21_SUB:SAPRCKM_MR21:0250/tblSAPRCKM_MR21MR21_TABCONTROL/txtCKI_MR21_0250-NEWVALPR[4,0]").CaretPosition = 4session.FindById("wnd[0]").SendVKey (0)' Savesession.FindById("wnd[0]/tbar[0]/btn[11]").Press' Save之后可能提示物料价格没有更改If Left(session.FindById("wnd[0]/sbar").Text, 4) = "对于物料" Thensession.FindById("wnd[0]").SendVKey (0)End If'====================================================================If Not session.FindById("/app/con[0]/ses[0]/wnd[1]/usr/txtMESSTXT1", False) Is Nothing Then '价格没有修改对话框leftCell.Offset(0, 5).Value = session.FindById("/app/con[0]/ses[0]/wnd[1]/usr/txtMESSTXT1").TextElse' 读取返回值leftCell.Offset(0, 5).Value = session.FindById("wnd[0]/sbar").TextEnd If' 保存If i Mod 5 = 0 ThenThisWorkbook.SaveEnd If' 滚动If i >= 25 ThenActiveWindow.SmallScroll down:=1End IfNext
End Sub

相关文章:

SAP GUI Scripting - 如何判断组件是否存在

总体来说&#xff0c;SAP Scripting 与 BDC 类似&#xff0c;因为是屏幕录制&#xff0c;就可能碰到不同的情况&#xff0c;比如每个录入的数据不同&#xff0c;可能出现一个对话框&#xff0c;或者出现一个状态栏消息。这种任何有变化的情况&#xff0c;在 Scripting 中没有考…...

Go 计算Utf8字符串的长度 不要超过mysql字段的最大长度

背景&#xff1a; 我有一个mysql的字段&#xff0c;是utf8格式的&#xff0c;但有时候前端传的字符串会超长&#xff0c;为此我需要在后端接口&#xff0c;先判断是否超长&#xff0c;如果超长&#xff0c;则报错提示前端。 代码&#xff1a; // 计算utf8下&#xff0c;字符串…...

llamafactory报错:双卡4090GPU,训练qwen2.5:7B、14B时报错GPU显存不足(out of memory),轻松搞定~~~

实际问题场景&#xff1a; 使用llamafactory进行微调qwen2.5 7B和14B的大模型时&#xff0c;会出现out of memory的报错。尝试使用降低batch_size&#xff08;原本是2&#xff0c;现在降到1&#xff09;的方式&#xff0c;可以让qwen2.5:7B跑起来&#xff0c;但时不时会不稳定…...

全局webSocket 单个页面进行监听并移除单页面监听

之前全局封装的 webSocket 在某些特定的页面中使用会直接去调用 webSocket 的 onMessage 方法 已进入页面就会调&#xff0c;如果退出页面移除整个监听的话全局监听就会被移除 这是修改后的 全局封装 let token uni.getStorageSync(token) const HEARTBEAT_INTERVAL 1 *…...

JVM调优实践篇

理论篇 1多功能养鱼塘&#xff0d;JVM内存 大鱼塘O&#xff08;可分配内存&#xff09;&#xff1a; JVM可以调度使用的总的内存数&#xff0c;这个数量受操作系统进程寻址范围、系统虚拟内存总数、系统物理内存总数、其他系统运行所占用的内存资源等因素的制约。 小池塘A&a…...

【JavaEE】Spring Web MVC

目录 一、Spring Web MVC简介 1.1 MVC简介1.2 Spring MVC1.3 RequestMapping注解1.3.1 使用1.3.2 RequestMapping的请求设置 1.3.2.1 方法11.3.2.2 方法2 二、Postman介绍 2.1 创建请求2.2 界面如下&#xff1a;2.3 传参介绍 一、Spring Web MVC简介 官方文档介绍&#xff…...

VSCode 插件开发实战(七):插件支持了哪些事件,以及如何利用和监听这些事件

前言 VSCode 作为现代开发者的首选编辑器之一&#xff0c;其核心优势在于其高度可扩展性。通过自定义插件&#xff0c;开发者可以根据自己的需求对编辑器进行功能扩展和优化。在这些插件开发过程中&#xff0c;事件处理和监听机制尤为重要&#xff0c;它们允许插件在特定事件发…...

指针详解之 多层嵌套的关系

1 例子之指向3个字符串的指针数组&#xff0c;易混淆&#xff01; 1.1过程详解&#xff1a; char *str[3]{ "Hello,thisisasample!", "Hi,goodmorning.", "Helloworld" }; char s[80]&#xff1b; strcpy(s,str[0]); //也可写成strcpy(s,*st…...

Animated Drawings:让纸上的角色动起来

前言 今天介绍的这个工具非常的有意思&#xff1a;它可以让我们在纸上绘画的角色动起来。先一起来看看效果&#xff1a; 准备 首先&#xff0c;我们先准备一张绘画。可以在纸上进行绘制&#xff0c;也可以在电子设备上进行绘制。绘制内容不限&#xff0c;在这里为了方便演示&am…...

技术与教育的结合:高校听课评价系统的设计与实施

3.1系统可行性分析 需要使用大部分精力开发的高校听课评价系统为了充分降低开发风险&#xff0c;特意在开发之前进行可行性分析这个验证系统开发是否可行的步骤。本文就会从技术角度&#xff0c;经济角度&#xff0c;还有用户使用的程序的运行角度进行综合阐述。 3.1.1 技术可行…...

web移动端项目常用解决方案

移动端总会遇到一系列特定于移动设备的问题&#xff0c;分享下常见的移动端常见问题的处理方案。 1px边框问题 在高清屏幕下&#xff0c;1px的边框显示得比较粗。 .border-1px {position: relative; } .border-1px::after {position: absolute;content: ;width: 200%;height:…...

LabVIEW软件项目设计方案如何制定

制定LabVIEW软件项目设计方案需要综合考虑需求分析、架构设计、功能模块划分和时间预算等多个方面&#xff0c;确保项目开发过程高效、可控且最终满足目标要求。以下是一个详细的制定流程&#xff1a; ​ 1. 需求分析 目标定义&#xff1a;明确项目的目标&#xff0c;例如数据采…...

数据结构(Java)——链表

1.概念及结构 链表是一种 物理存储结构上非连续 存储结构&#xff0c;数据元素的 逻辑顺序 是通过链表中的 引用链接 次序实现的 。 2.分类 链表的结构非常多样&#xff0c;以下情况组合起来就有 8 种链表结构&#xff1a; &#xff08;1&#xff09;单向或者双向 &#xff08;…...

变量与数据类型 - 整型、浮点型、字符型等

引言 在编程中&#xff0c;变量和数据类型是基础中的基础。理解它们如何工作以及如何正确使用它们对于编写高效且无误的代码至关重要。本文将详细介绍 C 中的几种基本数据类型&#xff1a;整型、浮点型、字符型等&#xff0c;并通过实例帮助读者更好地理解和掌握这些概念。 一…...

MacOS安装Xcode(非App Store)

文章目录 访问官网资源页面 访问官网资源页面 直接访问官网的历史版本下载资源页面地址&#xff1a;https://developer.apple.com/download/more/完成APP ID的登陆&#xff0c;直接找到需要的软件下载即可 解压后&#xff0c;安装将xcode.app移动到应用程序文件夹。...

运行Zr.Admin项目(后端)

1.下载Zr.Admin代码压缩包 https://codeload.github.com/izhaorui/Zr.Admin.NET/zip/refs/heads/main 2.打开项目 我这里装的是VS2022社区版 进入根目录&#xff0c;双击ZRAdmin.sln打开项目 3.安装.net7运行时 我当时下载的代码版本是.net7的 点击安装 点击安装&#xff0…...

Ubuntu24.04最新版本安装详细教程

Ubuntu 24.04 LTS发布说明 推荐的系统配置要求&#xff1a; 双核2 GHz处理器或更高 4 GB系统内存 25 GB磁盘存储空间 可访问的互联网 光驱或USB安装介质 Ubuntu 24.04官方下载网址&#xff1a;https://cn.ubuntu.com/download/desktop 04. Ubuntu 22.04(创建虚拟机方式一) 4…...

js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)

目录 Proxy Reflect 静态方法 部分实例 Iterator 实际开发迭代器的使用实例 迭代器&#xff08;Iterator&#xff09;应用 Generator Proxy Proxy 是 ES6 中新增的对象 Proxy 是JavaScript中的内置对象&#xff0c;它提供了一种机制&#xff0c;可以拦截并自定义各种…...

CSS实现一个自定义的滚动条

要使用CSS创建一个自定义的滚动条&#xff0c;你可以使用伪元素和CSS的伪类来控制滚动条的外观和行为。以下是一个简单的例子&#xff0c;展示如何为任何HTML元素添加一个自定义的滚动条样式&#xff1a; <!DOCTYPE html> <html lang"en"> <head> …...

CKA认证 | Day8 K8s安全

第八章 Kubernetes安全 1、Kubernetes RBAC授权 Kubernetes 基于角色的访问控制&#xff08;Role-Based Access Control, RBAC&#xff09; 是一种强大的权限管理机制&#xff0c;用于控制用户、用户组、服务账户对 Kubernetes 集群资源的访问。通过 RBAC&#xff0c;可以细…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

[特殊字符] Spring Boot底层原理深度解析与高级面试题精析

一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配&#xff0c;通过简化传统Spring应用的初始化和配置流程&#xff0c;显著提升开发效率。其底层原理可拆解为以下核心机制&#xff1a; 自动装配&#xff08;Auto-Configuration&#xff09; 核…...

篇章一 论坛系统——前置知识

目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构​编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...