吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2280|回复: 19
收起左侧

[Windows] 电脑软硬件信息的收集工具

[复制链接]
laldyf 发表于 2026-3-19 09:09
可用于局域网电脑的硬件信息收集
客户端采用autlot编写,硬盘使用smart工具收集信息,显示器使用monitorinfoview来收集,使用AI工具编写的
通过网盘分享的文件:电脑信息收集工具
链接: https://pan.baidu.com/s/1J932921yMM8XieBu46SOmA?pwd=ysqu 提取码: ysqu
服务端运行会生成日志文件夹logs,reports是收集到的每个电脑的信息,命名为部门+用户+时间

生成文件

生成文件

image.png

客户端运行

客户端运行


服务端运行

服务端运行


服务端日志

服务端日志




客户端代码:
[Asm] 纯文本查看 复制代码
#RequireAdmin
#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=
#AutoIt3Wrapper_Outfile=ComputerInfoCollector.exe
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_UseUpx=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <File.au3>
#include <String.au3>

; 定义资源文件路径和提取路径
Global $sBinDir = @TempDir & "\bin"
Global $sMonitorInfoDir = @TempDir & "\monitorinfoview"

; 创建临时目录
DirCreate($sBinDir)
DirCreate($sMonitorInfoDir)

; 嵌入bin目录下的文件
FileInstall("bin\drivedb.h", $sBinDir & "\drivedb.h", 1)
FileInstall("bin\runcmdu.exe", $sBinDir & "\runcmdu.exe", 1)
FileInstall("bin\smartctl-nc.exe", $sBinDir & "\smartctl-nc.exe", 1)
FileInstall("bin\smartctl.exe", $sBinDir & "\smartctl.exe", 1)
FileInstall("bin\smartd.conf", $sBinDir & "\smartd.conf", 1)
FileInstall("bin\smartd.exe", $sBinDir & "\smartd.exe", 1)
FileInstall("bin\smartd_mailer.conf.sample.ps1", $sBinDir & "\smartd_mailer.conf.sample.ps1", 1)
FileInstall("bin\smartd_mailer.ps1", $sBinDir & "\smartd_mailer.ps1", 1)
FileInstall("bin\smartd_warning.cmd", $sBinDir & "\smartd_warning.cmd", 1)
FileInstall("bin\update-smart-drivedb.ps1", $sBinDir & "\update-smart-drivedb.ps1", 1)
FileInstall("bin\wtssendmsg.exe", $sBinDir & "\wtssendmsg.exe", 1)

; 嵌入monitorinfoview目录下的文件
FileInstall("monitorinfoview\MonitorInfoView.cfg", $sMonitorInfoDir & "\MonitorInfoView.cfg", 1)
FileInstall("monitorinfoview\MonitorInfoView.chm", $sMonitorInfoDir & "\MonitorInfoView.chm", 1)
FileInstall("monitorinfoview\MonitorInfoView.exe", $sMonitorInfoDir & "\MonitorInfoView.exe", 1)
FileInstall("monitorinfoview\MonitorInfoView_lng.ini", $sMonitorInfoDir & "\MonitorInfoView_lng.ini", 1)
FileInstall("monitorinfoview\readme.txt", $sMonitorInfoDir & "\readme.txt", 1)
FileInstall("monitorinfoview\temp_monitors.csv", $sMonitorInfoDir & "\temp_monitors.csv", 1)

; 启用OnEvent模式
Opt("GUIOnEventMode", 1)

; 全局变量
Global $sCurrentDir = @ScriptDir
Global $iMonitorCount = 1
Global $aMonitorsInfo[0][3] ; 存储显示器详细信息:[品牌型号, 序列号, 大小]

Global $sMonitorDir = $sMonitorInfoDir ; 使用临时目录中的monitorinfoview

; 检查管理员权限
If Not IsAdmin() Then
    MsgBox(48, "权限错误", "此程序需要以管理员身份运行!" & @CRLF & "请右键选择""以管理员身份运行""")
    Exit
EndIf



; 创建主窗口
Local $hMainGUI = GUICreate("电脑信息收集工具", 920, 680, -1, -1)
GUISetBkColor(0xF0F0F0, $hMainGUI)
GUISetFont(9, 400, 0, "微软雅黑")

; 创建信息显示区域
Local $hInfoGroup = GUICtrlCreateGroup("系统信息", 15, 15, 890, 280)
GUICtrlSetFont(-1, 11, 600, 0, "微软雅黑")
GUICtrlSetColor(-1, 0x2C3E50)

; 计算机名
Local $hLabel1 = GUICtrlCreateLabel("计算机名:", 25, 42, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hComputerName = GUICtrlCreateInput("", 135, 40, 220, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; 用户名
Local $hLabel2 = GUICtrlCreateLabel("用户名:", 375, 42, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hUserName = GUICtrlCreateInput("", 485, 40, 150, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; 系统版本
Local $hLabel3 = GUICtrlCreateLabel("系统版本:", 25, 75, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hOSVersion = GUICtrlCreateInput("", 135, 73, 220, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; CPU型号
Local $hLabel4 = GUICtrlCreateLabel("CPU型号:", 375, 75, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hCPUModel = GUICtrlCreateInput("", 485, 73, 350, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; 内存总大小
Local $hLabel5 = GUICtrlCreateLabel("内存总大小:", 25, 108, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hMemorySize = GUICtrlCreateInput("", 135, 106, 200, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; 操作系统安装日期
Local $hLabel5_1 = GUICtrlCreateLabel("操作系统安装日期:", 375, 108, 120, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hOSInstallDate = GUICtrlCreateInput("", 505, 106, 200, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; 硬盘信息
Local $hLabel6 = GUICtrlCreateLabel("硬盘信息:", 25, 140, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hDiskInfo = GUICtrlCreateEdit("", 135, 138, 700, 55, BitOR($ES_READONLY, $ES_WANTRETURN, $WS_VSCROLL))
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetFont(-1, 9, 400, 0, "Consolas")

; MAC地址
Local $hLabel7 = GUICtrlCreateLabel("MAC地址:", 25, 200, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hMACAddress = GUICtrlCreateInput("", 135, 198, 220, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; IP地址
Local $hLabel8 = GUICtrlCreateLabel("IP地址:", 375, 200, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hIPAddress = GUICtrlCreateInput("", 485, 198, 220, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_DISABLE)

; 显示器信息(自动获取)
Local $hLabel9 = GUICtrlCreateLabel("显示器信息(自动获取):", 25, 232, 150, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hMonitorAutoInfo = GUICtrlCreateEdit("", 185, 230, 700, 55, BitOR($ES_READONLY, $ES_WANTRETURN, $WS_VSCROLL))
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetFont(-1, 9, 400, 0, "Consolas")

GUICtrlCreateGroup("", -99, -99, 1, 1) ; 关闭组

; 用户输入区域
Local $hInputGroup = GUICtrlCreateGroup("用户输入信息", 15, 305, 890, 320)
GUICtrlSetFont(-1, 11, 600, 0, "微软雅黑")
GUICtrlSetColor(-1, 0x2C3E50)

; 电脑主机编号
Local $hLabel10 = GUICtrlCreateLabel("电脑主机编号:", 25, 332, 110, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hHostNumber = GUICtrlCreateInput("ZDBG02-", 145, 330, 240, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetOnEvent($hHostNumber, "OnHostNumberChange")

; 显示器数量选择(单选按钮)
Local $hLabel11 = GUICtrlCreateLabel("显示器数量:", 405, 332, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hMonitorCount1 = GUICtrlCreateRadio("1个", 515, 330, 60, 24)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlSetOnEvent(-1, "OnMonitorCountChange")
Local $hMonitorCount2 = GUICtrlCreateRadio("2个", 585, 330, 60, 24)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
GUICtrlSetOnEvent(-1, "OnMonitorCountChange")

; 显示器编号输入
Local $hMonitorGroup = GUICtrlCreateGroup("显示器编号", 25, 365, 860, 70)
GUICtrlSetFont(-1, 9, 600, 0, "微软雅黑")
Local $hLabel12 = GUICtrlCreateLabel("显示器1编号:", 35, 390, 110, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hMonitor1Number = GUICtrlCreateInput("ZDBG01-", 155, 388, 240, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetOnEvent($hMonitor1Number, "OnMonitor1NumberChange")
Local $hMonitor2NumberLabel = GUICtrlCreateLabel("显示器2编号:", 415, 390, 110, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
GUICtrlSetState(-1, $GUI_HIDE)
Local $hMonitor2Number = GUICtrlCreateInput("ZDBG01-", 535, 388, 240, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetState(-1, $GUI_HIDE)
GUICtrlSetOnEvent($hMonitor2Number, "OnMonitor2NumberChange")
GUICtrlCreateGroup("", -99, -99, 1, 1)

; 使用部门
Local $hLabel13 = GUICtrlCreateLabel("使用部门:", 25, 450, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hDepartment = GUICtrlCreateCombo("", 135, 448, 150, 28, $CBS_DROPDOWNLIST)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetData(-1, "质量部|财务部|采购部|保密办|技术部|总经办|总体部|软件部|综合部|商务部|生产部", "")

; 责任人
Local $hLabel14 = GUICtrlCreateLabel("责任人:", 320, 450, 80, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hResponsible = GUICtrlCreateInput("", 400, 448, 150, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)

; 用途
Local $hLabel15 = GUICtrlCreateLabel("用途:", 570, 450, 50, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hPurpose = GUICtrlCreateCombo("", 620, 448, 140, 28, $CBS_DROPDOWNLIST)
GUICtrlSetBkColor(-1, 0xFFFFFF)
GUICtrlSetData(-1, "办公|测试|服务器|中间转换|其他", "")

; 服务端配置
Local $hServerGroup = GUICtrlCreateGroup("服务端配置", 25, 500, 860, 100)
GUICtrlSetFont(-1, 9, 600, 0, "微软雅黑")

; 服务端IP
Local $hLabel16 = GUICtrlCreateLabel("服务端IP:", 45, 530, 80, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hServerIP = GUICtrlCreateInput("127.0.0.1", 135, 528, 150, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)

; 服务端端口
Local $hLabel17 = GUICtrlCreateLabel("服务端端口:", 320, 530, 100, 22)
GUICtrlSetFont(-1, 9, 400, 0, "微软雅黑")
Local $hServerPort = GUICtrlCreateInput("8000", 430, 528, 80, 26)
GUICtrlSetBkColor(-1, 0xFFFFFF)

GUICtrlCreateGroup("", -99, -99, 1, 1) ; 关闭组

GUICtrlCreateGroup("", -99, -99, 1, 1) ; 关闭组

; 按钮
Local $hCollectBtn = GUICtrlCreateButton("收集系统信息", 15, 640, 130, 35)
GUICtrlSetFont(-1, 10, 600, 0, "微软雅黑")
GUICtrlSetBkColor(-1, 0x3498DB)
GUICtrlSetColor(-1, 0xFFFFFF)
Local $hSaveBtn = GUICtrlCreateButton("保存报告", 160, 640, 130, 35)
GUICtrlSetFont(-1, 10, 600, 0, "微软雅黑")
GUICtrlSetBkColor(-1, 0x27AE60)
GUICtrlSetColor(-1, 0xFFFFFF)
Local $hSendBtn = GUICtrlCreateButton("发送到服务端", 305, 640, 130, 35)
GUICtrlSetFont(-1, 10, 600, 0, "微软雅黑")
GUICtrlSetBkColor(-1, 0x9B59B6)
GUICtrlSetColor(-1, 0xFFFFFF)
Local $hExitBtn = GUICtrlCreateButton("退出", 450, 640, 130, 35)
GUICtrlSetFont(-1, 10, 600, 0, "微软雅黑")
GUICtrlSetBkColor(-1, 0xE74C3C)
GUICtrlSetColor(-1, 0xFFFFFF)

; 设置事件
GUICtrlSetOnEvent($hCollectBtn, "OnCollectInfo")
GUICtrlSetOnEvent($hSaveBtn, "OnSaveReport")
GUICtrlSetOnEvent($hSendBtn, "OnSendToServer")
GUICtrlSetOnEvent($hExitBtn, "OnExit")

; 设置窗口关闭事件
GUISetOnEvent($GUI_EVENT_CLOSE, "OnExit", $hMainGUI)

; 显示窗口
GUISetState(@SW_SHOW)

; 自动收集信息
OnCollectInfo()

; 消息循环
While 1
    Sleep(100)
WEnd

GUIDelete($hMainGUI)

; 收集系统信息
Func OnCollectInfo()
    GUICtrlSetData($hCollectBtn, "正在收集...")
    GUICtrlSetState($hCollectBtn, $GUI_DISABLE)
    
    ; 收集基本信息
    Local $sComputerName = @ComputerName
    Local $sUserName = @UserName
    Local $sOSVersion = GetOSVersion()
    
    GUICtrlSetData($hComputerName, $sComputerName)
    GUICtrlSetData($hUserName, $sUserName)
    GUICtrlSetData($hOSVersion, $sOSVersion)
    
    ; 收集CPU和内存信息
    CollectCPUAndMemory()
    
    ; 收集硬盘信息
    CollectDiskInfo()
    
    ; 收集网络信息
    CollectNetworkInfo()
    
    ; 收集显示器信息
    CollectMonitorInfo()
    
    GUICtrlSetData($hCollectBtn, "收集系统信息")
    GUICtrlSetState($hCollectBtn, $GUI_ENABLE)
EndFunc

; 收集CPU和内存信息
Func CollectCPUAndMemory()
    Local $sCPU = RegRead("HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0", "ProcessorNameString")
    If [url=home.php?mod=space&uid=209627]@Error[/url] Then
        $sCPU = "未知"
    EndIf
    GUICtrlSetData($hCPUModel, $sCPU)
    
    ; 获取内存大小
    Local $aMemInfo = MemGetStats()
    Local $iTotalMemGB = Round($aMemInfo[1] / 1024 / 1024, 2)
    GUICtrlSetData($hMemorySize, $iTotalMemGB & " GB")
    
    ; 获取操作系统安装日期
    Local $sInstallDate = GetOSInstallDate()
    GUICtrlSetData($hOSInstallDate, $sInstallDate)
EndFunc

; 收集硬盘信息
Func CollectDiskInfo()
    Local $sDiskInfo = ""
    
    ; 使用bin目录下的smartctl工具
    Local $sSmartctlExe = $sBinDir & "\smartctl.exe"
    
    If Not FileExists($sSmartctlExe) Then
        GUICtrlSetData($hDiskInfo, "错误: 找不到 smartctl.exe 工具")
        Return
    EndIf
    
    ; 创建临时文件保存硬盘信息
    Local $sTempFile = @TempDir & "\disk_info_" & [url=home.php?mod=space&uid=597021]@year[/url] & [url=home.php?mod=space&uid=556771]@Mon[/url] & [url=home.php?mod=space&uid=501075]@Mday[/url] & "_" & @HOUR & @MIN & @SEC & ".txt"
    Local $hTempFile = FileOpen($sTempFile, 2 + 8) ; 写入模式,UTF8
    If $hTempFile = -1 Then
        GUICtrlSetData($hDiskInfo, "错误: 无法创建临时文件")
        Return
    EndIf
    
    FileWriteLine($hTempFile, "=== 硬盘信息收集 ===" & @CRLF)
    FileWriteLine($hTempFile, "时间: " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF)
    
    ; 优先使用smartctl --scan获取设备列表(包含设备类型信息)
    Local $iFoundCount = 0
    Local $sScanOutput = ""
    
    ; 执行smartctl --scan
    Local $sScanCmd = 'cmd /c cd /d "' & $sBinDir & '" && smartctl.exe --scan'
    Local $iScanPID = Run($sScanCmd, "", @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD)
    
    If Not @error Then
        ; 等待进程完成
        While ProcessExists($iScanPID)
            $sScanOutput &= StdoutRead($iScanPID)
            If @error Then ExitLoop
            Sleep(100)
        WEnd
        ; 读取剩余输出
        $sScanOutput &= StdoutRead($iScanPID)
    EndIf
    
    ; 保存扫描结果到文件
    If $sScanOutput <> "" Then
        FileWriteLine($hTempFile, "=== smartctl --scan 输出 ===")
        FileWriteLine($hTempFile, $sScanOutput)
        FileWriteLine($hTempFile, @CRLF)
    Else
        FileWriteLine($hTempFile, "smartctl --scan 无输出或执行失败")
        FileWriteLine($hTempFile, @CRLF)
    EndIf
    
    ; 解析扫描结果
    Local $aScannedDisks = ParseSmartctlScan($sScanOutput)
    
    ; 保存解析结果
    If UBound($aScannedDisks) > 0 Then
        FileWriteLine($hTempFile, "=== 解析到的设备数量: " & UBound($aScannedDisks) & " ===")
        For $k = 0 To UBound($aScannedDisks) - 1
            FileWriteLine($hTempFile, "设备 " & ($k + 1) & ": " & $aScannedDisks[$k][0] & " 类型: " & $aScannedDisks[$k][1])
        Next
        FileWriteLine($hTempFile, @CRLF)
    Else
        FileWriteLine($hTempFile, "未解析到设备")
        FileWriteLine($hTempFile, @CRLF)
    EndIf
    
    ; 对扫描到的每个设备获取详细信息
    For $j = 0 To UBound($aScannedDisks) - 1
        Local $sScannedPath = $aScannedDisks[$j][0]
        Local $sScannedType = $aScannedDisks[$j][1]
        
        FileWriteLine($hTempFile, "=== 正在获取设备信息: " & $sScannedPath & " (类型: " & $sScannedType & ") ===")
        
        ; 获取完整原始输出
        Local $sFullOutput = GetDiskFullOutput($sScannedPath, $sScannedType)
        If $sFullOutput <> "" Then
            FileWriteLine($hTempFile, $sFullOutput)
            FileWriteLine($hTempFile, @CRLF)
            
            ; 解析并显示到界面
            Local $sParsedInfo = ParseDiskInfo($sFullOutput)
            If $sParsedInfo <> "" Then
                If $sDiskInfo <> "" Then $sDiskInfo &= @CRLF
                $sDiskInfo &= "硬盘 " & ($iFoundCount + 1) & ": " & $sParsedInfo
                $iFoundCount += 1
            EndIf
        Else
            FileWriteLine($hTempFile, "无法获取该设备信息")
            FileWriteLine($hTempFile, @CRLF)
        EndIf
    Next
    
    ; 如果扫描失败,尝试直接扫描PhysicalDrive0-9
    If $iFoundCount = 0 Then
        FileWriteLine($hTempFile, "=== 尝试直接扫描 PhysicalDrive ===")
        For $i = 0 To 9
            Local $sTestPath = "\\.\PhysicalDrive" & $i
            FileWriteLine($hTempFile, "尝试: " & $sTestPath)
            
            ; 获取完整原始输出
            Local $sFullOutput = GetDiskFullOutput($sTestPath)
            If $sFullOutput <> "" Then
                FileWriteLine($hTempFile, $sFullOutput)
                FileWriteLine($hTempFile, @CRLF)
                
                ; 检查是否有有效信息
                If StringInStr($sFullOutput, "Model Number") > 0 Or StringInStr($sFullOutput, "Device Model") > 0 Or StringInStr($sFullOutput, "Serial Number") > 0 Then
                    Local $sParsedInfo = ParseDiskInfo($sFullOutput)
                    If $sParsedInfo <> "" Then
                        If $sDiskInfo <> "" Then $sDiskInfo &= @CRLF
                        $sDiskInfo &= "硬盘 " & ($iFoundCount + 1) & ": " & $sParsedInfo
                        $iFoundCount += 1
                    EndIf
                EndIf
            EndIf
        Next
    EndIf
    
    FileClose($hTempFile)
    
    If $iFoundCount = 0 Then
        $sDiskInfo = "未找到物理磁盘" & @CRLF & "请确保以管理员身份运行"
    EndIf
    
    GUICtrlSetData($hDiskInfo, $sDiskInfo)
EndFunc

; 解析硬盘信息(从完整输出中提取关键信息)
Func ParseDiskInfo($sFullOutput)
    Local $sResult = ""
    
    ; 解析输出
    Local $sModel = ExtractSmartctlValue($sFullOutput, "Device Model")
    If $sModel = "" Then 
        $sModel = ExtractSmartctlValue($sFullOutput, "Model Family")
    EndIf
    If $sModel = "" Then
        $sModel = ExtractSmartctlValue($sFullOutput, "Model Number")
    EndIf
    
    Local $sSerial = ExtractSmartctlValue($sFullOutput, "Serial Number")
    If $sSerial = "" Then
        $sSerial = ExtractSmartctlValue($sFullOutput, "Serial number")
    EndIf
    
    ; 获取容量(支持多种格式)
    Local $sCapacity = ExtractSmartctlValue($sFullOutput, "User Capacity")
    If $sCapacity = "" Then
        $sCapacity = ExtractSmartctlValue($sFullOutput, "Total NVM Capacity")
    EndIf
    If $sCapacity = "" Then
        $sCapacity = ExtractSmartctlValue($sFullOutput, "Total capacity")
    EndIf
    
    ; 格式化容量
    Local $sFormattedCapacity = ""
    If $sCapacity <> "" Then
        ; 支持 [1.02 TB] 格式
        Local $aCapacityTB = StringRegExp($sCapacity, "\[(\d+\.?\d*)\s+TB\]", 1)
        If @error = 0 And UBound($aCapacityTB) > 0 Then
            Local $fTB = Number($aCapacityTB[0])
            Local $iGB = Round($fTB * 1024, 2)
            $sFormattedCapacity = $iGB & " GB"
        Else
            ; 尝试 [bytes] 格式
            Local $aCapacity = StringRegExp($sCapacity, "\[(\d+)\s+bytes\]", 1)
            If @error = 0 And UBound($aCapacity) > 0 Then
                Local $iBytes = Number($aCapacity[0])
                Local $iGB = Round($iBytes / 1024 / 1024 / 1024, 2)
                $sFormattedCapacity = $iGB & " GB"
            Else
                ; 尝试其他格式
                Local $aGB = StringRegExp($sCapacity, "(\d+\.?\d*)\s*GB", 1)
                If @error = 0 And UBound($aGB) > 0 Then
                    $sFormattedCapacity = $aGB[0] & " GB"
                Else
                    $sFormattedCapacity = $sCapacity
                EndIf
            EndIf
        EndIf
    EndIf
    
    ; 格式化显示:型号 | 序列号 | 大小
    If $sModel <> "" Or $sSerial <> "" Or $sFormattedCapacity <> "" Then
        Local $aParts[0]
        
        If $sModel <> "" Then
            ReDim $aParts[UBound($aParts) + 1]
            $aParts[UBound($aParts) - 1] = "型号: " & $sModel
        EndIf
        
        If $sSerial <> "" Then
            ReDim $aParts[UBound($aParts) + 1]
            $aParts[UBound($aParts) - 1] = "序列号: " & $sSerial
        EndIf
        
        If $sFormattedCapacity <> "" Then
            ReDim $aParts[UBound($aParts) + 1]
            $aParts[UBound($aParts) - 1] = "大小: " & $sFormattedCapacity
        EndIf
        
        ; 用 | 分隔
        $sResult = _ArrayToString($aParts, " | ")
    EndIf
    
    Return $sResult
EndFunc

; 获取磁盘完整原始输出(用于调试)
Func GetDiskFullOutput($sDiskPath, $sDeviceType = "")
    Local $sSmartctlExe = $sBinDir & "\smartctl.exe"
    Local $sResult = ""
    
    ; 如果未指定设备类型,尝试不同的设备类型
    Local $aDeviceTypes[5] = ["nvme", "sat", "ata", "scsi", ""]
    
    ; 如果指定了设备类型,优先使用
    If $sDeviceType <> "" Then
        $aDeviceTypes[0] = $sDeviceType
        ReDim $aDeviceTypes[1]
    EndIf
    
    For $i = 0 To UBound($aDeviceTypes) - 1
        Local $sCurrentType = $aDeviceTypes[$i]
        Local $sCmd = ""
        
        ; 使用 -a 参数获取完整信息
        If $sCurrentType = "" Then
            $sCmd = 'cmd /c cd /d "' & $sBinDir & '" && smartctl.exe -a "' & $sDiskPath & '"'
        Else
            $sCmd = 'cmd /c cd /d "' & $sBinDir & '" && smartctl.exe -d ' & $sCurrentType & ' -a "' & $sDiskPath & '"'
        EndIf
        
        Local $iPID = Run($sCmd, "", @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD)
        If @error Then ContinueLoop
        
        Local $sOutput = ""
        While ProcessExists($iPID)
            $sOutput &= StdoutRead($iPID)
            If @error Then ExitLoop
            Sleep(100)
        WEnd
        ; 读取剩余输出
        $sOutput &= StdoutRead($iPID)
        
        ; 检查是否有错误
        If StringInStr($sOutput, "Unable to detect device type") > 0 Or StringInStr($sOutput, "Device open failed") > 0 Then
            ContinueLoop
        EndIf
        
        ; 如果有任何输出,返回(用于调试)
        If $sOutput <> "" Then
            $sResult = "命令: " & $sCmd & @CRLF & @CRLF & $sOutput
            ExitLoop
        EndIf
    Next
    
    Return $sResult
EndFunc

; 解析smartctl --scan的输出
Func ParseSmartctlScan($sOutput)
    Local $aResult[0][2] ; [设备路径, 设备类型]
    
    If $sOutput = "" Then Return $aResult
    
    ; 按行分割
    Local $aLines = StringSplit($sOutput, @CRLF, 1)
    If @error Then
        $aLines = StringSplit($sOutput, @LF, 1)
    EndIf
    
    For $i = 1 To $aLines[0]
        Local $sLine = StringStripWS($aLines[$i], 3)
        If $sLine = "" Then ContinueLoop
        
        ; 提取设备路径和类型
        ; 格式: /dev/sda -d nvme # /dev/sda, NVMe device
        ; 或者: \\.\PhysicalDrive0 -d nvme
        ; 使用正则表达式匹配:设备路径 可选-d 设备类型
        Local $aMatch = StringRegExp($sLine, "^([^\s]+)(?:\s+-d\s+([^\s]+))?", 1)
        If @error = 0 And UBound($aMatch) > 0 Then
            Local $sDevice = StringStripWS($aMatch[0], 3)
            Local $sDeviceType = ""
            If UBound($aMatch) > 1 And $aMatch[1] <> "" Then
                $sDeviceType = StringStripWS($aMatch[1], 3)
            EndIf
            
            ; 如果是Windows路径格式,直接使用
            If StringInStr($sDevice, "\\.\PhysicalDrive") > 0 Then
                ReDim $aResult[UBound($aResult) + 1][2]
                $aResult[UBound($aResult) - 1][0] = $sDevice
                $aResult[UBound($aResult) - 1][1] = $sDeviceType
            ; 如果是Linux格式(/dev/sda),直接使用,smartctl支持
            ElseIf StringInStr($sDevice, "/dev/") > 0 Then
                ReDim $aResult[UBound($aResult) + 1][2]
                $aResult[UBound($aResult) - 1][0] = $sDevice
                $aResult[UBound($aResult) - 1][1] = $sDeviceType
            EndIf
        EndIf
    Next
    
    Return $aResult
EndFunc

; 从smartctl获取单个磁盘的详细信息
Func GetDiskInfoFromSmartctl($sDiskPath, $sDeviceType = "")
    Local $sSmartctlExe = $sBinDir & "\smartctl.exe"
    Local $sResult = ""
    
    ; 如果未指定设备类型,尝试不同的设备类型(NVMe、SATA、IDE等)
    Local $aDeviceTypes[5] = ["nvme", "sat", "ata", "scsi", ""]
    
    ; 如果指定了设备类型,优先使用
    If $sDeviceType <> "" Then
        $aDeviceTypes[0] = $sDeviceType
        ReDim $aDeviceTypes[1]
    EndIf
    
    For $i = 0 To UBound($aDeviceTypes) - 1
        Local $sCurrentType = $aDeviceTypes[$i]
        Local $sCmd = ""
        
        ; 使用 -a 参数获取完整信息(包括Model Number, Serial Number等)
        If $sCurrentType = "" Then
            ; 不指定设备类型,让smartctl自动检测
            $sCmd = '"' & $sSmartctlExe & '" -a "' & $sDiskPath & '"'
        Else
            ; 指定设备类型
            $sCmd = '"' & $sSmartctlExe & '" -d ' & $sCurrentType & ' -a "' & $sDiskPath & '"'
        EndIf
        
        Local $iPID = Run($sCmd, $sBinDir, @SW_HIDE, $STDOUT_CHILD)
        If @error Then ContinueLoop
        
        Local $sOutput = ""
        While ProcessExists($iPID)
            $sOutput &= StdoutRead($iPID)
            If @error Then ExitLoop
            Sleep(100)
        WEnd
        
        ; 检查是否有错误
        If StringInStr($sOutput, "Unable to detect device type") > 0 Or StringInStr($sOutput, "Device open failed") > 0 Or StringInStr($sOutput, "Read Device Identity failed") > 0 Then
            ContinueLoop
        EndIf
        
        ; 检查是否有有效信息(检查关键字段是否存在)
        Local $bHasValidInfo = False
        If StringInStr($sOutput, "Model Number") > 0 Or StringInStr($sOutput, "Device Model") > 0 Or StringInStr($sOutput, "Model Family") > 0 Then
            $bHasValidInfo = True
        EndIf
        If StringInStr($sOutput, "Serial Number") > 0 Or StringInStr($sOutput, "Serial number") > 0 Then
            $bHasValidInfo = True
        EndIf
        If StringInStr($sOutput, "Total NVM Capacity") > 0 Or StringInStr($sOutput, "User Capacity") > 0 Or StringInStr($sOutput, "Total capacity") > 0 Then
            $bHasValidInfo = True
        EndIf
        
        If $bHasValidInfo Then
            ; 解析输出
            Local $sModel = ExtractSmartctlValue($sOutput, "Device Model")
            If $sModel = "" Then 
                $sModel = ExtractSmartctlValue($sOutput, "Model Family")
            EndIf
            If $sModel = "" Then
                $sModel = ExtractSmartctlValue($sOutput, "Model Number")
            EndIf
            
            Local $sSerial = ExtractSmartctlValue($sOutput, "Serial Number")
            If $sSerial = "" Then
                $sSerial = ExtractSmartctlValue($sOutput, "Serial number")
            EndIf
            
            ; 获取容量(支持多种格式)
            Local $sCapacity = ExtractSmartctlValue($sOutput, "User Capacity")
            If $sCapacity = "" Then
                $sCapacity = ExtractSmartctlValue($sOutput, "Total NVM Capacity")
            EndIf
            If $sCapacity = "" Then
                $sCapacity = ExtractSmartctlValue($sOutput, "Total capacity")
            EndIf
            
            ; 如果至少有一个有效信息,返回结果
            If $sModel <> "" Or $sSerial <> "" Or $sCapacity <> "" Then
                If $sModel <> "" Then
                    $sResult &= "  型号: " & $sModel & @CRLF
                EndIf
                If $sSerial <> "" Then
                    $sResult &= "  序列号: " & $sSerial & @CRLF
                EndIf
                If $sCapacity <> "" Then
                    ; 格式化容量 - 支持 [1.02 TB] 格式
                    Local $aCapacityTB = StringRegExp($sCapacity, "\[(\d+\.?\d*)\s+TB\]", 1)
                    If @error = 0 And UBound($aCapacityTB) > 0 Then
                        Local $fTB = Number($aCapacityTB[0])
                        Local $iGB = Round($fTB * 1024, 2)
                        $sResult &= "  大小: " & $iGB & " GB"
                    Else
                        ; 尝试 [bytes] 格式
                        Local $aCapacity = StringRegExp($sCapacity, "\[(\d+)\s+bytes\]", 1)
                        If @error = 0 And UBound($aCapacity) > 0 Then
                            Local $iBytes = Number($aCapacity[0])
                            Local $iGB = Round($iBytes / 1024 / 1024 / 1024, 2)
                            $sResult &= "  大小: " & $iGB & " GB"
                        Else
                            ; 尝试其他格式
                            Local $aGB = StringRegExp($sCapacity, "(\d+\.?\d*)\s*GB", 1)
                            If @error = 0 And UBound($aGB) > 0 Then
                                $sResult &= "  大小: " & $aGB[0] & " GB"
                            Else
                                $sResult &= "  大小: " & $sCapacity
                            EndIf
                        EndIf
                    EndIf
                EndIf
                ; 找到有效信息,退出循环
                ExitLoop
            EndIf
        EndIf
    Next
    
    Return $sResult
EndFunc

; 从smartctl输出中提取值
Func ExtractSmartctlValue($sOutput, $sKey)
    ; 尝试多种模式匹配
    Local $aPatterns[3] = [$sKey & ":\s+(.+?)(?:\r\n|\r|\n)", $sKey & "\s+:\s+(.+?)(?:\r\n|\r|\n)", $sKey & ":\s+(.+?)$"]
    
    For $i = 0 To UBound($aPatterns) - 1
        Local $aMatches = StringRegExp($sOutput, $aPatterns[$i], 1)
        If @error = 0 And UBound($aMatches) > 0 Then
            Local $sValue = StringStripWS($aMatches[0], 3)
            ; 移除可能的注释部分(# 后面的内容)
            Local $iCommentPos = StringInStr($sValue, " #")
            If $iCommentPos > 0 Then
                $sValue = StringLeft($sValue, $iCommentPos - 1)
            EndIf
            Return StringStripWS($sValue, 3)
        EndIf
    Next
    
    Return ""
EndFunc

; 获取操作系统版本信息
Func GetOSVersion()
    Local $sVersion = ""
    
    ; 获取Windows版本号
    Local $sOSName = @OSVersion
    Local $sArch = @OSArch
    
    ; 获取Windows版本名称(家庭版/专业版等)
    Local $sEdition = ""
    Local $oWMIService = ObjGet("winmgmts:\\.\root\cimv2")
    If Not @error Then
        Local $oOS = $oWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem")
        For $oItem In $oOS
            $sEdition = $oItem.Caption
            ; 提取版本信息,例如 "Microsoft Windows 11 家庭版" -> "Windows 11 家庭版"
            Local $aMatch = StringRegExp($sEdition, "Windows\s+(\d+)\s*(.+)", 1)
            If @error = 0 And UBound($aMatch) >= 2 Then
                $sVersion = "Windows " & $aMatch[0] & " " & $aMatch[1]
            Else
                ; 如果正则匹配失败,尝试简单提取
                If StringInStr($sEdition, "Windows 11") > 0 Then
                    $sVersion = "Windows 11"
                    If StringInStr($sEdition, "家庭") > 0 Then
                        $sVersion &= " 家庭版"
                    ElseIf StringInStr($sEdition, "专业") > 0 Then
                        $sVersion &= " 专业版"
                    ElseIf StringInStr($sEdition, "企业") > 0 Then
                        $sVersion &= " 企业版"
                    ElseIf StringInStr($sEdition, "教育") > 0 Then
                        $sVersion &= " 教育版"
                    EndIf
                ElseIf StringInStr($sEdition, "Windows 10") > 0 Then
                    $sVersion = "Windows 10"
                    If StringInStr($sEdition, "家庭") > 0 Then
                        $sVersion &= " 家庭版"
                    ElseIf StringInStr($sEdition, "专业") > 0 Then
                        $sVersion &= " 专业版"
                    ElseIf StringInStr($sEdition, "企业") > 0 Then
                        $sVersion &= " 企业版"
                    ElseIf StringInStr($sEdition, "教育") > 0 Then
                        $sVersion &= " 教育版"
                    EndIf
                EndIf
            EndIf
            ExitLoop
        Next
    EndIf
    
    ; 如果无法获取,使用默认格式
    If $sVersion = "" Then
        $sVersion = $sOSName
    EndIf
    
    ; 添加架构信息(去掉X)
    Local $sArchClean = StringReplace($sArch, "X", "")
    $sVersion &= " " & $sArchClean & "位"
    
    Return $sVersion
EndFunc

; 获取操作系统安装日期
Func GetOSInstallDate()
    Local $sInstallDate = "未知"
    
    ; 使用WMI获取操作系统安装日期
    Local $oWMIService = ObjGet("winmgmts:\\.\root\cimv2")
    If Not @error Then
        Local $oOS = $oWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem")
        For $oItem In $oOS
            ; 获取安装日期(WMI返回的是UTC时间戳,需要转换)
            Local $sWMIInstallDate = $oItem.InstallDate
            If $sWMIInstallDate <> "" Then
                ; 转换WMI日期格式:YYYYMMDDHHMMSS.FFFFFF+000 -> YYYY-MM-DD HH:MM:SS
                Local $sYear = StringMid($sWMIInstallDate, 1, 4)
                Local $sMonth = StringMid($sWMIInstallDate, 5, 2)
                Local $sDay = StringMid($sWMIInstallDate, 7, 2)
                Local $sHour = StringMid($sWMIInstallDate, 9, 2)
                Local $sMinute = StringMid($sWMIInstallDate, 11, 2)
                Local $sSecond = StringMid($sWMIInstallDate, 13, 2)
                
                $sInstallDate = $sYear & "-" & $sMonth & "-" & $sDay & " " & $sHour & ":" & $sMinute & ":" & $sSecond
            EndIf
            ExitLoop
        Next
    EndIf
    
    Return $sInstallDate
EndFunc

; 收集网络信息
Func CollectNetworkInfo()
    Local $sMAC = ""
    Local $sIP = ""
    
    ; 使用WMI获取网络适配器信息
    Local $oWMIService = ObjGet("winmgmts:\\.\root\cimv2")
    If @error Then
        GUICtrlSetData($hMACAddress, "无法获取")
        GUICtrlSetData($hIPAddress, "无法获取")
        Return
    EndIf
    
    ; 获取所有已连接的网络适配器(状态码2表示已连接)
    Local $oAdapters = $oWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionStatus = 2 AND MACAddress IS NOT NULL")
    
    For $oAdapter In $oAdapters
        Local $sName = $oAdapter.Description
        Local $sAdapterMAC = $oAdapter.MACAddress
        
        ; 跳过虚拟适配器
        If StringInStr($sName, "Virtual") > 0 Or StringInStr($sName, "VMware") > 0 Or StringInStr($sName, "VirtualBox") > 0 Then
            ContinueLoop
        EndIf
        
        ; 跳过无效的MAC地址(全0或全F)
        If $sAdapterMAC = "00:00:00:00:00:00" Or $sAdapterMAC = "FF:FF:FF:FF:FF:FF" Then
            ContinueLoop
        EndIf
        
        ; 获取IP地址
        Local $sAdapterIP = ""
        Local $oConfigs = $oWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index = " & $oAdapter.Index)
        For $oConfig In $oConfigs
            If IsObj($oConfig) And $oConfig.IPAddress <> "" Then
                If IsArray($oConfig.IPAddress) Then
                    If UBound($oConfig.IPAddress) > 0 Then
                        ; 优先获取IPv4地址
                        For $i = 0 To UBound($oConfig.IPAddress) - 1
                            If StringInStr($oConfig.IPAddress[$i], ":") = 0 Then ; 不是IPv6
                                $sAdapterIP = $oConfig.IPAddress[$i]
                                ExitLoop
                            EndIf
                        Next
                        If $sAdapterIP = "" And UBound($oConfig.IPAddress) > 0 Then
                            $sAdapterIP = $oConfig.IPAddress[0]
                        EndIf
                    EndIf
                Else
                    $sAdapterIP = $oConfig.IPAddress
                EndIf
            EndIf
        Next
        
        ; 使用第一个有效的适配器
        If $sMAC = "" And $sAdapterMAC <> "" Then
            $sMAC = $sAdapterMAC
        EndIf
        If $sIP = "" And $sAdapterIP <> "" Then
            $sIP = $sAdapterIP
        EndIf
        
        ; 如果已经找到MAC和IP,退出循环
        If $sMAC <> "" And $sIP <> "" Then
            ExitLoop
        EndIf
    Next
    
    ; 设置显示
    If $sMAC = "" Then
        GUICtrlSetData($hMACAddress, "未找到")
    Else
        GUICtrlSetData($hMACAddress, $sMAC)
    EndIf
    
    If $sIP = "" Then
        GUICtrlSetData($hIPAddress, "未找到")
    Else
        GUICtrlSetData($hIPAddress, $sIP)
    EndIf
EndFunc

; 收集显示器信息
Func CollectMonitorInfo()
    Local $sMonitorInfo = ""
    
    If Not FileExists($sMonitorDir & "\MonitorInfoView.exe") Then
        GUICtrlSetData($hMonitorAutoInfo, "错误: 找不到 MonitorInfoView.exe")
        Return
    EndIf
    
    ; 运行MonitorInfoView获取活跃显示器,输出到临时目录
    Local $sTempOutputDir = @TempDir & "\computer_info_output"
    DirCreate($sTempOutputDir)
    Local $sOutputFile = $sTempOutputDir & "\monitors.csv"
    Local $sArgs = '/HideInactiveMonitors 1 /scomma "' & $sOutputFile & '"'
    
    RunWait('"' & $sMonitorDir & "\MonitorInfoView.exe" & '" ' & $sArgs, $sMonitorDir, @SW_HIDE)
    
    If Not FileExists($sOutputFile) Then
        GUICtrlSetData($hMonitorAutoInfo, "无法获取显示器信息")
        Return
    EndIf
    
    ; 解析CSV文件
    Local $aMonitors = ParseMonitorCSV($sOutputFile)
    
    ; 保存到全局变量
    $aMonitorsInfo = $aMonitors
    
    ; 显示信息并填充到输入框
    For $i = 0 To UBound($aMonitors) - 1
        If $sMonitorInfo <> "" Then $sMonitorInfo &= @CRLF
        $sMonitorInfo &= "显示器 " & ($i + 1) & ": " & $aMonitors[$i][0] & " | SN: " & $aMonitors[$i][1] & " | 大小: " & $aMonitors[$i][2]
        
        ; 显示器信息仅用于显示,不自动填充编号
    Next
    
    If $sMonitorInfo = "" Then
        $sMonitorInfo = "未检测到活跃的显示器"
    EndIf
    
    GUICtrlSetData($hMonitorAutoInfo, $sMonitorInfo)
EndFunc

; 解析显示器CSV文件
Func ParseMonitorCSV($sFile)
    Local $aResult[0][3]
    
    Local $hFile = FileOpen($sFile, 0)
    If $hFile = -1 Then Return $aResult
    
    ; 读取所有行
    Local $sContent = FileRead($hFile)
    FileClose($hFile)
    
    If $sContent = "" Then Return $aResult
    
    ; 按行分割
    Local $aLines = StringSplit($sContent, @CRLF, 1)
    If @error Then
        $aLines = StringSplit($sContent, @LF, 1)
    EndIf
    
    ; 处理每一行
    For $i = 1 To $aLines[0]
        Local $sLine = $aLines[$i]
        If $sLine = "" Then ContinueLoop
        
        ; 解析CSV行(处理引号内的逗号)
        Local $aFields[20]
        Local $iFieldCount = 0
        Local $sCurrentField = ""
        Local $bInQuotes = False
        
        For $j = 1 To StringLen($sLine)
            Local $sChar = StringMid($sLine, $j, 1)
            If $sChar = '"' Then
                $bInQuotes = Not $bInQuotes
            ElseIf $sChar = "," And Not $bInQuotes Then
                If $iFieldCount < UBound($aFields) Then
                    $aFields[$iFieldCount] = $sCurrentField
                    $iFieldCount += 1
                    $sCurrentField = ""
                EndIf
            Else
                $sCurrentField &= $sChar
            EndIf
        Next
        If $iFieldCount < UBound($aFields) Then
            $aFields[$iFieldCount] = $sCurrentField
            $iFieldCount += 1
        EndIf
        
        If $iFieldCount >= 3 Then
            Local $sModel = StringStripWS($aFields[0], 3) ; 品牌型号
            Local $sSN = StringStripWS($aFields[2], 3) ; 序列号
            
            ; 提取大小(通常在索引7或8的位置)
            Local $sSize = ""
            For $k = 7 To $iFieldCount - 1
                If $k < $iFieldCount And $aFields[$k] <> "" Then
                    Local $sField = $aFields[$k]
                    ; 查找包含英寸信息的字段
                    Local $aSizeMatch = StringRegExp($sField, "(\d+\.?\d*)\s*[英寸寸&#1250;]", 1)
                    If @error = 0 And UBound($aSizeMatch) > 0 Then
                        $sSize = $aSizeMatch[0] & "英寸"
                        ExitLoop
                    EndIf
                EndIf
            Next
            
            If $sSize = "" And $iFieldCount > 7 Then
                $sSize = StringStripWS($aFields[7], 3)
            EndIf
            
            ; 清理大小字符串
            $sSize = StringRegExpReplace($sSize, "[^0-9\.英寸寸]", "")
            If StringInStr($sSize, "英寸") = 0 And StringInStr($sSize, "寸") = 0 Then
                If $sSize <> "" Then $sSize &= "英寸"
            EndIf
            
            ReDim $aResult[UBound($aResult) + 1][3]
            $aResult[UBound($aResult) - 1][0] = $sModel
            $aResult[UBound($aResult) - 1][1] = $sSN
            $aResult[UBound($aResult) - 1][2] = $sSize
        EndIf
    Next
    
    Return $aResult
EndFunc

; 显示器数量改变事件
Func OnMonitorCountChange()
    ; 检查哪个单选按钮被选中
    If GUICtrlRead($hMonitorCount1) = $GUI_CHECKED Then
        $iMonitorCount = 1
        GUICtrlSetState($hMonitor2Number, $GUI_HIDE)
        GUICtrlSetState($hMonitor2NumberLabel, $GUI_HIDE)
    Else
        $iMonitorCount = 2
        GUICtrlSetState($hMonitor2Number, $GUI_SHOW)
        GUICtrlSetState($hMonitor2NumberLabel, $GUI_SHOW)
    EndIf
EndFunc

; 保存报告
Func OnSaveReport()
    ; 验证必填项
    Local $sDepartment = GUICtrlRead($hDepartment)
    Local $sHostNumber = GUICtrlRead($hHostNumber)
    Local $sResponsible = GUICtrlRead($hResponsible)
    Local $sPurpose = GUICtrlRead($hPurpose)
    Local $sMonitor1Number = GUICtrlRead($hMonitor1Number)
    
    ; 检查必填项
    If $sDepartment = "" Then
        MsgBox(48, "错误", "请填写使用部门!")
        Return
    EndIf
    
    If $sHostNumber = "" Or $sHostNumber = "ZDBG02-" Then
        MsgBox(48, "错误", "请填写电脑主机编号!")
        Return
    EndIf
    
    If $sResponsible = "" Then
        MsgBox(48, "错误", "请填写责任人!")
        Return
    EndIf
    
    If $sPurpose = "" Then
        MsgBox(48, "错误", "请填写用途!")
        Return
    EndIf
    
    If $sMonitor1Number = "" Or $sMonitor1Number = "ZDBG01-" Then
        MsgBox(48, "错误", "请填写显示器编号!")
        Return
    EndIf
    
    Local $sReport = "电脑信息收集报告" & @CRLF
    $sReport &= "==================" & @CRLF
    $sReport &= "生成时间: " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF
    
    ; 系统信息
    $sReport &= "【系统信息】" & @CRLF
    $sReport &= "计算机名: " & GUICtrlRead($hComputerName) & @CRLF
    $sReport &= "用户名: " & GUICtrlRead($hUserName) & @CRLF
    $sReport &= "系统版本: " & GUICtrlRead($hOSVersion) & @CRLF
    $sReport &= "CPU型号: " & GUICtrlRead($hCPUModel) & @CRLF
    $sReport &= "内存总大小: " & GUICtrlRead($hMemorySize) & @CRLF
    $sReport &= "操作系统安装日期: " & GUICtrlRead($hOSInstallDate) & @CRLF & @CRLF
    
    ; 硬盘信息
    $sReport &= "【硬盘信息】" & @CRLF
    $sReport &= GUICtrlRead($hDiskInfo) & @CRLF & @CRLF
    
    ; 网络信息
    $sReport &= "【网络信息】" & @CRLF
    $sReport &= "MAC地址: " & GUICtrlRead($hMACAddress) & @CRLF
    $sReport &= "IP地址: " & GUICtrlRead($hIPAddress) & @CRLF & @CRLF
    
    ; 显示器信息
    $sReport &= "【显示器信息】" & @CRLF
    $sReport &= "显示器1编号: " & GUICtrlRead($hMonitor1Number) & @CRLF
    If $iMonitorCount = 2 Then
        $sReport &= "显示器2编号: " & GUICtrlRead($hMonitor2Number) & @CRLF
    EndIf
    $sReport &= @CRLF
    
    ; 显示器详细信息(从MonitorInfoView获取)
    For $i = 0 To UBound($aMonitorsInfo) - 1
        $sReport &= "显示器 " & ($i + 1) & " 详细信息: " & @CRLF
        $sReport &= "  品牌型号: " & $aMonitorsInfo[$i][0] & @CRLF
        $sReport &= "  序列号(SN): " & $aMonitorsInfo[$i][1] & @CRLF
        $sReport &= "  尺寸: " & $aMonitorsInfo[$i][2] & @CRLF
        $sReport &= @CRLF
    Next
    
    ; 用户输入信息
    $sReport &= "【用户输入信息】" & @CRLF
    $sReport &= "电脑主机编号: " & GUICtrlRead($hHostNumber) & @CRLF
    $sReport &= "使用部门: " & GUICtrlRead($hDepartment) & @CRLF
    $sReport &= "责任人: " & GUICtrlRead($hResponsible) & @CRLF
    $sReport &= "用途: " & GUICtrlRead($hPurpose) & @CRLF
    
    ; 获取部门和责任人信息
    Local $sDepartment = GUICtrlRead($hDepartment)
    Local $sResponsible = GUICtrlRead($hResponsible)
    
    ; 处理空值情况
    If $sDepartment = "" Then $sDepartment = "未知部门"
    If $sResponsible = "" Then $sResponsible = "未知责任人"
    
    ; 生成日期时间字符串
    Local $sDateTime = @YEAR & @MON & @MDAY & "_" & @HOUR & @MIN & @SEC
    
    ; 保存文件到用户桌面,使用部门-责任人-日期时间.txt格式
    Local $sDesktopDir = @DesktopDir
    Local $sFileName = $sDesktopDir & "\" & $sDepartment & "-" & $sResponsible & "-" & $sDateTime & ".txt"
    Local $hFile = FileOpen($sFileName, 2 + 8) ; 写入模式,UTF8
    If $hFile <> -1 Then
        FileWrite($hFile, $sReport)
        FileClose($hFile)
        MsgBox(64, "成功", "报告已保存到:" & @CRLF & $sFileName)
    Else
        MsgBox(48, "错误", "无法保存文件!")
    EndIf
EndFunc

; 电脑主机编号输入事件
Func OnHostNumberChange()
    Local $sCurrentText = GUICtrlRead($hHostNumber)
    ; 如果前缀被删除,自动添加回来
    If StringLeft($sCurrentText, 7) <> "ZDBG02-" Then
        Local $sCleanText = StringReplace($sCurrentText, "ZDBG02-", "")
        GUICtrlSetData($hHostNumber, "ZDBG02-" & $sCleanText)
    EndIf
EndFunc

; 显示器1编号输入事件
Func OnMonitor1NumberChange()
    Local $sCurrentText = GUICtrlRead($hMonitor1Number)
    ; 如果前缀被删除,自动添加回来
    If StringLeft($sCurrentText, 7) <> "ZDBG01-" Then
        Local $sCleanText = StringReplace($sCurrentText, "ZDBG01-", "")
        GUICtrlSetData($hMonitor1Number, "ZDBG01-" & $sCleanText)
    EndIf
EndFunc

; 显示器2编号输入事件
Func OnMonitor2NumberChange()
    Local $sCurrentText = GUICtrlRead($hMonitor2Number)
    ; 如果前缀被删除,自动添加回来
    If StringLeft($sCurrentText, 7) <> "ZDBG01-" Then
        Local $sCleanText = StringReplace($sCurrentText, "ZDBG01-", "")
        GUICtrlSetData($hMonitor2Number, "ZDBG01-" & $sCleanText)
    EndIf
EndFunc

; 发送到服务端
Func OnSendToServer()
    ; 获取服务端配置
    Local $sServerIP = GUICtrlRead($hServerIP)
    Local $sServerPort = GUICtrlRead($hServerPort)
    
    ; 验证配置
    If $sServerIP = "" Or $sServerPort = "" Then
        MsgBox(48, "错误", "请填写完整的服务端配置!")
        Return
    EndIf
    
    ; 验证必填项
    Local $sDepartment = GUICtrlRead($hDepartment)
    Local $sHostNumber = GUICtrlRead($hHostNumber)
    Local $sResponsible = GUICtrlRead($hResponsible)
    Local $sPurpose = GUICtrlRead($hPurpose)
    Local $sMonitor1Number = GUICtrlRead($hMonitor1Number)
    
    ; 检查必填项
    If $sDepartment = "" Then
        MsgBox(48, "错误", "请填写使用部门!")
        Return
    EndIf
    
    If $sHostNumber = "" Or $sHostNumber = "ZDBG02-" Then
        MsgBox(48, "错误", "请填写电脑主机编号!")
        Return
    EndIf
    
    If $sResponsible = "" Then
        MsgBox(48, "错误", "请填写责任人!")
        Return
    EndIf
    
    If $sPurpose = "" Then
        MsgBox(48, "错误", "请填写用途!")
        Return
    EndIf
    
    If $sMonitor1Number = "" Or $sMonitor1Number = "ZDBG01-" Then
        MsgBox(48, "错误", "请填写显示器编号!")
        Return
    EndIf
    
    ; 直接生成报告内容,不保存到本地
    Local $sReport = "电脑信息收集报告" & @CRLF
    $sReport &= "==================" & @CRLF
    $sReport &= "生成时间: " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF
    
    ; 系统信息
    $sReport &= "【系统信息】" & @CRLF
    $sReport &= "计算机名: " & GUICtrlRead($hComputerName) & @CRLF
    $sReport &= "用户名: " & GUICtrlRead($hUserName) & @CRLF
    $sReport &= "系统版本: " & GUICtrlRead($hOSVersion) & @CRLF
    $sReport &= "CPU型号: " & GUICtrlRead($hCPUModel) & @CRLF
    $sReport &= "内存总大小: " & GUICtrlRead($hMemorySize) & @CRLF
    $sReport &= "操作系统安装日期: " & GUICtrlRead($hOSInstallDate) & @CRLF & @CRLF
    
    ; 硬盘信息
    $sReport &= "【硬盘信息】" & @CRLF
    $sReport &= GUICtrlRead($hDiskInfo) & @CRLF & @CRLF
    
    ; 网络信息
    $sReport &= "【网络信息】" & @CRLF
    $sReport &= "MAC地址: " & GUICtrlRead($hMACAddress) & @CRLF
    $sReport &= "IP地址: " & GUICtrlRead($hIPAddress) & @CRLF & @CRLF
    
    ; 显示器信息
    $sReport &= "【显示器信息】" & @CRLF
    $sReport &= "显示器1编号: " & GUICtrlRead($hMonitor1Number) & @CRLF
    If $iMonitorCount = 2 Then
        $sReport &= "显示器2编号: " & GUICtrlRead($hMonitor2Number) & @CRLF
    EndIf
    $sReport &= @CRLF
    
    ; 显示器详细信息(从MonitorInfoView获取)
    For $i = 0 To UBound($aMonitorsInfo) - 1
        $sReport &= "显示器 " & ($i + 1) & " 详细信息: " & @CRLF
        $sReport &= "  品牌型号: " & $aMonitorsInfo[$i][0] & @CRLF
        $sReport &= "  序列号(SN): " & $aMonitorsInfo[$i][1] & @CRLF
        $sReport &= "  尺寸: " & $aMonitorsInfo[$i][2] & @CRLF
        $sReport &= @CRLF
    Next
    
    ; 用户输入信息
    $sReport &= "【用户输入信息】" & @CRLF
    $sReport &= "电脑主机编号: " & GUICtrlRead($hHostNumber) & @CRLF
    $sReport &= "使用部门: " & GUICtrlRead($hDepartment) & @CRLF
    $sReport &= "责任人: " & GUICtrlRead($hResponsible) & @CRLF
    $sReport &= "用途: " & GUICtrlRead($hPurpose) & @CRLF
    
    ; 获取文件名所需的信息
    Local $sDepartment = GUICtrlRead($hDepartment)
    Local $sResponsible = GUICtrlRead($hResponsible)
    
    ; 处理空值情况
    If $sDepartment = "" Then $sDepartment = "未知部门"
    If $sResponsible = "" Then $sResponsible = "未知责任人"
    
    ; 生成日期时间字符串
    Local $sDateTime = @YEAR & @MON & @MDAY & "_" & @HOUR & @MIN & @SEC
    
    ; 生成文件名(仅用于发送,不保存到本地)
    Local $sFileName = $sDepartment & "-" & $sResponsible & "-" & $sDateTime & ".txt"
    
    ; 发送请求
    GUICtrlSetData($hSendBtn, "发送中...")
    GUICtrlSetState($hSendBtn, $GUI_DISABLE)
    
    ; 禁用所有错误提示
    Local $iOriginalErrorMode = Opt("ErrorMode", 2) ; 重定向错误到@error,不显示对话框
    
    Local $bSentSuccessfully = False
    
    ; 尝试发送请求
    Local $oHTTP = ObjCreate("WinHttp.WinHttpRequest.5.1")
    If IsObj($oHTTP) Then
        ; 设置COM错误处理
        ObjEvent($oHTTP, "HTTP_Error_")
        ; 定义请求URL
        Local $sURL = "http://" & $sServerIP & ":" & $sServerPort & "/upload"
        
        ; 定义请求体
        Local $sBoundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"
        Local $sContentType = "multipart/form-data; boundary=" & $sBoundary
        Local $sBody = "--" & $sBoundary & @CRLF
        $sBody &= "Content-Disposition: form-data; name=""file""; filename=""" & $sFileName & """" & @CRLF
        $sBody &= "Content-Type: text/plain" & @CRLF & @CRLF
        $sBody &= $sReport & @CRLF
        $sBody &= "--" & $sBoundary & "--" & @CRLF
        
        ; 设置超时时间
        $oHTTP.SetTimeouts(5000, 5000, 5000, 5000)
        
        ; 发送请求,使用严格的错误检查
        Local $iError = 0
        
        ; 尝试打开连接
        $oHTTP.Open("POST", $sURL, False)
        If @error = 0 Then
            ; 设置请求头
            $oHTTP.SetRequestHeader("Content-Type", $sContentType)
            If @error = 0 Then
                ; 发送请求
                $oHTTP.Send($sBody)
                If @error = 0 Then
                    ; 尝试获取状态码
                    Local $iStatus = 0
                    $iStatus = $oHTTP.Status
                    If @error = 0 And $iStatus = 200 Then
                        $bSentSuccessfully = True
                    EndIf
                EndIf
            EndIf
        EndIf
        
        ; 释放对象
        $oHTTP = 0
    EndIf
    
    ; 恢复错误设置
    Opt("ErrorMode", $iOriginalErrorMode)
    
    ; 显示结果
    If $bSentSuccessfully Then
        MsgBox(64, "成功", "发送成功")
    Else
        MsgBox(48, "错误", "发送失败,可能是服务端未响应或网络问题")
    EndIf
    
    GUICtrlSetData($hSendBtn, "发送到服务端")
    GUICtrlSetState($hSendBtn, $GUI_ENABLE)
EndFunc

; 退出
Func OnExit()
    ; 删除临时目录和文件
    Local $aTempDirs[4] ; 声明一个足够大的数组
    
    ; 填充数组
    $aTempDirs[0] = @TempDir & "\bin"
    $aTempDirs[1] = @TempDir & "\monitorinfoview"
    $aTempDirs[2] = @TempDir & "\computer_info_output"
    
    ; 使用UBound遍历数组
    For $i = 0 To 2 ; 只遍历我们填充的元素
        If FileExists($aTempDirs[$i]) Then
            ; 尝试删除目录中的所有文件
            FileDelete($aTempDirs[$i] & "\*.*")
            ; 尝试删除目录本身
            DirRemove($aTempDirs[$i])
        EndIf
    Next
    
    Exit
EndFunc

; HTTP错误处理函数(空实现,仅用于捕获COM对象错误)
Func HTTP_Error_()
    ; 空函数,用于捕获COM对象错误
    ; 不做任何处理,只是防止错误显示给用户
EndFunc

; 安全发送HTTP请求的包装函数
Func SendHttpRequest($oHTTP, $sURL, $sBody, $sContentType)
    Local $bSuccess = False
    
    ; 确保对象有效
    If Not IsObj($oHTTP) Then Return False
    
    ; 禁用错误提示
    Local $iOriginalErrorMode = Opt("ErrorMode", 0)
    
    ; 尝试打开连接
    $oHTTP.Open("POST", $sURL, False)
    If Not @error Then
        ; 尝试设置超时时间
        $oHTTP.SetTimeouts(5000, 5000, 5000, 5000)
        If Not @error Then
            ; 尝试设置请求头
            $oHTTP.SetRequestHeader("Content-Type", $sContentType)
            If Not @error Then
                ; 尝试发送请求
                $oHTTP.Send($sBody)
                If Not @error Then
                    ; 尝试获取状态码
                    Local $iStatus = $oHTTP.Status
                    If Not @error And $iStatus = 200 Then
                        $bSuccess = True
                    EndIf
                EndIf
            EndIf
        EndIf
    EndIf
    
    ; 恢复错误设置
    Opt("ErrorMode", $iOriginalErrorMode)
    
    Return $bSuccess
EndFunc

免费评分

参与人数 3吾爱币 +2 热心值 +2 收起 理由
Lmschang + 1 + 1 我很赞同!
lario + 1 谢谢@Thanks!
15520220211 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

TobiasCN 发表于 2026-3-22 13:53
收集的再增加2个选项。一个是办公软件,就是微软还是金山的,还要收集版本号。一个是杀毒软件,是哪个厂、版本号。别的没了,一般单位的资产清单都要这个。可加使用者密码等,严谨。
 楼主| laldyf 发表于 2026-3-20 10:44
hypwise 发表于 2026-3-20 09:35
使用部门、用途这两项写死了,应该根据各家情况自定义

我当时也在想自定义,但是因为是AI做的,试了下不太好做,就在客户端里面手动改的添加的,等有时间了我来修改下
lodon 发表于 2026-3-19 19:09
ebing 发表于 2026-3-19 20:45
感谢分享!
liyuhuimuzi 发表于 2026-3-20 07:43
使用部门 用途 这些是不是写死了
hanjiangke 发表于 2026-3-20 08:42
日常需要,下载试试
hypwise 发表于 2026-3-20 08:55
正需要此种类型的软件,感谢分享
hypwise 发表于 2026-3-20 09:35
使用部门、用途这两项写死了,应该根据各家情况自定义
yt0903 发表于 2026-3-20 09:40
这个对局域网很友好呀  下载试试 谢谢分享
lanstervv 发表于 2026-3-20 09:48
这款更进步了,能看到MAC地址了
chopard1027 发表于 2026-3-20 09:58
单位使用太合适了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-20 22:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表