1

Тема: WSH: как получить размер кластера?

Собственно, не знает ли, случайно, достопочтеннейшая публика ПРОСТОГО способа получения размера кластера локального тома из скрипта (желательно - JScript)? Пытался создавать файлик размером 1байт и проверять свободное место, но винда частенько и сама активно пишет на диск, да еще временные файлы запущенных приложений... В общем, фигня какая-то получается.

2

Re: WSH: как получить размер кластера?

Для ОС, начиная с 2003 и выше: Win32_Volume class → DefragAnalysis method of the Win32_Volume Class → Win32_DefragAnalysis class → свойство «.ClusterSize».

Для прочих же придётся пользовать разбор вывода внешних утилит, наподобие:

c:\>fsutil.exe fsinfo ntfsinfo c:
…
Байт на кластер:                  4096
…

или:

c:\>defrag.exe -a -v c:
…
    Размер кластера                     = 4 КБ
…

3

Re: WSH: как получить размер кластера?

alexii, спасибо за вектор. Нет, через Win32_Volume class не получилось - видимо не всё доступно из скриптов, но наводка на WMI оказалась правильной:

m=GetObject('winmgmts:').instancesOf('CIM_StorageExtent');
for(n=new Enumerator(m);!n.atEnd();n.moveNext()){
  if(n.item().systemCreationClassName==null){
    WScript.Echo(
     'VolumeName:\t'+n.item().name+
     '\nClusterSize:\t'+n.item().blockSize+
     '\nFreeSpace:\t'+n.item().freeSpace
    );
  }
}

З.Ы. Если убрать if(), можно посмотреть что ещё есть в CIM_StorageExtent

4

Re: WSH: как получить размер кластера?

Serge Yolkin, лично у меня Ваш код ничего не выдаёт. Ибо все классы, основанные на базовом классе CIM_StorageExtent class имеют непустое свойство «.SystemCreationClassName».

Ваш подход в принципе ошибочен. Каково свойство «.CreationClassName» у Вас?

5

Re: WSH: как получить размер кластера?

alexii, слава Богу, у меня такого свойства нет: меня мама рожала
А у энумерабельных объектов класса есть. Но не у всех. creationClassName для
Disk #x, Partition #x  - Win32_DiskPartition
C:, D:, E: и т.д.  - Win32_LogicalDisk
а для C:\, D:\ ... , котоорые мне и нужны - null (deviceID для них имеет вид \\?\Volume{8cb3af28-a985-11e1-9eee-806e6f6e6963}\)
для сетевых дисков  - Win32_LogicalDisk
а вот для сетевых томов с тем же deviceID (L:, P: ...) - опять же null
systemCreationClassName для всех, кроме тех, что мне нужны  - Win32_ComputerSystem

Проверил на работе (W7Pro32) и дома (W7HB32SP1) - в принципе ошибочный подход работает.
Подозреваю, дело не в том, что какое-то свойство оказалось пустым, а в том, что винда не даёт к нему доступа из скрипта, и WSH возвращает null.

6 (изменено: Serge Yolkin, 2012-06-15 22:47:33)

Re: WSH: как получить размер кластера?

Кстати, а если убрать условие if, остальное у Вас работает?
В этом случае, наверное, правильным условием будет

if(/^\\\\\?\\Volume/.test(n.item().deviceID)){...

7

Re: WSH: как получить размер кластера?

Смысл в том, что ровно с тем же успехом можно (и на самом деле — нужно) использовать класс «Win32_LogicalDisk», производный от «CIM_StorageExtent».

Но у меня и в том, и в другом случае свойство «.BlockSize» — пустое. А для класса «Win32_DiskPartition» оно означает ровно то, что и должно означать — число байт в секторе, 512, а не размер кластера. Вот примерное объяснение тому: Why no CIM/base class data?.

А что у Вас?

8

Re: WSH: как получить размер кластера?

вобщето клайстер это свойство волюмы, а не логического диска и тем более прочих драйвов и разделов

Я конечно далек от мысли... (с)

9

Re: WSH: как получить размер кластера?

smaharbA, обратите внимание на пост #2.

10

Re: WSH: как получить размер кластера?

понял

Я конечно далек от мысли... (с)

11 (изменено: Serge Yolkin, 2012-06-17 22:09:18)

Re: WSH: как получить размер кластера?

alexii, при всём уважении, если Вы настаиваете на правльности использования Win32_LogicalDisk - дайте рабочий пример.

smaharbA пишет:

вобщето клайстер это свойство волюмы

полностью с Вами согласен.

2All: Господа (кому не в лом), не могли бы Вы представить здесь результат выполнения следующего скрипта (файлик test.csv создаётся в той же папке, что и скрипт):

var
 f=new ActiveXObject('Scripting.fileSystemObject'),
 m='DeviceID;Name;BlockSize;CreationClassName;SystemCreationClassName;Path_',
 n=new Enumerator(GetObject('winmgmts:').instancesOf('CIM_StorageExtent'));

for(var n;!n.atEnd();n.moveNext()){
  m+='\n'+n.item().deviceID+';'+n.item().name+';'+n.item().blockSize+';'+
   n.item().creationClassName+';'+n.item().systemCreationClassName+';'+
   n.item().path_;
   
}
with(f.openTextFile('test.csv',2,true)){
  write(m);
  close();
}

12 (изменено: Serge Yolkin, 2012-06-17 22:10:30)

Re: WSH: как получить размер кластера?

Вот что уменя:

DeviceID;Name;BlockSize;CreationClassName;SystemCreationClassName;Path_
Disk #0, Partition #0;Disk #0, Partition #0;512;Win32_DiskPartition;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #0"
Disk #1, Partition #0;Disk #1, Partition #0;512;Win32_DiskPartition;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #0"
C:;C:;null;Win32_LogicalDisk;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
D:;D:;null;Win32_LogicalDisk;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_LogicalDisk.DeviceID="D:"
E:;E:;null;Win32_LogicalDisk;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_LogicalDisk.DeviceID="E:"
Memory Array 0;Memory Array;null;Win32_MemoryArray;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_MemoryArray.DeviceID="Memory Array 0"
\\?\Volume{232a2744-0602-11e0-ade5-806e6f6e6963}\;C:\;4096;null;null;\\NOTE\root\cimv2:Win32_Volume.DeviceID="\\\\?\\Volume{232a2744-0602-11e0-ade5-806e6f6e6963}\\"
\\?\Volume{2f7f3a4a-9b5a-11e0-ad2a-001d60b89b0a}\;E:\;8192;null;null;\\NOTE\root\cimv2:Win32_Volume.DeviceID="\\\\?\\Volume{2f7f3a4a-9b5a-11e0-ad2a-001d60b89b0a}\\"
\\?\Volume{232a2747-0602-11e0-ade5-806e6f6e6963}\;D:\;null;null;null;\\NOTE\root\cimv2:Win32_Volume.DeviceID="\\\\?\\Volume{232a2747-0602-11e0-ade5-806e6f6e6963}\\"
Cache Memory 0;Cache Memory;1024;Win32_CacheMemory;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_CacheMemory.DeviceID="Cache Memory 0"
Cache Memory 1;Cache Memory;1024;Win32_CacheMemory;Win32_ComputerSystem;\\NOTE\root\cimv2:Win32_CacheMemory.DeviceID="Cache Memory 1"

(Открывается в Excell)

13

Re: WSH: как получить размер кластера?

alexii, при всём уважении, если Вы настаиваете на правльности использования Win32_LogicalDisk - дайте рабочий пример.

Я имею в виду то, что следует использовать не общий класс «CIM_StorageExtent», а частный. По поводу «Win32_LogicalDisk» — меня ввёл в заблуждение пост #5. Теперь ясно, что это не «Win32_LogicalDisk», а некий иной класс.

У меня:

DeviceID;Name;BlockSize;CreationClassName;SystemCreationClassName
Memory Device 0;Устройство памяти;null;Win32_MemoryDevice;Win32_ComputerSystem
Memory Device 1;Устройство памяти;null;Win32_MemoryDevice;Win32_ComputerSystem
Memory Device 2;Устройство памяти;null;Win32_MemoryDevice;Win32_ComputerSystem
Memory Device 3;Устройство памяти;null;Win32_MemoryDevice;Win32_ComputerSystem
Memory Array 0;Массив памяти;null;Win32_MemoryArray;Win32_ComputerSystem
Cache Memory 0;Кэш-память;1024;Win32_CacheMemory;Win32_ComputerSystem
Cache Memory 1;Кэш-память;1024;Win32_CacheMemory;Win32_ComputerSystem
Cache Memory 2;Кэш-память;1024;Win32_CacheMemory;Win32_ComputerSystem
Disk #1, Partition #0;Диск #1, раздел #0;512;Win32_DiskPartition;Win32_ComputerSystem
Disk #0, Partition #0;Диск #0, раздел #0;512;Win32_DiskPartition;Win32_ComputerSystem
Disk #0, Partition #1;Диск #0, раздел #1;512;Win32_DiskPartition;Win32_ComputerSystem
Disk #0, Partition #2;Диск #0, раздел #2;512;Win32_DiskPartition;Win32_ComputerSystem
Disk #2, Partition #0;Диск #2, раздел #0;512;Win32_DiskPartition;Win32_ComputerSystem
A:;A:;null;Win32_LogicalDisk;Win32_ComputerSystem
C:;C:;null;Win32_LogicalDisk;Win32_ComputerSystem
D:;D:;null;Win32_LogicalDisk;Win32_ComputerSystem
E:;E:;null;Win32_LogicalDisk;Win32_ComputerSystem
F:;F:;null;Win32_LogicalDisk;Win32_ComputerSystem
G:;G:;null;Win32_LogicalDisk;Win32_ComputerSystem
H:;H:;null;Win32_LogicalDisk;Win32_ComputerSystem
I:;I:;null;Win32_LogicalDisk;Win32_ComputerSystem
J:;J:;null;Win32_LogicalDisk;Win32_ComputerSystem
K:;K:;null;Win32_LogicalDisk;Win32_ComputerSystem
L:;L:;null;Win32_LogicalDisk;Win32_ComputerSystem

Как Вы видите, у меня в принципе отсутствует «\\?\Volume{…}\» (очевидно из-за ОС).

Добавьте «n.item().Path_» в сбор информации: хочу всё-таки поглядеть, что же это за класс у Вас.

14 (изменено: Serge Yolkin, 2012-06-17 22:17:06)

Re: WSH: как получить размер кластера?

alexii, добавил в скрипт (пост #11) и в результат (пост #12). Класс Win32_Volume, что логично. Жаль, если в XP его нет (к сожалению, не на чем проверить). Почему в соответствующем свойстве - null - вопрос, вероятно, к WSH.

15

Re: WSH: как получить размер кластера?

alexii, добавил в скрипт (пост #11) и в результат (пост #12). Класс Win32_Volume, что логично. Жаль, если в XP его нет (к сожалению, не на чем проверить).

Нетути в XP этого класса , нету. Потому у меня и пусто. В итоге, мы возвращаемся к посту №2. Попробую посмотреть завтра напрямую на класс «Win32_Volume».

16 (изменено: Serge Yolkin, 2012-06-18 01:18:02)

Re: WSH: как получить размер кластера?

«Windows XP and earlier:  This class is not available.»

17

Re: WSH: как получить размер кластера?

Ну, вот, смотрите:

Option Explicit

Dim strComputer

Dim objSWbemLocator
Dim objSWbemServicesEx
Dim objSWbemObjectEx_Win32_Volume
Dim objSWbemObjectEx_Win32_DefragAnalysis

Dim boolDefragRecommended


strComputer = "."

Set objSWbemLocator    = WScript.CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServicesEx = objSWbemLocator.ConnectServer(strComputer, "root\cimv2")

For Each objSWbemObjectEx_Win32_Volume In objSWbemServicesEx.InstancesOf("Win32_Volume")
    With objSWbemObjectEx_Win32_Volume
        WScript.Echo "-----------------------------------"
        WScript.Echo "Drive:", .DriveLetter, "(" & .Label & ") [" & .DeviceID & "]"
        WScript.Echo "-----------------------------------"
        WScript.Echo "Serial number:               ", Left(Hex(.SerialNumber), 4) & "-" & Right(Hex(.SerialNumber), 4)
        WScript.Echo "Volume automount/boot/system:", Array("Yes", "No")(Abs(Not .Automount)) & "/" & Array("Yes", "No")(Abs(Not .BootVolume)) & "/" & Array("Yes", "No")(Abs(Not .SystemVolume))
        WScript.Echo "Size total/free (% usage):   ", FormatNumber(.Capacity / (2 ^ 30), 1) & " Gb/" & FormatNumber(.FreeSpace / (2 ^ 30), 1) & " Gb (" & FormatPercent((.Capacity - .FreeSpace) / .Capacity, 1) & ")"
        WScript.Echo "Drive type (File system):    ", Array("Unknown", "No Root Directory", "Removable Disk", "Local Disk", "Network Drive", "Compact Disk", "RAM Disk")(.DriveType) & " (" & .FileSystem & ")"
        
        If .DefragAnalysis(boolDefragRecommended, objSWbemObjectEx_Win32_DefragAnalysis) = 0 Then
            WScript.Echo "Block size/Cluster size:     ", .BlockSize & " b/" & objSWbemObjectEx_Win32_DefragAnalysis.ClusterSize & " b"
        End If
        
        Set objSWbemObjectEx_Win32_DefragAnalysis = Nothing
        
        WScript.Echo "-----------------------------------"
        WScript.Echo
    End With
Next

Set objSWbemServicesEx = Nothing
Set objSWbemLocator    = Nothing

WScript.Quit 0

В моём случае свойство «.BlockSize» класса «Win32_Volume» всегда оказывалось равным свойству «.ClusterSize» класса «Win32_DefragAnalysis». Всегда ли бывает так — не скажу, не знаю. Смотрите сами.

18 (изменено: Serge Yolkin, 2012-06-18 14:41:07)

Re: WSH: как получить размер кластера?

У меня под семёркой условие If .DefragAnalysis(... никогда не выполняется (в смысле - ни для какого диска). Методом комментирования лишнего пришел к выводу: нет у меня .DefragAnalysis : если убираю If - «Ошибка выполнения Microsoft VBScript: Требуется объект: ''». Собственно, примерно то же я получил и в самом начале по Вашей подсказке (только на js), поэтому полез искать альтернативу. Интересно, универсального способа нет?

19

Re: WSH: как получить размер кластера?

Serge Yolkin, выполняете под пользователем с административными полномочиями? Выполняете мой vbs-скрипт, или на JScript?

Загрузите Download: WMI Administrative Tools - Microsoft Download Center - Download Details и посмотрите, есть ли у класса «Win32_Volume» метод «.DefragAnalysis()». Должен быть.

20 (изменено: Serge Yolkin, 2012-06-21 04:00:10)

Re: WSH: как получить размер кластера?

alexii пишет:

выполняете под пользователем с административными полномочиями?

Дома - да, на работе - под бесправным пользователем. Результат одинаковый.

alexii пишет:

Выполняете мой vbs-скрипт, или на JScript?

И то, и другое. Сначала - Ваш скрипт, потом играюсь с js вариациями.

alexii пишет:

есть ли у класса «Win32_Volume» метод «.DefragAnalysis()».

Есть. (Не может не есть )

Вероятно, как я уже говорил, проблема в доступности объектов именно из скриптов. Не сомневаюсь, что из полноценной программы будет работать всё, или почти всё (ну, может, UAC о чём-нибудь спросит).

Поиграл с WMICodeCreator - всё то же. Метод есть, возвращает "ложь".