#213036 - 2017-12-06 01:02 AM
IsSSD UDF Testing / RFC
|
Allen
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.
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_
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
|
|
|
|
#213039 - 2017-12-06 03:18 PM
Re: IsSSD UDF Testing / RFC
[Re: Allen]
|
ShaneEP
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... $Instances = $oWMI.InstancesOf("MSFT_PhysicalDisk", 1)
|
Top
|
|
|
|
#213042 - 2017-12-06 05:02 PM
Re: IsSSD UDF Testing / RFC
[Re: Allen]
|
ShaneEP
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...
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
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?;;
;;=====================================================================================-----
;;
;;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 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!
|
Top
|
|
|
|
Moderator: Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart
|
0 registered
and 447 anonymous users online.
|
|
|