Page 1 of 1 1
Topic Options
#213036 - 2017-12-06 01:02 AM IsSSD UDF Testing / RFC
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4549
Loc: USA
I needed a function to find out which PCs have SSDs. Below is the fruit of my research.

 Code:
function IsSSD(optional $Letter)
  Dim $oWMI, $Instances, $Instance, $DiskNumber
  if val(@dos)>=6.2   ; Windows 8 or Higher
    if $letter=""
      $letter="C"
    endif
    if right($letter,1)=":"
      $letter=left($letter,1)
    endif
    $letter=ucase($letter)
    $oWMI = GetObject("WINMGMTS:\\.\ROOT\Microsoft\Windows\Storage")
    $Instances = $oWMI.InstancesOf("MSFT_PhysicalDisk", 1)
    $DiskNumber = GetObject("WINMGMTS:\\.\ROOT\Microsoft\Windows\Storage").ExecQuery("Select * from MSFT_Partition WHERE DriveLetter='" + $Letter + "'").ItemIndex(0).DiskNumber
    For Each $Instance In $Instances 
      if $instance.DeviceID=$DiskNumber
        if $instance.Mediatype=4 and $instance.SpindleSpeed=0
    	    $IsSSD=1
        endif
      endif
    Next
  endif
EndFunction


Note: I only tested this on Win10, but based on documentation, it should also work on Windows 8. Win 7 and below is out of luck.

Would someone mind testing it out, in particular if you have something like a D drive that is a SSD.

Also, it appears MS has created a whole bunch of new WMI spaces. I wonder if we could find a way to incorporate them into kixomatic?

Suggestions, comments?


Top
#213037 - 2017-12-06 10:23 AM Re: IsSSD UDF Testing / RFC [Re: Allen]
Arend_ Moderator Offline
MM club member
*****

Registered: 2005-01-17
Posts: 1895
Loc: Hilversum, The Netherlands
You can use my .Net version of scriptomatic.
This version automatically generates a list of all available WMI spaces.
ScriptOMatic .Net v2.0

Top
#213038 - 2017-12-06 02:55 PM Re: IsSSD UDF Testing / RFC [Re: Arend_]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4549
Loc: USA
Thanks I'll check it out.
Top
#213039 - 2017-12-06 03:18 PM Re: IsSSD UDF Testing / RFC [Re: Allen]
ShaneEP Moderator Offline
MM club member
*****

Registered: 2002-11-29
Posts: 2125
Loc: Tulsa, OK
Might want to add some error handling. I tried it on my Win7 laptop that has an SSD (even though I know you said it wouldn't work on Win7). Got a kixtart error "expected ')'!" on line 15. Which is the below line in my script...
 Code:
  $Instances = $oWMI.InstancesOf("MSFT_PhysicalDisk", 1)

Top
#213040 - 2017-12-06 03:21 PM Re: IsSSD UDF Testing / RFC [Re: ShaneEP]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4549
Loc: USA
Noted... will do. Thanks.
Top
#213041 - 2017-12-06 03:45 PM Re: IsSSD UDF Testing / RFC [Re: Allen]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4549
Loc: USA
Top most post updated to reflect Shane's suggestion.
Top
#213042 - 2017-12-06 05:02 PM Re: IsSSD UDF Testing / RFC [Re: Allen]
ShaneEP Moderator Offline
MM club member
*****

Registered: 2002-11-29
Posts: 2125
Loc: Tulsa, OK
That didn't fix the error on Win7 for some reason. It still fails on same line. I would suggest adding something like so...

 Code:
function IsSSD(optional $Letter)
  Dim $oWMI, $Instances, $Instance, $DiskNumber
  if val(@dos)>=6.2   ; Windows 8 or Higher
    if $letter=""
      $letter="C"
    endif
    if right($letter,1)=":"
      $letter=left($letter,1)
    endif
    $letter=ucase($letter)
    $oWMI = GetObject("WINMGMTS:\\.\ROOT\Microsoft\Windows\Storage")
    if @error = 0
      $Instances = $oWMI.InstancesOf("MSFT_PhysicalDisk", 1)
      $DiskNumber = GetObject("WINMGMTS:\\.\ROOT\Microsoft\Windows\Storage").ExecQuery("Select * from MSFT_Partition WHERE DriveLetter='" + $Letter + "'").ItemIndex(0).DiskNumber
      For Each $Instance In $Instances 
        if $instance.DeviceID=$DiskNumber
          if $instance.Mediatype=4 and $instance.SpindleSpeed=0
    	      $IsSSD=1
          endif
        endif
      Next
    endif
  endif
EndFunction

Top
#213064 - 2017-12-14 12:37 AM Re: IsSSD UDF Testing / RFC [Re: ShaneEP]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4396
Loc: New Jersey
I've been using this for quite a while. Much more complex, but being a black-box, who cares?
 Code:
;;
;;=====================================================================================-----
;;
;;FUNCTION       IsSSD()
;;
;;ACTION         Determines if a disk is SSD or Rotating Media
;;
;;AUTHOR         Glenn Barnas
;;
;;VERSION        1.0 / 2014/12/05
;;
;;SYNTAX         IsSSD(Drive [, MfrList] [,ReturnVSA])
;;
;;PARAMETERS     Drive - REQUIRED - Drive letter to check
;;
;;               MfrList - OPTIONAL - Array
;;               - Array of manufacturer names/IDs that ONLY manufacture SSD drives
;;               or controller chips.
;;               (eg: 'Satron', 'JMicron', 'Indilinx', 'SandForce', 'STEC', 'Crucial')
;;               Use of this parameter (using at least the above list) is highly
;;               recommended.
;;
;;               ReturnVSA - OPTIONAL - Integer
;;               - A Boolean value that returns the Vendor Specific Attribute data
;;               instead of a digit indicating the SSD detections that were triggered.
;;               This can be used with any media type that supports SMART data.
;;
;;REMARKS        A method to determine if a target drive is an SSD, usually to
;;               decide on the type of  maintenance (if any) to apply. It can
;;               also return SMART data for additional health analysis.
;;
;;RETURNS        A single digit ranging from 0-255 that represents the detections
;;               that were triggered, or an  array of Vendor Specific Attribute data.
;;               The binary weighted detection values are:
;;                 0 NOT an SSD - no detections were triggered
;;                 1 SMART Attribute 0x03 (Spin Up Time) is Defined and value is Zero
;;                 2 SMART Attribute 0x04 (Start/Stop Count) is Defined and value is Zero
;;                 4 SMART Attribute 0x08 (Seek Time Performance) is Defined and value
;;                   is Zero
;;                 8 (not currently implemented)
;;                16 One of the listed manufacturers was found in the Product ID string
;;                32 Text string "SSD" was detected in the Product ID string
;;                64 SMART Attribute unique to SSD drives was detected
;;               128 SMART Data was not retrived - detection is limited to Product ID
;;                   containing "SSD" or a match in the Manufacturer ID list.
;;               
;;               Values between 1 and 127 indicate that the drive is "probably" an
;;               SSD type, with the value increasing with the likelyhood of a valid
;;               detection. Values below 8 should be  considered suspect, as not all
;;               vendors report these values on SSD drives (although  rotating media
;;               drives that do report these values will most likely be >0).
;;               A value of Zero indicates that no detections were triggered, so the
;;               drive is almost certainly a rotating-media type.
;;               Values of 128 or higher indicate that SMART data was not retrieved
;;               from the drive; this prevents all of the low probability and the
;;               highest probability detections from being triggered. A value of 128
;;               is NOT an SSD, but values above 128 indicate that  detections based
;;               on Product String evaluations have been triggered. The user may want
;;               to further test the product string.
;;
;;               This method always return SUCCESS.
;;
;;               When the argument ReturnVSA is true, an array in the following format
;;               is returned that  contains the Drive Product ID string and all data in
;;               the SMART Vendor Specific Attribute.
;;                * ProductID	The Product ID string, usually containing the vendor
;;                  name and model number.
;;                * Attr_Data	A comma-delimited string in the format:
;;                   Attr_ID (hh),Cur_Val (d),Wst_Val (d),Thr_Val (d),RAW_Data (7 hh bytes)
;;
;;                   (hh) is a hex byte, (d) is a decimal value in the range 0-255
;;                   Attr_ID is the attribute ID; Cur_Val is the current value; Wst_Val
;;                   is the  detected worst-case value; Thr_Val is the threshold value
;;                   (if used). All remaining data is returned as Hex bytes in the
;;                   RAW_Data field.
;;               
;;               As many Attr_Data rows are returned as Vendor-Specific Attributes
;;               are defined in the SMART data query. This information can be used
;;               to evaluate the health of any SMART-enabled drive.
;;               
;;               This method will return SUCCESS if SMART data is available, and FAIL
;;               (Exit 1/single-element array with ProductID) if SMART data is not available.
;;
;;               Will not likely work with USB-attached drives due to hardware limitations.
;;               
;;
;;DEPENDENCIES   WMI, SMART
;;
;;TESTED WITH    W2K8, W2K12, Win7, Win8
;;
;;EXAMPLES       
;
Function IsSSD($_Volume, Optional $_aMfrList, OPTIONAL $_ReturnVSA)

  Dim $_aVolData[4]							; array of disk volume data
  Dim $_WMIService							; WMI Service Object
  Dim $_wmiDiskDrives, $_wmiDiskDrive					; WMI Drives collection & enumerator
  Dim $_wmiDiskPartitions, $_wmiDiskPartition				; WMI Partitions collection & enumerator
  Dim $_wmiLogicalDisks, $_wmiLogicalDisk				; WMI LogicalDisks collection & enumerator
  Dim $_wmiSmartItems, $_wmiSmartItem					; WMI SMART data objects
  Dim $_Query								; Query string
  Dim $_aVSpec								; Array of VendorSpecific data
  Dim $_O, $_I								; enumeration pointers
  Dim $_VSAttr								; Vendor Specific Attribute ID to search for
  Dim $_OutString							; Output String for when ReturnVSA is true
  Dim $_ECode								; exit code variable

  $IsSSD  = 0
  $_ECode = 0

  ; Need to match disk volume (D:) with the physical device to determine if it is an SSD drive

  ; instantiate a WMI connection
  $_WMIService = GetObject('winmgmts:\\.\root\cimv2')

  ; Get all disk drive objects
  $_wmiDiskDrives = $_WMIService.ExecQuery('Select DeviceID, Caption, PNPDeviceID from Win32_DiskDrive',,48)
  For Each $_wmiDiskDrive in $_wmiDiskDrives

    ; create a query for this disk object
    $_Query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + $_wmiDiskDrive.DeviceID + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"

    ; get the list of related objects for this disk & enum results
    $_wmiDiskPartitions = $_WMIService.ExecQuery($_Query)

    For Each $_wmiDiskPartition in $_wmiDiskPartitions

      ; Get the related Logical Disk data and enum results
      $_wmiLogicalDisks = $_wmiService.ExecQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + $_wmiDiskPartition.DeviceID + "'} WHERE AssocClass = Win32_LogicalDiskToPartition")
      For Each $_wmiLogicalDisk In $_wmiLogicalDisks

        ; If the Device ID matches the desired volume, proceed
        If $_wmiLogicalDisk.DeviceID = $_Volume

          If InStr($_wmiDiskDrive.Caption, 'SSD')
            $IsSSD = $IsSSD + 32							; "SSD" detected in product name
          EndIf

          ; Check for manufacturers that only make SSD (no spinning) drives
          For Each $_I in $_aMfrList
            If InStr($_wmiDiskDrive.Caption, $_I)
              $IsSSD = $IsSSD + 16
            EndIf
          Next

          ; Not ID'd in product name - additional examination required
          $_aVolData[0] = $_wmiLogicalDisk.DeviceID
          $_aVolData[1] = $_wmiDiskDrive.Caption
          $_aVolData[2] = $_wmiDiskDrive.DeviceID
          $_aVolData[3] = $_wmiDiskPartition.DeviceID
          $_aVolData[4] = $_wmiDiskDrive.PNPDeviceID

        EndIf

      Next
    Next
  Next

  $_WMIService = 0							; clear the prior object

  ; check the Vendor Specific Attributes - each attribute is formatted as:
  ;  1 Byte	- Identifier - the Attribute ID
  ;  1 Byte	- Threshold - the failure limit for the attribute
  ;  1 Bytes	- Status Flag - bitwise values, mostly vendor-specific (not returned)
  ;  1 Byte	- Value - the current "health" measured against the Threshold
  ;  1 Byte	- Worst - the worst value ever detected, measured against the Threshold
  ;  6 Bytes	- Data - the raw measurement data
  ;  1 Bytes	- Status Flag - bitwise values, mostly vendor-specific (not returned)

  If $_ReturnVSA
    $_OutString = $_aVolData[1] + ' / ' + $_aVolData[3] + @CRLF
  EndIf

  ; extract the SMART data from the drive for further analysis
  $_WMIService = GetObject('winmgmts:\\.\root\WMI')
  $_wmiSmartItems = $_WMIService.ExecQuery('SELECT InstanceName,VendorSpecific FROM MSStorageDriver_ATAPISmartData')

  For Each $_wmiSmartItem In $_wmiSmartItems

    ; does the instance name match that of the volume requested?
    If InStr($_wmiSmartItem.InstanceName, $_aVolData[4])

      $_aVSpec = Split(Join($_wmiSmartItem.VendorSpecific, ','), ',')
      ; Scan SSD-Only objects
      For $_O = 2 to UBound($_aVSpec) Step 12
        ; Find the Vendor Specific Attribute ID as a 2-char Hex Byte
        $_VSAttr = Right('0' + DecToHex($_aVSpec[$_O]), 2)

        ; Does it match any SSD-Specific attributes?
        If InStr(':AB:B6:FC:', ':' + $_VSAttr + ':')
          $IsSSD = $IsSSD + 64
        EndIf

        ; other tests of object/value combinations can be done here (Start Count=0 or Seek Time=0)

        ; attribute 0x03 (Spin Up Time) with a value of 0
        $_I = $_aVSpec[$_O + 3]						; Attribute Value
        If $_VSAttr ='03' And $_I = 0
          $IsSSD = $IsSSD + 1
        EndIf

        ; attribute  0x04 (Start/Stop Count) with a value of 0
        $_I = $_aVSpec[$_O + 3]						; Attribute Value
        If $_VSAttr ='03' And $_I = 0
          $IsSSD = $IsSSD + 2
        EndIf

        ; attribute 0x08 (Seek Time Performance) with a value of 0
        $_I = $_aVSpec[$_O + 3]						; Attribute Value
        If $_VSAttr ='08' And $_I = 0
          $IsSSD = $IsSSD + 4
        EndIf

        If $_ReturnVSA
          If $_VSAttr <> '00'
            $_OutString = $_OutString + $_VSAttr + ','
            $_OutString = $_OutString + Right('   ' + $_aVSpec[$_O + 3], 3) + ','	; Current
            $_OutString = $_OutString + Right('   ' + $_aVSpec[$_O + 4], 3) + ','	; Worst
            $_OutString = $_OutString + Right('   ' + $_aVSpec[$_O + 1], 3) + ','	; Threshold
            $_OutString = $_OutString + Right('00' + DecToHex($_aVSpec[$_O + 10]), 2)	; RAW Data bytes
            $_OutString = $_OutString + Right('00' + DecToHex($_aVSpec[$_O + 9]), 2)
            $_OutString = $_OutString + Right('00' + DecToHex($_aVSpec[$_O + 8]), 2)
            $_OutString = $_OutString + Right('00' + DecToHex($_aVSpec[$_O + 7]), 2)
            $_OutString = $_OutString + Right('00' + DecToHex($_aVSpec[$_O + 6]), 2)
            $_OutString = $_OutString + Right('00' + DecToHex($_aVSpec[$_O + 5]), 2) + @CRLF
          EndIf
        EndIf
      Next

    Else
      $IsSSD = $IsSSD + 128						; SMART Data unavailable
      If $_ReturnVSA $_ECode = 1 EndIf					; return Error if ReturnVSA is true
    EndIf

  Next

  If $_ReturnVSA
    $IsSSD = Split($_OutString, @CRLF)					; Return VSA array instead of SSD status
  EndIf

  Exit $_ECode

EndFunction
My requirements were a bit more broad, but I use this as
 Code:
If $(IsSSD($Volume) & 127)				; TRUE if any SSD-specific attributes are on
Not all drives report 0 spindle speed or other typical detection methods. This looks at attributes that would only be present on an SSD.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#213065 - 2017-12-14 12:46 AM Re: IsSSD UDF Testing / RFC [Re: Glenn Barnas]
Allen Administrator Offline
KiX Supporter
*****

Registered: 2003-04-19
Posts: 4549
Loc: USA
Yeah... I agree this is way more complex than what I did. Any chance you could verify mine on a drive that you found to be suspect with your code and/or on a drive letter other than C:?
Top
Page 1 of 1 1


Moderator:  Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 433 anonymous users online.
Newest Members
Raoul, Timothy, Jojo67, MaikSimon, kvn317
17875 Registered Users

Generated in 0.062 seconds in which 0.023 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org