|
|
|||||||
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? |
||||||||
|
|
|||||||
You can use my .Net version of scriptomatic. This version automatically generates a list of all available WMI spaces. ScriptOMatic .Net v2.0 |
||||||||
|
|
|||||||
Thanks I'll check it out. |
||||||||
|
|
|||||||
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) |
||||||||
|
|
|||||||
Noted... will do. Thanks. |
||||||||
|
|
|||||||
Top most post updated to reflect Shane's suggestion. |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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 Code: If $(IsSSD($Volume) & 127) ; TRUE if any SSD-specific attributes are on Glenn |
||||||||
|
|
|||||||
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:? |