例子:获取硬盘和分区列表

优质
小牛编辑
118浏览
2023-12-01

引用 DriveList.nsi 的内容:

!include MUI2.nsh
!include FileFunc.nsh
!include WordFunc.nsh

Name "DriveList"
OutFile "DriveList.exe"

Var DISK_LIST
Var PART_LIST
Var REFRESHBTN1
Var REFRESHBTN2
Var PriPtNumber
Var ExtPtNumber

!define PropertyStandardQuery 0
!define StorageDeviceProperty 0

!define OPEN_EXISTING 3
!define MAX_DISKS     24
!define MAX_PATH      260

!define GENERIC_READ  0x80000000

!define FILE_SHARE_READ         0x00000001
!define FILE_SHARE_WRITE        0x00000002
!define FILE_FLAG_NO_BUFFERING  0x20000000
!define FILE_FLAG_WRITE_THROUGH 0x80000000

!define IOCTL_STORAGE_QUERY_PROPERTY  0x002D1400
!define IOCTL_DISK_GET_DRIVE_GEOMETRY 0x00070000
!define IOCTL_DISK_GET_DRIVE_LAYOUT   0x0007400C


Page custom PageInit
!insertmacro MUI_LANGUAGE "SimpChinese"

Section -Main

SectionEnd

Function PageInit

    !insertmacro MUI_HEADER_TEXT "磁盘分区浏览" "请先选择磁盘,然后可在分区列表中查看该磁盘的所有分区。"

    nsDialogs::Create 1018
    Pop $0
    ${If} $0 == error
        Abort
    ${EndIf}

    ${NSD_CreateLabel} 0u 0u 300u 8u "磁盘列表:"
    Pop $0
    ${NSD_CreateDroplist} 0u 13u 230u 70u ""
    Pop $DISK_LIST
    ${NSD_OnChange} $DISK_LIST EnumParts

    ${NSD_CreateButton} 240u 11u 60u 16u "刷新"
    Pop $REFRESHBTN1
    ${NSD_OnClick} $REFRESHBTN1 EnumDisks

    ${NSD_CreateLabel} 0u 40u 300u 8u "分区列表:"
    Pop $0
    ${NSD_CreateDroplist} 0u 53u 230u 70u ""
    Pop $PART_LIST

    ${NSD_CreateButton} 240u 51u 60u 16u "刷新"
    Pop $REFRESHBTN2
    ${NSD_OnClick} $REFRESHBTN2 EnumParts

    Call EnumDisks

  nsDialogs::Show

FunctionEnd

Function EnumDisks

  SendMessage $DISK_LIST ${CB_RESETCONTENT} 0 0
  SendMessage $PART_LIST ${CB_RESETCONTENT} 0 0

  ${For} $1 0 ${MAX_DISKS}
    StrCpy $R0 "\\.\PhysicalDrive$1"
    Call CheckDisk
    ${If} $R1 != ""
      SendMessage $DISK_LIST ${CB_ADDSTRING} 0 "STR:hd$1:$R1"
    ${EndIf}
  ${Next}

FunctionEnd

Function CheckDisk

  StrCpy $R1 ""
  System::Call "kernel32::CreateFile(tR0,i0,i${FILE_SHARE_READ}|${FILE_SHARE_WRITE},i0,i${OPEN_EXISTING},i0,i0)i.R2"
  ${If} $R2 > 0
    System::Alloc 24
    Pop $R3
    System::Call "kernel32::DeviceIoControl(iR2,i${IOCTL_DISK_GET_DRIVE_GEOMETRY},i0,i0,iR3,i24,*i.R5,i0)i.R4"
    ${If} $R4 == 0
      Return
    ${EndIf}
    System::Call "*$R3(&i8.R4,i.R5,i.R6,i.R7,i.R8)"
    System::Free $R3
    IntOp $R6 $R6 * $R7
    IntOp $R6 $R6 * $R8
    System::Int64Op $R4 * $R6
    Pop $R4
    System::Call 'shlwapi::StrFormatByteSize64(lR4,t.R4,t${NSIS_MAX_STRLEN})'
    StrCpy $R8 $R4

    System::Call "*(i${StorageDeviceProperty},i${PropertyStandardQuery},i0)i.s"
    Pop $R3
    System::Alloc 1024
    Pop $R4
    System::Call "kernel32::DeviceIoControl(iR2,i${IOCTL_STORAGE_QUERY_PROPERTY},iR3,i12,iR4,i1024,*i.R5,i0)i.."
    ${If} $R5 > 0

      IntOp $R5 $R4 + 28
      System::Call "*$R5(i.R6)"
      ${Select} $R6
        ${Case} "1"
          StrCpy $R6 "SCSI"
        ${Case} "3"
          StrCpy $R6 "ATA"
        ${Case} "4"
          StrCpy $R6 "1394"
        ${Case} "5"
          StrCpy $R6 "SSA"
        ${Case} "6"
          StrCpy $R6 "FIBRE"
        ${Case} "7"
          StrCpy $R6 "USB"
        ${Case} "8"
          StrCpy $R6 "RAID"
        ${Case} "9"
          StrCpy $R6 "iSCSI"
        ${Case} "10"
          StrCpy $R6 "SAS"
        ${Case} "11"
          StrCpy $R6 "SATA"
        ${Case} "12"
          StrCpy $R6 "SD"
        ${Case} "13"
          StrCpy $R6 "MMC"
        ${CaseElse}
          StrCpy $R6 ""
      ${EndSelect}
      ${If} $R6 != ""
        StrCpy $R1 "$R6:"
      ${EndIf}

      IntOp $R5 $R4 + 12
      System::Call "*$R5(i.R6)"
      ${If} $R6 != 0
        IntOp $R5 $R4 + $R6
        System::Call "*$R5(&t1024.R6)"
        ${WordReplace} $R6 " " "" "{}*" $R7
        ${If} $R7 != ""
          StrCpy $R1 $R1$R7-
        ${EndIf}
      ${EndIf}

      IntOp $R5 $R4 + 16
      System::Call "*$R5(i .R6)"
      ${If} $R6 != 0
        IntOp $R5 $R4 + $R6
        System::Call "*$R5(&t1024.R6)"
        ${WordReplace} $R6 " " "" "{}*" $R7
        ${If} $R1 != ""
        ${AndIf} $R7 != ""
          StrCpy $R1 "$R1$R7"
        ${EndIf}
      ${EndIf}

      IntOp $R5 $R4 + 20
      System::Call "*$R5(i.R6)"
      ${If} $R6 != 0
        IntOp $R5 $R4 + $R6
        System::Call "*$R5(&t1024.R6)"
        ${WordReplace} $R6 " " "" "{}*" $R7
        ${If} $R7 != ""
          StrCpy $R1 "$R1($R7)"
        ${EndIf}
      ${EndIf}
    ${EndIf}

    StrCpy $R1 "$R1 ($R8)"
    System::Free $R3
    System::Free $R4
    System::Call "kernel32::CloseHandle(iR2)"
  ${EndIf}

FunctionEnd

Function EnumParts

  SendMessage $PART_LIST ${CB_RESETCONTENT} 0 0 $R1
  ${NSD_GetText} $DISK_LIST $R1
  StrCpy $R2 $R1 1 4
  ${If} $R2 != ":"
    StrCpy $R2 $R1 3
  ${Else}
    StrCpy $R2 $R1 4
  ${EndIf}
  StrCpy $PriPtNumber 0
  StrCpy $ExtPtNumber 4

  ${If} $R2 == "fd0"
  ${OrIf} $R2 == "fd1"
    Return
  ${EndIf}

  StrCpy $R2 $R2 "" 2
  StrCpy $R0 "\\.\PhysicalDrive$R2"
  System::Call "kernel32::CreateFile(tR0,i${GENERIC_READ},i${FILE_SHARE_WRITE},i0,i${OPEN_EXISTING},i0,i0)i.R2"
  ${If} $R2 > 0
    System::Alloc 4096
    Pop $R1
    System::Call "kernel32::DeviceIoControl(iR2,i${IOCTL_DISK_GET_DRIVE_LAYOUT},i0,i0,iR1,i4096,*i.R5,i0)i.R4"
    ${If} $R4 == 0
      Goto lblenumptret
    ${EndIf}

    System::Call "*$R1(i .R5)"
    ${If} $R5 < 1
      Goto lblenumptret
    ${EndIf}

    IntOp $R0 $R1 + 8

    ${For} $R3 1 $R5
      System::Call "*$R0(l.R6)"
      ${If} $R6 != 0
        System::Call "*$R0(l..,l.R4)"
        System::Call 'shlwapi::StrFormatByteSize64(lR4,t.R4,t${MAX_PATH})'
        System::Call "*$R0(&i20..,i.R7,&i1.R8,&i1.R9)"
        ${If} $R7 == 0
          ${If} $R3 <= 4
            IntOp $PriPtNumber $PriPtNumber + 1
          ${EndIf}
          GoTo lblenumptloop
        ${EndIf}
        ${If} $R3 <= 4
          StrCpy $R7 $PriPtNumber
          IntOp $PriPtNumber $PriPtNumber + 1
        ${Else}
          StrCpy $R7 $ExtPtNumber
          IntOp $ExtPtNumber $ExtPtNumber + 1
        ${EndIf}
        Call GetFSType
        ${If} $R9 == 1
          StrCpy $R9 ", 活动"
        ${Else}
          StrCpy $R9 ""
        ${EndIf}
        SendMessage $PART_LIST ${CB_ADDSTRING} 0 "STR:$R7 ($R4, $R8$R9)"
      ${EndIf}

    lblenumptloop:
      IntOp $R0 $R0 + 32
    ${Next}

    lblenumptret:
    System::Call "kernel32::CloseHandle(iR2)"
    System::Free $R1
  ${Else}
    Call EnumDisks
    Return
  ${EndIf}

FunctionEnd

Function GetFSType

    IntFmt $R8 "%02X" $R8
      ${Select} $R8
        ${Case} "01"
          StrCpy $R8 "FAT12"
        ${Case3} "04" "06" "0E"
          StrCpy $R8 "FAT16"
        ${Case} "07"
          StrCpy $R8 "NTFS/exFAT"
        ${Case2} "0B" "0C"
          StrCpy $R8 "FAT32"
        ${Case} "11"
          StrCpy $R8 "隐藏 FAT12"
        ${Case3} "14" "16" "1E"
          StrCpy $R8 "隐藏 FAT16"
        ${Case} "17"
          StrCpy $R8 "隐藏 NTFS/exFAT"
        ${Case2} "1B" "1C"
          StrCpy $R8 "隐藏 FAT32"
        ${Case} "27"
          StrCpy $R8 "隐藏 NTFS (RE)"
        ${Case} "35"
          StrCpy $R8 "JFS"
        ${Case2} "80" "81"
          StrCpy $R8 "MINIX"
        ${Case} "82"
          StrCpy $R8 "LINUX SWAP"
        ${Case} "83"
          StrCpy $R8 "LINUX"
        ${CaseElse}
          StrCpy $R8 "不支持的分区"
      ${EndSelect}

FunctionEnd