1

Тема: AHK: Определить размер файла.

Доброго дня.

Моя конечная цель, просто получить размер файла с длинным путем (> 260символов). Утилит, удовлетворяющих, не нашел (консольных) для встраивания в батник. Мне вроде бы и не нужен ahk (я с ним не дружу вообще), но он позволяет работать с WinAPI.
NtQueryInformationFile - кажись это оно, нашел пример работы:

filepath := "c:\_test\First_level_directory_with_a_long_name_for_checking_paths_in_windows_with_a_limit_of_two_hundred_and_six_children_characters\Second_level_directory_with_a_long_name_for_checking_paths_in_windows_with_a_limit_of_two_hundred_and_six_children_characters\and_here_is_the_file_itself_with_a_long_name.txt"
File := FileOpen(filepath, "r")
MsgBox % accessmode(File)
File.Close()

accessmode(File) {
	Local
	VarSetCapacity(ioStatus, 12, 0)
	er := DllCall("ntdll.dll\NtQueryInformationFile", "Ptr", File.__handle, "Ptr", &ioStatus, "UIntP", ACCESS_MASK:=0, "Int", 4, "Int", FileAccessInformation:=0x8)
	Return Format("{:}{:}", ACCESS_MASK & 1 ? "r" : "", ACCESS_MASK>>1 & 1 ? "w" : "")
}

Я правильно понимаю, функция FileOpen вполне себе открывает файл?

Нашел решение на C:

status = NtQueryInformationFile(
	(void*)handle, 
	&ioStatusBlock,
	&openInfo, 
	sizeof(openInfo), 
	FileNetworkOpenInformation);
	
if (!NT_SUCCESS(status))
	return RtlNtStatusToDosError(status);
else
{
	if (filesize)
		*filesize = (unsigned int)openInfo.EndOfFile.u.LowPart;
	return STATUS_SUCCESS;
}

Пробую так:

filepath := "c:\_test\First_level_directory_with_a_long_name_for_checking_paths_in_windows_with_a_limit_of_two_hundred_and_six_children_characters\Second_level_directory_with_a_long_name_for_checking_paths_in_windows_with_a_limit_of_two_hundred_and_six_children_characters\and_here_is_the_file_itself_with_a_long_name.txt"
File := FileOpen(filepath, "r")
MsgBox % size(File)
File.Close()

size(File) {
	Local
	VarSetCapacity(ioStatus, 12, 0)
	er := DllCall("ntdll.dll\NtQueryInformationFile", "Ptr", File.__handle, "Ptr", &ioStatus, "UIntP", ACCESS_MASK:=0, "Int", 4, "Int", FileAccessInformation:=0x34)
	Return %ACCESS_MASK%
}

По сути поменял только строку:
FileAccessInformation:=8
на
FileAccessInformation:=0x34

ЧЯДНТ?

Нас невозможно сбить с пути, нам пофигу куда идти.

2 (изменено: Alectric, 2022-02-22 15:31:45)

Re: AHK: Определить размер файла.

File Object

FileObj := FileOpen(a_scriptfullpath,"r")
FileSize := FileObj.Length
FileObj.Close()
msgbox,% FileSize " bytes"
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

3

Re: AHK: Определить размер файла.

А какая ОС?
На десятке работает такой код:

dir := "c:\_test\First_level_directory_with_a_long_name_for_checking_paths_in_windows_with_a_limit_of_two_hundred_and_six_children_characters\Second_level_directory_with_a_long_name_for_checking_paths_in_windows_with_a_limit_of_two_hundred_and_six_children_characters"

fileName := "and_here_is_the_file_itself_with_a_long_name.txt"

FileCreateDir, % dir
MsgBox, % "FileCreateDir: " . (ErrorLevel ? "fail" : "success")

FileAppend, text, %dir%\%fileName%
MsgBox, % "FileAppend: " . (ErrorLevel ? "fail" : "success")

FileGetSize, size, %dir%\%fileName%
MsgBox, % "FileGetSize: " . (ErrorLevel ? "fail" : "success") . "`nsize: " . size

FileRemoveDir, c:\_test, 1
MsgBox, % "FileRemoveDir: " . (ErrorLevel ? "fail" : "success")
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AHK: Определить размер файла.

Сам запутался и вас запутал.

Запускал на разных компьютерах, поэтому "FileOpen" на одном компе сработало, на другом нет.

Что говорит Гугл. Что бы включить в винде поддержку длинных имен, нужно явно включить в реестре:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001

При таком раскладе, и Ваш Alectric и Ваш teadrinker примеры работают.

И тогда волшебным образом, команда dir заработает, но не всегда, если в наименовании файла встречается нестандартный символ (в моем случае длинное тире — (alt +  0 1 5 1)) то могут возникнуть трудности.
(в логе заменил длинный путь на LONG_PATH для простоты)

c:\_test>dir /s/a-d
 Содержимое папки c:\LONG_PATH

24.02.2022  09:47                11 and_here_is_the_file_itself_with_a_long_name.txt
24.02.2022  09:47                12 and_here_is_the_file_itself_with_a_long_name—.txt
               2 файлов             23 байт

     Всего файлов:
               2 файлов             23 байт
               0 папок  16 050 933 760 байт свободно

c:\_test>(@for /F "delims=" %a in ('dir /b/s/a-d') do @echo %~za %~fa)
11 c:\LONG_PATH\and_here_is_the_file_itself_with_a_long_name.txt
 c:\LONG_PATH\and_here_is_the_file_itself_with_a_long_name-.txt

А почему я заговорил про недокументированные функции WinApi?

Потому что, независимо от ключа реестра "LongPathsEnabled"=dword:00000001, включен он или выключен некоторым программам, наплевать на длинные пути, они работают, например Total Commander или:


c:\_test>robocopy . nil /L /E /FP /BYTES /NDL /NJH /NJS

            Новый файл                11        c:\LONG_PATH\and_here_is_the_file_itself_with_a_long_name.txt
            Новый файл                12        c:\LONG_PATH\and_here_is_the_file_itself_with_a_long_name-.txt

Та-дам!

Нас невозможно сбить с пути, нам пофигу куда идти.

5 (изменено: DnsIs, 2022-02-25 13:51:35)

Re: AHK: Определить размер файла.

Даже не включая поддержку длинных путей
Так работает

dir \\?\c:\_test /s/a-d

а так нет

(@for /F "delims=" %a in ('dir \\?\c:\_test /b/s/a-d') do @echo %~za %~fa)
Нас невозможно сбить с пути, нам пофигу куда идти.

6

Re: AHK: Определить размер файла.

DnsIs, но причём тут AHK?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Определить размер файла.

Как итог решил задачу так:

SetBatchLines, -1

if A_Args.Length() < 1 {
	MsgBox % "Run:`nPATH\autohotkey.exe fileSize.ahk FILENAME"
	ExitApp
}

file := A_Args[1]
pos := RegExMatch(file, "^.:\\")

if (pos = 0)
	file := "\\?\" . A_WorkingDir . "\" . file
else
	file := "\\?\" . file

FileGetSize, OutputVar, %file%
MsgBox Size of %OutputVar% bytes.

Осталось сделать вывод в консоль.

Нас невозможно сбить с пути, нам пофигу куда идти.