windows USB 了解

news2025/3/31 22:24:52

GUID

GUID 是一个 128 位的数字,在全球范围内是独一无二的,常被用于标识软件组件、设备接口等,以保证在不同系统和环境中能唯一识别特定对象。

DEFINE_GUID(GUID_DEVINTERFACE_USCUSTOMKEYS, 0x12345678, 0x1234, 0x5678, 0x12, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78);

DEFINE_GUID:这是一个宏,在 Windows 编程里用于定义 GUID。它在 <guiddef.h> 头文件中被定义,此宏会创建一个 GUID 类型的全局变量,并且对其进行初始化。

GUID_DEVINTERFACE_USCUSTOMKEYS:这是所定义的 GUID 的名称。在后续代码里,可借助这个名称来引用该 GUID。

0x12345678, 0x1234, 0x5678, 0x12, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78:这些是构成 128 位 GUID 的具体数值。GUID 通常会被拆分成几个部分,以便于表示和处理。

枚举设备

#include <windows.h>
#include <iostream>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
#include <tchar.h>

#pragma comment(lib, "setupapi.lib")

// 这里使用 USB 设备类的 GUID 作为示例,你可以根据需要替换为其他设备类的 GUID
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);

int main() {
    HDEVINFO hDevInfo;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 };
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;
    DWORD requiredSize = 0;
    DWORD index = 0;

    // 获取指定设备类的设备信息集
    hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hDevInfo == INVALID_HANDLE_VALUE) {
        std::cerr << "SetupDiGetClassDevs failed with error: " << GetLastError() << std::endl;
        return 1;
    }

    // 初始化 SP_DEVICE_INTERFACE_DATA 结构体
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    // 枚举设备接口
    while (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, index, &deviceInterfaceData)) {
        // 获取所需的缓冲区大小
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL);

        // 分配缓冲区
        deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredSize);
        if (deviceInterfaceDetailData == NULL) {
            std::cerr << "LocalAlloc failed with error: " << GetLastError() << std::endl;
            SetupDiDestroyDeviceInfoList(hDevInfo);
            return 1;
        }
        deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        // 获取设备接口的详细信息
        if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, NULL)) {
            std::cerr << "SetupDiGetDeviceInterfaceDetail failed with error: " << GetLastError() << std::endl;
            LocalFree(deviceInterfaceDetailData);
            index++;
            continue;
        }

        // 打印设备接口的详细信息
        std::wcout << L"Device Path: " << deviceInterfaceDetailData->DevicePath << std::endl;

        // 释放缓冲区
        LocalFree(deviceInterfaceDetailData);
        index++;
    }

    // 检查枚举是否因错误而终止
    if (GetLastError() != ERROR_NO_MORE_ITEMS) {
        std::cerr << "SetupDiEnumDeviceInterfaces failed with error: " << GetLastError() << std::endl;
    }

    // 销毁设备信息集
    SetupDiDestroyDeviceInfoList(hDevInfo);

    return 0;
}    

SetupDiGetClassDevs

HDEVINFO SetupDiGetClassDevs(
  const GUID          *ClassGuid,
  PCTSTR              Enumerator,
  HWND                hwndParent,
  DWORD               Flags
);

功能:此函数会创建一个包含指定设备类的设备信息集,该集合可用来枚举和操作设备。
参数:
ClassGuid:指向设备类的 GUID(全局唯一标识符)的指针,指定要枚举的设备类。若为 NULL,则会返回所有设备类的设备。
Enumerator:指定设备枚举器名称的字符串,如 USB 或 PCI。若为 NULL,则不限制枚举器。
hwndParent:与设备安装程序相关的父窗口句柄,通常设为 NULL。
Flags:控制函数行为的标志位,常用标志有:
DIGCF_PRESENT:仅返回当前存在的设备。
DIGCF_DEVICEINTERFACE:返回支持指定设备接口类的设备。
返回值:若函数调用成功,会返回设备信息集的句柄;若失败,则返回 INVALID_HANDLE_VALUE。

SetupDiEnumDeviceInterfaces

BOOL SetupDiEnumDeviceInterfaces(
  HDEVINFO                 DeviceInfoSet,
  PSP_DEVINFO_DATA         DeviceInfoData,
  const GUID               *InterfaceClassGuid,
  DWORD                    MemberIndex,
  PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
);

功能:对设备信息集中的设备接口进行枚举。
参数:
DeviceInfoSet:由 SetupDiGetClassDevs 函数返回的设备信息集的句柄。
DeviceInfoData:指向 SP_DEVINFO_DATA 结构体的指针,用于指定特定设备。若为 NULL,则枚举所有设备。
InterfaceClassGuid:指向设备接口类的 GUID 的指针,指定要枚举的接口类。
MemberIndex:要枚举的设备接口的索引,从 0 开始。
DeviceInterfaceData:指向 SP_DEVICE_INTERFACE_DATA 结构体的指针,用于接收枚举到的设备接口信息。
返回值:若函数调用成功,返回 TRUE;若失败或没有更多设备接口可供枚举,返回 FALSE,此时可通过 GetLastError 函数获取错误代码。若错误代码为 ERROR_NO_MORE_ITEMS,则表示枚举结束。

SetupDiGetInterfaceDeviceDetail

BOOL SetupDiGetInterfaceDeviceDetail(
  HDEVINFO                         DeviceInfoSet,
  PSP_DEVICE_INTERFACE_DATA        DeviceInterfaceData,
  PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,
  DWORD                            DeviceInterfaceDetailDataSize,
  PDWORD                           RequiredSize,
  PSP_DEVINFO_DATA                 DeviceInfoData
);

功能:获取指定设备接口的详细信息,像设备路径之类的。
参数:
DeviceInfoSet:由 SetupDiGetClassDevs 函数返回的设备信息集的句柄。
DeviceInterfaceData:指向 SP_DEVICE_INTERFACE_DATA 结构体的指针,包含要获取详细信息的设备接口信息。
DeviceInterfaceDetailData:指向 SP_DEVICE_INTERFACE_DETAIL_DATA 结构体的指针,用于接收设备接口的详细信息。
DeviceInterfaceDetailDataSize:DeviceInterfaceDetailData 结构体的大小。
RequiredSize:指向 DWORD 类型变量的指针,用于接收所需的缓冲区大小。
DeviceInfoData:指向 SP_DEVINFO_DATA 结构体的指针,用于接收设备的详细信息。若为 NULL,则不接收该信息。
返回值:若函数调用成功,返回 TRUE;若失败,返回 FALSE,可通过 GetLastError 函数获取错误代码。若所需的缓冲区大小超过 DeviceInterfaceDetailDataSize,则返回 FALSE,且 RequiredSize 会包含所需的缓冲区大小。

SetupDiDestroyDeviceInfoList

BOOL SetupDiDestroyDeviceInfoList(
  HDEVINFO DeviceInfoSet
);

功能:销毁由 SetupDiGetClassDevs 函数创建的设备信息集,释放相关资源。
参数:
DeviceInfoSet:要销毁的设备信息集的句柄。
返回值:若函数调用成功,返回 TRUE;若失败,返回 FALSE,可通过 GetLastError 函数获取错误代码。
总结
这些函数通常按以下顺序使用:
调用 SetupDiGetClassDevs 函数创建设备信息集。
利用 SetupDiEnumDeviceInterfaces 函数枚举设备信息集中的设备接口。
针对每个枚举到的设备接口,调用 SetupDiGetInterfaceDeviceDetail 函数获取详细信息。
最后调用 SetupDiDestroyDeviceInfoList 函数销毁设备信息集,释放资源。

总结

这些函数通常按以下顺序使用:
调用 SetupDiGetClassDevs 函数创建设备信息集。
利用 SetupDiEnumDeviceInterfaces 函数枚举设备信息集中的设备接口。
针对每个枚举到的设备接口,调用 SetupDiGetInterfaceDeviceDetail 函数获取详细信息。
最后调用 SetupDiDestroyDeviceInfoList 函数销毁设备信息集,释放资源。

注意

需要注意环境的编码格式,根据实际使用选择
在这里插入图片描述

开打管道

m_hReadPipe = CreateFile((LPCSTR)m_ReadPipe, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);

CreateFile 是 Windows API 中的一个函数,用于创建或打开文件、目录、物理磁盘、卷、控制台缓冲区、通信资源、邮件槽、管道等对象。此函数会返回一个句柄,后续可使用该句柄对这些对象进行操作。

  1. (LPCSTR)m_ReadPipe
    含义:这是要打开的对象的名称,在该代码里为管道的名称。m_ReadPipe 应当是一个字符串类型的变量,代表管道的名称。(LPCSTR) 是一个强制类型转换,将 m_ReadPipe 转换为 LPCSTR 类型(即指向以 null 结尾的多字节字符串的指针)。
    注意:在 Unicode 字符集环境下,建议使用 CreateFileW 函数并传入 LPCWSTR 类型的参数,以避免字符编码问题。

  2. GENERIC_READ | GENERIC_WRITE
    含义:这是访问权限标志,用于指定对打开对象的访问方式。
    GENERIC_READ:表示对对象具有读权限,也就是可以从对象中读取数据。
    GENERIC_WRITE:表示对对象具有写权限,即能够向对象中写入数据。
    GENERIC_READ | GENERIC_WRITE:表示同时具有读和写的权限。

  3. FILE_SHARE_READ | FILE_SHARE_WRITE
    含义:这是共享模式标志,用于指定其他进程对该对象的访问权限。
    FILE_SHARE_READ:允许其他进程以读权限打开该对象。
    FILE_SHARE_WRITE:允许其他进程以写权限打开该对象。
    FILE_SHARE_READ | FILE_SHARE_WRITE:表示其他进程可以同时以读和写的权限打开该对象。

  4. NULL
    含义:这是指向 SECURITY_ATTRIBUTES 结构体的指针,用于指定对象的安全属性。若为 NULL,则表示使用默认的安全属性,并且该对象的句柄不能被子进程继承。

  5. OPEN_EXISTING
    含义:这是创建方式标志,用于指定如果对象不存在时的处理方式。OPEN_EXISTING 表示仅当对象已经存在时才打开它,如果对象不存在,函数将失败并返回 INVALID_HANDLE_VALUE。

  6. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED
    含义:这是文件属性和标志的组合。
    FILE_ATTRIBUTE_NORMAL:表示文件没有特殊的属性,是最常见的文件属性。
    FILE_FLAG_OVERLAPPED:表示以异步(重叠)方式打开文件。在异步模式下,对文件的读写操作会立即返回,而不会等待操作完成,可通过 OVERLAPPED 结构体来处理操作结果。

  7. 0
    含义:这是模板文件的句柄,用于指定一个模板文件的句柄,新创建的文件将继承该模板文件的属性。若为 0,则表示不使用模板文件。

返回值
若函数调用成功,会返回一个有效的句柄,该句柄可用于后续对管道的读写操作。
若失败,会返回 INVALID_HANDLE_VALUE,可通过 GetLastError 函数获取具体的错误代码。

不要忘记还有 CloseHandle(m_hReadPipe);
CloseHandle 是 Windows API 中的一个函数,它的主要作用是关闭对象的句柄。在 Windows 操作系统里,许多系统资源(像文件、管道、线程、进程等)都会用句柄来标识,当不再需要使用这些资源时,就需要调用 CloseHandle 函数来关闭对应的句柄,从而释放系统资源。

异步读取

#include <windows.h>
#include <iostream>
#include <string>

const char* WRITE_PIPE_NAME = "\\\\.\\pipe\\Pipe0";
const char* READ_PIPE_NAME = "\\\\.\\pipe\\Pipe1";
const int BUFFER_SIZE = 1024;
const int WRITE_INTERVAL_MS = 3000;
const int MAIN_LOOP_INTERVAL_MS = 100; // 主循环间隔设为 100 毫秒

void WriteAsync(HANDLE hPipe, int writeCount, HANDLE hWriteEvent) {
    OVERLAPPED overlapped = { 0 };
    overlapped.hEvent = hWriteEvent;

    std::string message = "Data write number " + std::to_string(writeCount);
    DWORD bytesWritten;
    if (!WriteFile(hPipe, message.c_str(), static_cast<DWORD>(message.length()), NULL, &overlapped)) {
        if (GetLastError() != ERROR_IO_PENDING) {
            std::cerr << "WriteFile failed: " << GetLastError() << std::endl;
            return;
        }
    }

    DWORD waitResult = WaitForSingleObject(hWriteEvent, INFINITE);
    if (waitResult == WAIT_OBJECT_0) {
        if (!GetOverlappedResult(hPipe, &overlapped, &bytesWritten, FALSE)) {
            std::cerr << "GetOverlappedResult failed: " << GetLastError() << std::endl;
        } else {
            std::cout << "Asynchronous write completed. Bytes written: " << bytesWritten << std::endl;
        }
        ResetEvent(hWriteEvent);
    } else {
        std::cerr << "WaitForSingleObject failed: " << waitResult << std::endl;
    }
}

void ReadAsync(HANDLE hPipe, HANDLE hReadEvent) {
    OVERLAPPED overlapped = { 0 };
    overlapped.hEvent = hReadEvent;

    char buffer[BUFFER_SIZE];
    DWORD bytesRead;
    if (!ReadFile(hPipe, buffer, BUFFER_SIZE, NULL, &overlapped)) {
        if (GetLastError() != ERROR_IO_PENDING) {
            std::cerr << "ReadFile failed: " << GetLastError() << std::endl;
            return;
        }
    }

    DWORD waitResult = WaitForSingleObject(hReadEvent, INFINITE);
    if (waitResult == WAIT_OBJECT_0) {
        if (!GetOverlappedResult(hPipe, &overlapped, &bytesRead, FALSE)) {
            std::cerr << "GetOverlappedResult failed: " << GetLastError() << std::endl;
        } else if (bytesRead > 0) {
            buffer[bytesRead] = '\0';
            std::cout << "Asynchronous read completed. Bytes read: " << bytesRead << std::endl;
            std::cout << "Read data: " << buffer << std::endl;
        }
        ResetEvent(hReadEvent);
    } else {
        std::cerr << "WaitForSingleObject failed: " << waitResult << std::endl;
    }
}

int main() {
    HANDLE hWritePipe = CreateFile(
        WRITE_PIPE_NAME,
        GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL
    );

    if (hWritePipe == INVALID_HANDLE_VALUE) {
        std::cerr << "CreateFile for write pipe failed: " << GetLastError() << std::endl;
        return 1;
    }

    HANDLE hReadPipe = CreateFile(
        READ_PIPE_NAME,
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL
    );

    if (hReadPipe == INVALID_HANDLE_VALUE) {
        std::cerr << "CreateFile for read pipe failed: " << GetLastError() << std::endl;
        CloseHandle(hWritePipe);
        return 1;
    }

    HANDLE hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (hWriteEvent == NULL) {
        std::cerr << "CreateEvent for write failed: " << GetLastError() << std::endl;
        CloseHandle(hWritePipe);
        CloseHandle(hReadPipe);
        return 1;
    }

    HANDLE hReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (hReadEvent == NULL) {
        std::cerr << "CreateEvent for read failed: " << GetLastError() << std::endl;
        CloseHandle(hWriteEvent);
        CloseHandle(hWritePipe);
        CloseHandle(hReadPipe);
        return 1;
    }

    int writeCount = 1;
    DWORD lastWriteTime = GetTickCount();

    while (true) {
        DWORD currentTime = GetTickCount();
        if (currentTime - lastWriteTime >= WRITE_INTERVAL_MS) {
            WriteAsync(hWritePipe, writeCount++, hWriteEvent);
            lastWriteTime = currentTime;
        }

        ReadAsync(hReadPipe, hReadEvent);
        Sleep(MAIN_LOOP_INTERVAL_MS);
    }

    CloseHandle(hWriteEvent);
    CloseHandle(hReadEvent);
    CloseHandle(hWritePipe);
    CloseHandle(hReadPipe);
    return 0;
}    

Pipe0 每 3 秒写入一次数据,同时在主循环中以更短的时间间隔尝试从 Pipe1 读取数据,且写入和读取操作分别使用独立的事件对象。

CreateEvent

创建或打开一个命名或未命名的事件对象,事件对象是一种同步对象,用于线程间或进程间的同步,可用来通知其他线程某个操作已经完成。

常用于异步操作中,当异步操作完成时,将事件对象设置为有信号状态,通知其他线程操作已完成。

HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL                  bManualReset,
  BOOL                  bInitialState,
  LPCTSTR               lpName
);

lpEventAttributes:指向 SECURITY_ATTRIBUTES 结构体的指针,该结构体决定返回的句柄是否可被子进程继承。若为 NULL,则句柄不能被继承。
bManualReset:指定事件对象的复位方式。若为 TRUE,则为手动复位事件,需要调用 ResetEvent 函数将其设置为无信号状态;若为 FALSE,则为自动复位事件,当一个等待线程被释放后,系统会自动将其设置为无信号状态。
bInitialState:指定事件对象的初始状态。若为 TRUE,则初始状态为有信号状态;若为 FALSE,则初始状态为无信号状态。
lpName:指定事件对象的名称,若为 NULL,则创建一个未命名的事件对象。
返回值
若函数成功,返回事件对象的句柄;若失败,返回 NULL,可通过 GetLastError 函数获取错误代码。

WaitForSingleObject

等待指定的对象(如事件、互斥体、信号量等)变为有信号状态,或者等待指定的时间间隔过去。
在异步操作中,用于等待异步操作完成的通知(即事件对象变为有信号状态)。

DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD  dwMilliseconds
);

参数
hHandle:要等待的对象的句柄。
dwMilliseconds:等待的时间间隔,以毫秒为单位。若为 INFINITE,则表示无限期等待,直到对象变为有信号状态。

返回值
返回一个指示等待结果的 DWORD 值,常见的返回值有:
WAIT_OBJECT_0:表示等待的对象变为有信号状态。
WAIT_TIMEOUT:表示等待的时间间隔已过,对象仍未变为有信号状态。

ResetEvent

BOOL ResetEvent(
  HANDLE hEvent
);

功能
将指定的事件对象设置为无信号状态。
参数
hEvent:要设置的事件对象的句柄。
返回值
若函数成功,返回 TRUE;若失败,返回 FALSE,可通过 GetLastError 函数获取错误代码。
使用场景
对于手动复位事件,在处理完事件通知后,需要调用该函数将事件对象重置为无信号状态,以便下次使用。

GetOverlappedResult

BOOL GetOverlappedResult(
  HANDLE       hFile,
  LPOVERLAPPED lpOverlapped,
  LPDWORD      lpNumberOfBytesTransferred,
  BOOL         bWait
);

功能
获取指定的异步(重叠)操作的结果,包括操作是否成功以及传输的字节数。
参数
hFile:进行异步操作的对象的句柄,如文件、管道等。
lpOverlapped:指向 OVERLAPPED 结构体的指针,该结构体包含了异步操作的相关信息。
lpNumberOfBytesTransferred:指向 DWORD 变量的指针,用于接收异步操作传输的字节数。
bWait:指定函数是否等待异步操作完成。若为 TRUE,则函数会等待操作完成;若为 FALSE,则若操作尚未完成,函数会立即返回 FALSE。
返回值
若函数成功,返回 TRUE;若失败,返回 FALSE,可通过 GetLastError 函数获取错误代码。
使用场景
在异步操作中,当事件对象变为有信号状态,表示异步操作可能已经完成,此时可调用该函数获取操作的具体结果。

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

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

相关文章

光谱相机的光谱信息获取

光谱信息的获取方式主要依赖于不同分光技术和成像方法&#xff0c;将入射光分解为不同波长并记录其强度。以下是常见的光谱信息获取技术分类及原理&#xff1a; ‌1. 分光技术&#xff08;物理分解波长&#xff09;‌ ‌(1) 滤光片法‌ ‌原理‌&#xff1a;使用固定或可调滤…

免去繁琐的手动埋点,Gin 框架可观测性最佳实践

作者&#xff1a;牧思 背景 在云原生时代的今天&#xff0c;Golang 编程语言越来越成为开发者们的首选&#xff0c;而对于 Golang 开发者来说&#xff0c;最著名的 Golang Web 框架莫过于 Gin [ 1] 框架了&#xff0c;Gin 框架作为 Golang 编程语言官方的推荐框架 [ 2] &…

构建大语言模型应用:简介(第一部分)

本专栏聚焦大语言模型&#xff08;LLM&#xff09;相关内容的解析&#xff0c;通过检索增强生成&#xff08;RAG&#xff09;应用的视角来进行。 本系列文章 简介&#xff08;本文&#xff09;数据准备句子转换器向量数据库搜索与检索大语言模型开源检索增强生成评估大语言模…

PEmicro Multilink FX调试踩坑

文章目录 1.背景2 功能说明2.1 实时数据查看功能2.1 电压观测2.2 SWO功能 3 设置与支持 1.背景 既然使用了NXP的芯片&#xff0c;笔者就想使用一下它的专用调试器&#xff0c;这里先说一下&#xff0c;笔者是从朋友那里借了一个调试器&#xff0c;型号为PEmicro Multilink FX …

主流大模型采用的架构、注意力机制、位置编码等汇总表

记录下主流大模型的一些核心知识点&#xff0c;包括&#xff1a; 架构注意力机制位置编码归一化激活函数模型参数 表中的一些模型已经是很久之前的了&#xff0c;比如表中并未收入 DeepSeek V3 中使用的MLA的注意力机制。先占个位&#xff0c;后续如果有更新的汇总表再来更…

SpringBoot学习笔记3.27

目录 实战篇第二课 1.注册参数的校验&#xff1a; 学习过程中遇到的问题&#xff1a; 1.什么是正则表达式 2.怎么自定义异常&#xff1f; 1. 创建全局异常处理类 2. 定义响应对象 3. 使用 ExceptionHandler 4. 设置响应状态码 5. 返回统一响应 6. 测试全局异常处理 …

2025NCTF--Web

文章目录 Websqlmap-masterez_dashez_dash_revenge Web sqlmap-master 源码 from fastapi import FastAPI, Request from fastapi.responses import FileResponse, StreamingResponse import subprocessapp FastAPI()app.get("/") async def index():return File…

如何破解软件自动化测试框架的维护难题

破解软件自动化测试框架的维护难题应从优化测试用例设计、加强脚本的模块化与复用性、提高自动化测试工具的选择与使用效率等方面入手。其中&#xff0c;加强脚本的模块化与复用性尤为关键&#xff0c;通过提高脚本的模块化程度&#xff0c;可以显著降低后续维护成本&#xff0…

外星人入侵(python设计小游戏)

这个游戏简而言之就是操作一个飞机对前方的飞船进行射击&#xff0c;和一款很久之前的游戏很像&#xff0c;这里是超级低配版那个游戏&#xff0c;先来看看效果图&#xff1a; 由于设计的是全屏的&#xff0c;所以电脑不能截图。。。。 下面的就是你操控的飞船&#xff0c;上面…

iOS rootless无根越狱检测方案

不同于安卓的开源生态&#xff0c;iOS一直秉承着安全性更高的闭源生态&#xff0c;系统中的硬件、软件和服务会经过严格审核和测试&#xff0c;来保障安全性与稳定性。 据FairGurd观察&#xff0c;虽然iOS系统具备一定的安全性&#xff0c;但并非没有漏洞&#xff0c;如市面上…

LLM 优化技术(1)——Scaled-Dot-Product-Attention(SDPA)

在 Transformer 中抛弃了传统的 CNN 和 RNN&#xff0c;整个网络结构完全由Scaled Dot Product Attention 和Feed Forward Neural Network组成。一个基于 Transformer 的可训练的神经网络可以通过堆叠 Transformer 的形式进行搭建&#xff0c;Attention is All You Need论文中通…

基于音频驱动的CATIA动态曲面生成技术解析

一、技术背景与创新价值 在工业设计领域&#xff0c;参数化建模与动态仿真的结合一直是研究热点。本文提出的音频驱动建模技术突破了传统参数调整方式&#xff0c;实现了音乐节奏与三维曲面的实时动态交互。该技术可广泛应用于以下场景&#xff1a; ​艺术化产品设计&#xf…

5-管理员-维护权限

在“后台”-“人员管理”-“权限”下&#xff0c;通过不同的操作按钮&#xff0c;按照权限分组对权限进行设置。操作部分的按钮依次为 视野维护&#xff1a;设置该分组可以查看、访问的视图。权限维护&#xff1a;设置分组成员可以操作的具体动作等所有在禅道中涉及的权限。成…

全新升级 | Built For You Spring ‘25 发布,Fin 智能客服实现新突破!

图像识别、语音交互、任务自动化&#xff0c;立即体验智能客服蜕变&#xff01; 上周&#xff0c;Intercom 举办了 Built For You Spring 25 发布会&#xff0c;正式揭晓了 AI Agent Fin 的一系列令人振奋的更新。Fin 正在以前所未有的速度革新客户支持模式——它已经成功解决了…

LeeCode 434. 字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 请注意&#xff0c;你可以假定字符串里不包括任何不可打印的字符。 示例: 输入: "Hello, my name is John" 输出: 5 解释: 这里的单词是指连续的不是空格的字符&#xff0c;所以 "…

【AI编程学习之Python】第一天:Python的介绍

Python介绍 简介 Python是一种解释型、面向对象的语言。由吉多范罗苏姆(Guido van Rossum)于1989年发明,1991年正式公布。官网:www.python.org Python单词是"大蟒蛇”的意思。但是龟叔不是喜欢蟒蛇才起这个名字,而是正在追剧:英国电视喜剧片《蒙提派森的飞行马戏团》(Mo…

西域平台商品详情接口设计与实现‌

接口描述&#xff1a; 该接口用于获取西域平台中指定商品的详细信息&#xff0c;包括商品名称、价格、库存、描述、图片等。 点击获取key和secret 接口地址&#xff1a; GET /api/product/detail 请求参数&#xff1a; 参数名 类型 是否必填 描述 productId st…

如何让 history 记录命令执行时间?Linux/macOS 终端时间戳设置指南

引言:你真的会用 history 吗? 有没有遇到过这样的情况:你想回顾某个重要命令的执行记录,却发现 history 只列出了命令序号和内容,根本没有时间戳?这在运维排查、故障分析、甚至审计时都会带来极大的不便。 想象一下,你在服务器上误删了某个文件,但不知道具体是几点执…

04-SpringBoot3入门-配置文件(多环境配置)

1、简介 在 SpringBoot 中&#xff0c;不同的环境&#xff08;如开发、测试、生产&#xff09;可以编写对应的配置文件&#xff0c;例如数据库连接信息、日志级别、缓存配置等。在不同的环境中使用对应的配置文件。 2、配置环境 # 开发环境 zbj:user:username: root # 测试环…

windows第十八章 菜单、工具栏、状态栏

文章目录 创建框架窗口菜单菜单的风格通过资源创建菜单菜单的各种使用通过代码创建菜单在鼠标位置右键弹出菜单 CMenu常用函数介绍工具栏方式一&#xff0c;从资源创建工具栏方式二&#xff0c;代码创建 状态栏状态栏基础创建状态栏 创建框架窗口 手动创建一个空项目&#xff…