Orion9

|
Posted: Wed Sep 03, 2025 00:40 Post subject: |
|
|
Loopback
Вот что значит быстро читать. Просмотрел этот момент. Не ожидал, что будет так много сообщений за время моего отсутствия, пришлось ускориться. Но обновленную версию видел и скачал, просто подумал, что она связана с багофиксами, которые обсуждались, и как-то не вкурил я в эту фразу: "регресс с версии 2.2.17"
В общем, хотел использовать эту фичу в вызове GetVolumePathNameW, но поскольку такой формат записи не сработал, пришлось откатиться на буфер. Сейчас, думаю, менять уже ничего не буду, так как таким образом останется совместимость с 2.2.19.1
Замутил я тут одну тему под стать возможностям современного Autorun, оказалось, ему вполне по силам - вывести информацию о фрагментации файлов в отдельном наборе колонок и дополнительном окне подсказки. Результатом очень даже доволен.
 autorun.cfg Code: | Pragma AutorunPluginFields "Frag:::FileVCN" "FragNum::ft_numeric_32:NumVCN" "FragEntry::ft_numeric_32:EntryVCN"
# параметры фрагментации
Global FRAG_SHOW = false, _
FRAG_LINES = 40, _
FRAG_BUFFER = 32, _
FRAG_NUM = false, _
FRAG_ENTRY = false
Global FRAG_START1 = 100000000, FRAG_END1 = 110000000, _
FRAG_START2 = 200000000, FRAG_END2 = 220000000, _
FRAG_START3 = 0, FRAG_END3 = 100000
RegisterCommand 70400 ReadFileVCN
Func ReadFileVCN(lParam)
Local bClipBoard = IsPressed(0x11)
Local sPath = RequestCopyDataInfo("SP")
Local sName = RequestCopyDataInfo("SN")
Local sFile = sPath & sName
If Not FileExist(sFile) Then
ShowHint("Файл не существует " & sFile)
Return
Endif
FRAG_SHOW = Not bClipBoard
FileVCN(sFile, 0, bClipBoard)
FRAG_SHOW = 0
EndFunc
Func NumVCN(FileName, FieldIndex, UnitIndex)
FRAG_NUM = 1
Local n = FileVCN(FileName, 0, 0)
FRAG_NUM = 0
Return n
EndFunc
Func EntryVCN(FileName, FieldIndex, UnitIndex)
Local f = FRAG_ENTRY
FRAG_ENTRY = 2
Local n = FileVCN(FileName, 0, 0)
FRAG_ENTRY = f
Return n
EndFunc
Func FileVCN(FileName, FieldIndex, UnitIndex)
Local Const OPEN_EXISTING = 3, _
FSCTL_GET_RETRIEVAL_POINTERS = 0x090073, _
ERROR_MORE_DATA = 234
Local Bytes = 0
Local hFile = 0
Local fs = FileGetSize(FileName)
Local sVolume, nCluster, nSector, nFree, nTotal, nRet, nSysErr, nEntry = 0, Dbg = 0
Static bf1 = Buffer(8)
bf1.Zero()
DllCall("GetVolumePathNameW", "wstr", FileName, "ptr", bf1.ptr, "dword", bf1.size)
sVolume = bf1.GetStr()
DllCall("GetDiskFreeSpaceW", "wstr", sVolume, _
"dword*", @nCluster, "dword*", @nSector, _
"dword*", @nFree, "dword*", @nTotal)
bf1.Zero()
Static bf2 = Buffer(1024*FRAG_BUFFER)
bf2.Zero()
hFile = DllCall("CreateFileW", "wstr", FileName, _
"dword", 0, _
"dword", 3, _
"ptr", 0, _
"dword", OPEN_EXISTING, _
"dword", 0, _
"ptr", 0, "handle")
If hFile > 0 Then
nRet = DllCall("DeviceIoControl", "handle", hFile, _
"dword", FSCTL_GET_RETRIEVAL_POINTERS, _
"ptr", bf1.ptr, _
"dword", bf1.size, _
"ptr", bf2.ptr, _
"dword", bf2.size, _
"dword*", @Bytes, _
'ptr', 0)
nSysErr = SYSERROR
DllCall("CloseHandle", "handle", hFile)
Endif
Local c = bf2.GetNum(), _
vcn = bf2.GetNum(8,"dword"),
lcn = bf2.GetNum(24,"dword"), _
next_vcn = 0, _
last_vcn = bf2.GetNum((c-1)*16+16,"dword"), _
prev_lcn = 0, _
clus = 0, _
contig = 0, _
i = 0
Local sOut
sOut = StrFormat("%3u %8u %12s", 1, vcn, SizeFormat(lcn, 0, "B", 0, 2))
For i = 0 To c - 1
next_vcn = bf2.GetNum(i*16+16,"dword")
prev_lcn = lcn
lcn = bf2.GetNum((i+1)*16+24,"dword")
clus = next_vcn - vcn
If lcn - clus = prev_lcn Then contig += 1
If FRAG_ENTRY Then
Local lcn_start = prev_lcn, lcn_end = prev_lcn + clus
If nEntry = 0 Then
If (lcn_start >= FRAG_START1 And lcn_start <= FRAG_END1) Or _
(lcn_end >= FRAG_START1 And lcn_end <= FRAG_END1) Then nEntry = 1
EndIf
If nEntry = 0 Then
If (lcn_start >= FRAG_START2 And lcn_start <= FRAG_END2) Or _
(lcn_end >= FRAG_START2 And lcn_end <= FRAG_END2) Then nEntry = 2
EndIf
If nEntry = 0 Then
If (lcn_start >= FRAG_START3 And lcn_start <= FRAG_END3) Or _
(lcn_end >= FRAG_START3 And lcn_end <= FRAG_END3) Then nEntry = 3
EndIf
EndIf
If FRAG_SHOW Or UnitIndex Then
sOut &= ' ' & StrFormat("%9u %12s", clus, SizeFormat(clus * nCluster * nSector, 1, "G", 2))
EndIf
vcn = next_vcn
If FRAG_SHOW Or UnitIndex Then
If FRAG_SHOW And i+2 > FRAG_LINES Then Break
sOut &= auCRLF & StrFormat("%3u %8u %12s", i+2, vcn, SizeFormat(lcn, 0, "B", 0, 2))
EndIf
Next
If FRAG_SHOW Or UnitIndex Then
SetHintParam("ShowHint", "Font", 9, "Consolas")
SetHintParam("ShowHint", "BackColor", 0x000000)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
sDbg = nSysErr & auCRLF & "hFile=" & hFile & auCRLF & "bytes=" & Bytes & auCRLF
sHeader = "File: " & StrLeft(FileGetName(FileName),40) & auCRLF & _
"Volume: " & sVolume & auCRLF & _
"Sector: " & nSector & " bytes" & auCRLF & _
"Cluster: " & nCluster & " sectors" & auCRLF & _
"Free: " & nFree & " Total: " & nTotal & auCRLF & _
"Fragments: " & (contig > 0 ? c-contig & "/" : "") & c & _
" Clusters: " & (nSysErr = ERROR_MORE_DATA ? ">" : "") & last_vcn & _
" Size: " & SizeFormat(fs, 1, "G", 2) & auCRLF & _
"-------------------------------------------------" & auCRLF & _
" N VCN LCN Clusters Size " & auCRLF & _
"-------------------------------------------------"
sOut = (Dbg ? sDbg : "") & sHeader & auCRLF & sOut
If UnitIndex = 1 Then
ClipPut(sOut)
ShowHint(c & " фрагментов скопировано в буфер")
Sleep(200)
Else
ShowHint(sOut)
EndIf
Sleep(500)
SetHintParam("ShowHint", "Reload")
EndIf
If FRAG_NUM Then Return c
If FRAG_ENTRY = 2 Then Return nEntry
Return (nSysErr = ERROR_MORE_DATA ? ">" : "") & _
(contig > 0 ? c-contig & "/" : "") & c & (nEntry > 0 ? "*" & nEntry : "")
EndFunc |
Код кнопки стандартный. При желании номер команды можно заменить:
Code: | TOTALCMD#BAR#DATA
70400
%COMMANDER_EXE%
Кластеры файла|Ctrl - Скопировать в буфер
-1
|
Небольшое описание переменных:
FRAG_SHOW - просто глобальная переменная, которая используется внутренне. Ее первоначальное значение ни на что не влияет.
FRAG_LINES - количество строк в подсказке. Т.к. фрагментов может быть сотни и тысячи, размер посказки нужно как-то ограничивать.
FRAG_BUFFER - размер буфера в килобайтах. Это буфер, в который возвращается информация о фрагментах. Но поскольку фрагментов может быть очень много, всё в буфер может не влезть. В таких случаях рекомендуют делать повторные вызовы, но я не стал этим загоняться. При желании можно увеличить буфер, если нужно видеть большее количество записей. 32Кб дают где-то 2000 записей.
FRAG_NUM - если true, то в кастомное поле "Frag" будет выводится только числовой тип данных. По умолчанию это поле строковое и может содержать строку формата "1/3*2", где 1 - число реальных фрагментов, 3 - число записей в MFT, 2 - попадание во второй диапазон.
FRAG_ENTRY - если true, то в кастомное поле "Frag" будет попадать информация о вхождении в диапазон после звездочки.
FRAG_START1 и FRAG_START3 - начало и конец диапазона в кластерном пространстве. Информация о диапазоне также выводится в поле "FragEntry". Удобно, если нужно найти файлы, попадающие в ту или иную область на диске.
Поле "FragNum" содержит информацию только в числовом выражении.
Есть кое-какие ограничения в работе, но о них нужно отдельно написать. Завтра, по возможности, это сделаю. |
|