Что нового

Найти и удалить файлы по маске.

semiono

Новичок
Сообщения
18
Репутация
0
Нужно найти и удалить файлы по маске.
_msi_keyfile[далее следует любая абракадабра]

например, _msi_keyfile_e094r13aql1h1qk0mcquql

Путь для поиска:
(@ProgramFilesDir & '\Videodeluxe\')

Но надо найти во всех возможных подкаталогах \*\*\*\... итд.

Это почему-то не работает:
$search = FileFindFirstFile('@ProgramFilesDir&'\Videodeluxe\_msi_keyfile*')
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
semiono
Попробуйте так:
Код:
$sPath = @ProgramFilesDir & '\Videodeluxe'
$sMask = '_msi_keyfile*'
$iDel = 0
$iNoDel = 0
$iStart = TimerInit()
$aSearch = _FileSearch($sPath, $sMask, 1)

If $aSearch[0] Then
	For $i = 1 To $aSearch[0]
		If FileDelete($aSearch[$i]) Then
			$iDel += 1
		Else
			FileSetAttrib($aSearch[$i], '-RASHOT')
			If FileDelete($aSearch[$i]) Then
				$iDel += 1
			Else
				$iNoDel += 1
			EndIf
		EndIf
	Next
	$sTime = StringFormat('%.2f сек', TimerDiff($iStart) / 1000)
	MsgBox(64, 'Info', 'Найдено файлов ' & $sMask & ' всего: ' & $aSearch[0] & @CRLF & _
			'Удалено файлов: ' & $iDel & @CRLF & 'Не удалено файлов: ' & $iNoDel & @CRLF & _
			'Затрачено времени: ' & $sTime)
Else
	$sTime = StringFormat('%.2f сек', TimerDiff($iStart) / 1000)
	MsgBox(16, 'Info', 'Не найдено ни одного файла ' & $sMask & @CRLF & _
			'Затрачено времени: ' & $sTime)
EndIf

;$iFlag = 0 - Файлы и папки (по умолчанию)
;$iFlag = 1 - Только файлы
;$iFlag = 2 - Только папки
Func _FileSearch($sPath, $sFileMask, $iFlag = 0)
	Local $sOutBin, $sOut, $aOut, $sRead, $hDir, $sAttrib

	Switch $iFlag
		Case 1
			$sAttrib = ' /A-D'
		Case 2
			$sAttrib = ' /AD'
		Case Else
			$sAttrib = ' /A'
	EndSwitch

	$sOut = StringToBinary('0' & @CRLF, 2)
	$aMasks = StringSplit($sFileMask, ';')

	For $i = 1 To $aMasks[0]
		$hDir = Run(@ComSpec & ' /U /C DIR "' & $sPath & '\' & $aMasks[$i] & '" /S /B' & $sAttrib, @SystemDir, @SW_HIDE, 6)

		While 1
			$sRead = StdoutRead($hDir, False, True)

			If @error Then
				ExitLoop
			EndIf

			If $sRead <> "" Then
				$sOut &= $sRead
			EndIf
		WEnd
	Next

	$aOut = StringRegExp(BinaryToString($sOut, 2), '[^\r\n]+', 3)

	If @error Then
		Return SetError(1)
	EndIf

	$aOut[0] = UBound($aOut) - 1
	Return $aOut
EndFunc   ;==>_FileSearch

_FileSearch().
 
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
Не работает!
Я надеюсь этот скрипт понимет что надо найти файлы такого вида
_msi_keyfile_wbhd2dlozs_abmycwy1mvl
_msi_keyfile_cxq_5w0it6in7j7uvxcqwl
_msi_keyfile_w39gg598erqfh8i5vv1n8v
итп. причём в подпапках?
Команда find например не понимает маску _msi_keyfile*, а вот GNU Find это понимает,
насчёт автоит функции я не знаю.
 
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
Скрипт пишет что не найджено файлов.
madmasles, ещё мнеб надо просто скрипт для удаления и всё...
Чтоб msgbox не открывался, даже в случае ошибок.
Я его сам протестирую, но чтоб окно не было.
Ато я боюсь скрипт испортить если сам попытаюсь закоментировать.

Кстати, у меня XP64-bit, может ProgramFiles (x64) надо было?
Хотя я думаю что там проблемма в маске? Или нет?
_msi_keyfile* это точно обрабатывается как маска?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
semiono
Попробуйте добавить в самом начале скрипта
Код:
If @OSArch <> 'X86' Then
	DllCall('kernel32.dll', 'int', 'Wow64DisableWow64FsRedirection', 'int', 1)
EndIf
Так написано в справке, но проверить сейчас не могу. Если не поможет, укажите путь полностью, т.е.
Код:
$sPath = 'C:\Program Files (x64)\Videodeluxe'
Если сообщения Вам не нужны, удалите их.
 
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
OK! Уже проверил! Точно оказалось перенаправление, блин.
Скампилил скрипт (x64) и тогда пошло дело!
Я уже с этими граблями часто сталкиваюсь, так что не впервой.
Добавлю код что вы добавили тоже, пригодиться.
Жаль что SciTE нету x64, из-за этого и проблеммы бывают, тем более что движёк
автоит уже весь 64 битный! Или может быть есть? :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles сказал(а):
Код:
If @OSArch <> 'X86' Then
	DllCall('kernel32.dll', 'int', 'Wow64DisableWow64FsRedirection', 'int', 1)
EndIf

Можно обойтись без проверки, т.к. в 32-битных системах функции Wow64DisableWow64FsRedirection() просто нет.
 
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
[HKLM\Software\Microsoft\Windows\CurrentVersion]
"ProgramFilesDir"="C:\Apps"
"ProgramFilesDir (x86)"="C:\Apps"

У меня пути к папкам одинаоквые :smile:
Тем не менее эти тупые апи не дают покоя! ))
Зря это придумано было, ну ладоб для system32, а тут то зачем!
И функций у них как правило нет которых могло бы быть 'Wow64DisableWow64FsRedirection'
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied
Проверил на Windows 7 64
Код:
MsgBox(0, '1', @ProgramFilesDir)
DllCall('kernel32.dll', 'int', 'Wow64DisableWow64FsRedirection', 'int', 1)
MsgBox(0, '2', @ProgramFilesDir)
У меня и до и после макрос @ProgramFilesDir указывает путь C:\Program Files (86). :wacko: Можно еще так попробовать:
Код:
$sProgramFiles = @ProgramFilesDir
If @OSArch <> 'X86' Then
	If StringInStr($sProgramFiles, ' (86)') Then
		$sProgramFiles = StringReplace($sProgramFiles, ' (86)', '')
	EndIf
EndIf
$sPath = $sProgramFiles & '\Videodeluxe'
MsgBox(0, '', $sPath)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles сказал(а):
У меня и до и после макрос @ProgramFilesDir указывает путь C:\Program Files (86).

Если код скомпилировать в x64 и выключить перенаправление, то, например, такой вызов:

Код:
$hFile = FileOpen('C:\Windows\System32\MyFile.txt')


автоматически (на уровне системы) будет интерпритироваться как:

Код:
$hFile = FileOpen('C:\Windows\SysWOW64\MyFile.txt')


На макрос @SystemDir, это никак не влияет. Вообще, эта функция потенциально очень опасна, т.к. перенаправление действует на всю программу. Любой внутренний вызов в AutoIt при выключенном перенаправлении может повлечь за собой вылет программы, т.к. системные библиотеки будут банально взяты из другого места (вместо 64-битных DLL будет попытка загрузить 32-битные, что в принципе невозможно). Поэтому нужно делать так:

Код:
DllCall('kernel32.dll', 'int', 'Wow64EnableWow64FsRedirection', 'int', 0)
; Что-то быстро делаем и сразу включаем обратно
DllCall('kernel32.dll', 'int', 'Wow64EnableWow64FsRedirection', 'int', 1)


Если целью является только определение папки x86, то проще сделать следующим образом:
Код:
#Include <WinAPIEx.au3>

If @AutoItX64 Then
	$ProgramDir = _WinAPI_ShellGetSpecialFolderPath($CSIDL_PROGRAM_FILESX86)
ELse
	$ProgramDir = _WinAPI_ShellGetSpecialFolderPath($CSIDL_PROGRAM_FILES)
EndIf

ConsoleWrite($ProgramDir & @CR)


madmasles

Папки "Program Files (x64)" по умолчанию не существует, есть "Program Files (x86)".
 
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
Код:
 ; (x64) @ProgramFilesDir
$ProgramFilesDir = RegRead('HKLM64\Software\Microsoft\Windows\CurrentVersion','ProgramFilesDir')

:smile:

а ещё я такие вещи делаю, для надёжности. HKLM64 + Wow6432Node
Код:
RegDelete('HKLM64\Software\Wow6432Node\MAGIX\Common')

и ещё вот
Код:
; @HomeDrive
StringLeft(@ComSpec,2)

:smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Если ваш скрипт скомпилирован в x64, то @ProgramFilesDir уже будет указывать туда, куда нужно.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
Самое главное не мешает после кампиляции и заодно помогает тестить в 32-битном SciTE.
(иначе скрипт перенаправляется) Хотя конечно, если скампилить то всё верно.

Код:
Я очень плохо знаю 64-ые системы

Перенаправляется только Program Files в Program Files (x86),
Common Files в Common Files (x86),
system32 в SysWOW64.
И реестр HKLM\Software в HKLM\Software\Wow6432Node
Больше как бы я никогда не встречал, хотя ещё какой нибудь ime (x86) может быть.
Всем спасибо!
:smile:
 
Автор
S

semiono

Новичок
Сообщения
18
Репутация
0
Код:
$sPath = @ProgramFilesDir & '\Videodeluxe'
$sMask = '_msi_keyfile*'
$iDel = 0
$iNoDel = 0
$iStart = TimerInit()
$aSearch = _FileSearch($sPath, $sMask, 1)

    For $i = 1 To $aSearch[0]
        If FileDelete($aSearch[$i]) Then
            $iDel += 1
        Else
            FileSetAttrib($aSearch[$i], '-RASHOT')
            If FileDelete($aSearch[$i]) Then
                $iDel += 1
            Else
                $iNoDel += 1
            EndIf
        EndIf
    Next

Func _FileSearch($sPath, $sFileMask, $iFlag = 0)
    Local $sOutBin, $sOut, $aOut, $sRead, $hDir, $sAttrib
; ...

Правильно? Можно ли Next как-то убрать? Как можно утромбовать код, чтоб лишнего не было?

А две переменные обязательно нужны?
$iDel = 0
$iNoDel = 0

Нельзя ли явно указать $sPath без переменной? Почему-то это не получается. :smile:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
semiono
Упрощенный вариант:
Код:
$aSearch = _FileSearch(@ProgramFilesDir & '\Videodeluxe', '_msi_keyfile*', 1)

If $aSearch[0] Then
	For $i = 1 To $aSearch[0]
		If Not FileDelete($aSearch[$i]) Then
			FileSetAttrib($aSearch[$i], '-RASHOT')
			FileDelete($aSearch[$i]) Then
		EndIf
	Next
EndIf

Func _FileSearch($sPath, $sFileMask, $iFlag = 0)
	;...
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
semiono
{CodeWarn}
 
Верх