Что нового

[Файловая система] Восстановление удаленного файла

Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied [?]
Ты не поверишь, но я тоже хотел написать аналогичный пример, но лень меня одолела...

Ты и так затратил столько времени на разработку ф-ии
Ну а у меня уже была наработка на свой примитивный вариант.
Я её приспособил.
Не знаю уж как получилось ???
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Да, про расширение файла я как то забыл, вот прямая функция восстановления файла, проверено на XP:

Код:
$sFileName = InputBox("Recycled File Name", "Please type recycled file/folder name or path", "test.txt")
If Not @error Then _FileRecycleBinFileRestore($sFileName)

Func _FileRecycleBinFileRestore($sFile, $iReplace = 0)
	Local $sRecyclePath, $sOriginFileName, $sOriginPath
	
	Local $ssfBITBUCKET = 10
	Local $oShellApp = ObjCreate("Shell.Application")
	Local $oRecycleBin = $oShellApp.NameSpace($ssfBITBUCKET)
	
	If Not IsObj($oRecycleBin) Then
		Return SetError(-1, 0, "Could not get Recycle Bin")
	EndIf
	
	; Get Special Folder based upon input name
	$oFolderItems = $oRecycleBin.Items() ; Get items within Recycle Bin
	
	For $oItem In $oFolderItems ; Delete all items within Special Folder
		$sRecyclePath = $oItem.Path
		$sOriginFileName = $oRecycleBin.GetDetailsOf($oItem, 0)
		If StringInStr(StringRegExpReplace($sRecyclePath, '^.*\\', ''), ".") Then $sOriginFileName &= StringRegExpReplace($sRecyclePath, "^.*\.", ".")
		
		$sOriginPath = $oRecycleBin.GetDetailsOf($oItem, 1) & "\" & $sOriginFileName
		
		If $sOriginPath = $sFile Or $sOriginFileName = $sFile Then
			If $oItem.Type = "File Folder" Then ; Check for file type
				Return DirMove($sRecyclePath, $sOriginPath, $iReplace)
			Else
				Return FileMove($sRecyclePath, $sOriginPath, $iReplace)
			EndIf
			
			ExitLoop
		EndIf
	Next
	
	Return SetError(1)
EndFunc


gregaz [?]
Пример одного из вариантов применения ф-ии
Хороший пример, но это не хорошо так в цикле постоянно удалять и создавать элементы, при этом каждый раз опрашивать корзину :smile: Сорри, не заметил сразу «Case Else».
И ещё, раз уж в списке есть возможность мультивыделения, то почему нет возможности работать с более чем одним файлом?

Так будет немного лучше:
Код:
#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <File.au3>

Global $sFile

$hGUI = GUICreate('Demo File Restore', 1110, 600)
GUISetBkColor(0xB1B1B1)

$hLabelRecyCler = GUICtrlCreateLabel('Папка  корзины', 5, 5, 100, 20)
$sStyle = BitOR($LVS_REPORT, $LVS_ShowSELALWAYS)
$sExStyle = BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT)
$hListViewRecycler = GUICtrlCreateListView("", 5, 30, 800, 520, $sStyle, $sExStyle)
GUICtrlSetBkColor(-1, 0xDBDB00)

_GUICtrlListView_InsertColumn($hListViewRecycler, 0, 'Original name', 160)
_GUICtrlListView_InsertColumn($hListViewRecycler, 1, 'Original Patch', 300)
_GUICtrlListView_InsertColumn($hListViewRecycler, 2, 'Deleted Data', 100)
_GUICtrlListView_InsertColumn($hListViewRecycler, 3, 'Size', 50)
_GUICtrlListView_InsertColumn($hListViewRecycler, 4, 'Atributes', 40)
_GUICtrlListView_InsertColumn($hListViewRecycler, 5, 'Recycle name', 300)

$hLabelTempFolder = GUICtrlCreateLabel('Папка : Temp Folder', 810, 5, 300, 20)
$hListView = GUICtrlCreateListView("", 810, 30, 300, 520, $sStyle, $sExStyle)
GUICtrlSetBkColor(-1, 0xDBDBDB)
_GUICtrlListView_InsertColumn($hListView, 0, 'FileName', 160)
_GUICtrlListView_InsertColumn($hListView, 1, 'FileFullName', 700)

$hBtRestore = GUICtrlCreateButton("Restore", 10, 570, 70, 20)
$hBtClearRecycler = GUICtrlCreateButton("Clear Recycler", 90, 570, 110, 20)
$hBtTestFileCreate = GUICtrlCreateButton("TestFile Create", 610, -1, 100, '')
$hBtDelete = GUICtrlCreateButton("Delete", 850, -1, 70, '')
$hBtBack = GUICtrlCreateButton("Back", 1030, -1, '', '')

GUISetState()

; Создаем в рабочей папке скрипта  Папку : " Temp Folder "
DirCreate(@ScriptDir & '\Temp Folder')
Update_RecyclerFolderLV($hListViewRecycler)
Update_TempFolderLV($hListView)

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			DirRemove(@ScriptDir & '\Temp Folder')
			Exit
		Case $hBtClearRecycler
			If MsgBox(36, 'Attention', 'Are you sure, clear the recycle bin?', 0, $hGUI) = 6 Then FileRecycleEmpty()
		Case $hBtTestFileCreate
			; Создаем в  папке : "Temp Folder "  файлы\папки для тестирования
			For $i = 1 To 3
				DirCreate(@ScriptDir & '\Temp Folder\TestFolder ' & $i)
				FileClose(FileOpen(@ScriptDir & '\Temp Folder\TestFile ' & $i & '.txt', 2))
			Next
		Case $hBtDelete
			$aItems = _GUICtrlListView_GetSelectedIndices($hListView, 1)
			
			For $i = 1 To $aItems[0]
				$sFile = _GUICtrlListView_GetItemText($hListView, $aItems[$i], 1)
				FileRecycle($sFile)
			Next
		Case $hBtBack
			_FileRecycleBinFileRestore($sFile)
		Case $hBtRestore
			$aItems = _GUICtrlListView_GetSelectedIndices($hListViewRecycler, True)
			If $aItems[0] = 0 Then ContinueLoop
			
			For $i = 1 To $aItems[0]
				$sFile = _GUICtrlListView_GetItemText($hListViewRecycler, $aItems[$i], 5)
				_FileRecycleBinFileRestore($sFile, 1)
			Next
		Case Else
			ContinueLoop
	EndSwitch
	
	Update_RecyclerFolderLV($hListViewRecycler)
	Update_TempFolderLV($hListView)
WEnd

Func _FileRecycleBinEnumItems($sRoot = '')
	Local $oShellApp, $oRecycleBin, $oFolderItems, $oItem
	
	$oShellApp = ObjCreate('Shell.Application')
	$oRecycleBin = $oShellApp.NameSpace(10)
	
	If Not IsObj($oRecycleBin) Then
		Return SetError(1, 0, 0)
	EndIf
	
	Local $Ret, $Result[101][6] = [[0]]
	
	$sRoot = StringStripWS($sRoot, 3)
	
	If $sRoot > '' Then
		If StringInStr($sRoot, ':') Then
			$sRoot = StringRegExpReplace($sRoot, ':.*', '')
		Else
			$sRoot = ''
		EndIf
		
		If Not FileExists($sRoot & ':') Then
			Return SetError(1, 0, 0)
		EndIf
	EndIf
	
	$Ret = DllCall('shell32.dll', 'none', 'SHGetSettings', 'uint*', 0, 'dword', 2)
	
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	
	$oFolderItems = $oRecycleBin.Items()
	
	For $oItem In $oFolderItems
		If ($sRoot > '') And ($sRoot <> StringLeft($oItem.Path, 1)) Then
			ContinueLoop
		EndIf
		
		$Result[0][0] += 1
		
		If $Result[0][0] > UBound($Result) - 1 Then
			ReDim $Result[$Result[0][0] + 100][UBound($Result, 2)]
		EndIf
		
		$Result[$Result[0][0]][0] = $oRecycleBin.GetDetailsOf($oItem, 0) ; Original name
		$Result[$Result[0][0]][1] = $oRecycleBin.GetDetailsOf($oItem, 1) ; Original path
		$Result[$Result[0][0]][2] = $oRecycleBin.GetDetailsOf($oItem, 2) ; Deleted date
		$Result[$Result[0][0]][3] = $oItem.Size ; Size
		$Result[$Result[0][0]][4] = FileGetAttrib($oItem.Path) ; Attributes
		$Result[$Result[0][0]][5] = $oItem.Path ; Recycle name
		
		If (Not $Ret[1]) And (Not StringInStr($Result[$Result[0][0]][4], 'D')) Then
			If StringInStr($Result[$Result[0][0]][5], '.') Then
				$Result[$Result[0][0]][0] &= StringRegExpReplace($Result[$Result[0][0]][5], '^.*\.', '.')
			EndIf
		EndIf
	Next
	
	ReDim $Result[$Result[0][0] + 1][UBound($Result, 2)]
	Return $Result
EndFunc

Func _FileRecycleBinFileRestore($sFile, $iFlag = 0, $iReplace = 0)
	Local $aData = _FileRecycleBinEnumItems()
	
	For $i = 1 To UBound($aData, 1) - 1
		$sOriginalFullName = $aData[$i][1] & '\' & $aData[$i][0]
		$sRecyclerFullName = $aData[$i][5]
		$sAtributes = $aData[$i][4]
		$sCompare = $sOriginalFullName
		If $iFlag <> 0 Then $sCompare = $sRecyclerFullName
		
		If $sCompare = $sFile Then
			If $sAtributes = 'D' Then
				DirMove($sRecyclerFullName, $sOriginalFullName, $iReplace)
			Else
				FileMove($sRecyclerFullName, $sOriginalFullName, $iReplace)
			EndIf
			
			ExitLoop
		EndIf
	Next
EndFunc

Func Update_RecyclerFolderLV($hLV)
	$aData = _FileRecycleBinEnumItems()
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($hLV))
	
	For $i = 1 To UBound($aData, 1) - 1
		_GUICtrlListView_AddItem($hLV, $aData[$i][0])
		
		For $j = 1 To UBound($aData, 2) - 1
			_GUICtrlListView_AddSubItem($hLV, $i - 1, $aData[$i][$j], $j)
		Next
	Next
EndFunc

Func Update_TempFolderLV($hLV)
	$aArray = _FileListToArray(@ScriptDir & '\Temp Folder', '*.*', 0)
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($hLV))
	
	For $i = 1 To UBound($aArray, 1) - 1
		_GUICtrlListView_AddItem($hLV, $aArray[$i])
		_GUICtrlListView_AddSubItem($hLV, $i - 1, @ScriptDir & '\Temp Folder\' & $aArray[$i], 1)
	Next
EndFunc
 
Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
CreatoR [?]
Так будет немного лучше:
Да , конечно. Обратил внимание на твои изменения . Спасибо.Учту на будущее.

И ещё, раз уж в списке есть возможность мультивыделения, то почему нет возможности работать с более чем одним файлом?
Только здесь получается нереализованным ОТКАТ при удалении нескольких файлов. Хотя все это мелочи.
И
наверное надо с флагом : 1
 

StarEdik

Новичок
Сообщения
365
Репутация
4
Подскажите, пожалуйста. Как из корзины восстановить все файлы с расширением *.au3
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
StarEdik [?]
Как из корзины восстановить все файлы с расширением *.au3
Немного изменил функцию _FileRecycleBinFileRestore:

Код:
_FileRecycleBinFileRestore('*.au3', 0, 0, 'C:\')

Func _FileRecycleBinEnumItems($sRoot = '')
	Local $oShellApp, $oRecycleBin, $oFolderItems, $oItem
	
	$oShellApp = ObjCreate('Shell.Application')
	$oRecycleBin = $oShellApp.NameSpace(10)
	
	If Not IsObj($oRecycleBin) Then
		Return SetError(1, 0, 0)
	EndIf
	
	Local $Ret, $Result[101][6] = [[0]]
	
	$sRoot = StringStripWS($sRoot, 3)
	
	If $sRoot > '' Then
		If StringInStr($sRoot, ':') Then
			$sRoot = StringRegExpReplace($sRoot, ':.*', '')
		Else
			$sRoot = ''
		EndIf
		
		If Not FileExists($sRoot & ':') Then
			Return SetError(1, 0, 0)
		EndIf
	EndIf
	
	$Ret = DllCall('shell32.dll', 'none', 'SHGetSettings', 'uint*', 0, 'dword', 2)
	
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	
	$oFolderItems = $oRecycleBin.Items()
	
	For $oItem In $oFolderItems
		If ($sRoot > '') And ($sRoot <> StringLeft($oItem.Path, 1)) Then
			ContinueLoop
		EndIf
		
		$Result[0][0] += 1
		
		If $Result[0][0] > UBound($Result) - 1 Then
			ReDim $Result[$Result[0][0] + 100][UBound($Result, 2)]
		EndIf
		
		$Result[$Result[0][0]][0] = $oRecycleBin.GetDetailsOf($oItem, 0) ; Original name
		$Result[$Result[0][0]][1] = $oRecycleBin.GetDetailsOf($oItem, 1) ; Original path
		$Result[$Result[0][0]][2] = $oRecycleBin.GetDetailsOf($oItem, 2) ; Deleted date
		$Result[$Result[0][0]][3] = $oItem.Size ; Size
		$Result[$Result[0][0]][4] = FileGetAttrib($oItem.Path) ; Attributes
		$Result[$Result[0][0]][5] = $oItem.Path ; Recycle name
		
		If (Not $Ret[1]) And (Not StringInStr($Result[$Result[0][0]][4], 'D')) Then
			If StringInStr($Result[$Result[0][0]][5], '.') Then
				$Result[$Result[0][0]][0] &= StringRegExpReplace($Result[$Result[0][0]][5], '^.*\.', '.')
			EndIf
		EndIf
	Next
	
	ReDim $Result[$Result[0][0] + 1][UBound($Result, 2)]
	Return $Result
EndFunc

Func _FileRecycleBinFileRestore($sFile, $iFlag = 0, $iReplace = 0, $sRoot = '')
	Local $aData = _FileRecycleBinEnumItems($sRoot)
	
	If StringInStr($sFile, "*") Then
		$sFile = StringReplace($sFile, "*", ".*")
		$sFile = StringRegExpReplace($sFile, '([][\^\\+$(){}=!|:?]|\.[^*])', '\\\1')
	EndIf
	
	For $i = 1 To UBound($aData, 1) - 1
		$sOriginalFullName = $aData[$i][1] & '\' & $aData[$i][0]
		$sRecyclerFullName = $aData[$i][5]
		$sAtributes = $aData[$i][4]
		$sCompare = $sOriginalFullName
		
		If $iFlag <> 0 Then
			$sCompare = $sRecyclerFullName
		EndIf
		
		If $sCompare = $sFile Or StringRegExp($sCompare, $sFile & '$') Then
			If $sAtributes = 'D' Then
				DirMove($sRecyclerFullName, $sOriginalFullName, $iReplace)
			Else
				FileMove($sRecyclerFullName, $sOriginalFullName, $iReplace)
			EndIf
		EndIf
	Next
EndFunc
 

StarEdik

Новичок
Сообщения
365
Репутация
4
CreatoR
Спасибо.Отлично. Только вот одно неудобство .Файлы удаляются из разных дисков ,а не только из «С:\». Хотел как то приспособить вместо имя диска .
Код:
$Korzina = RegRead('HKCR\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}', '')

Но не смог. Можете сделать восстановление из всех дисков ?
 

StarEdik

Новичок
Сообщения
365
Репутация
4
CreatoR
Респект. Но
- Если с диска удалить только один файл, то при восстановлении в корзине остается " след " файла. Я с каждого диска удалял по одному файлу – итог тоже самое. И если обновить (F5) корзину " след" исчезает.
- А если с одного диска удалить 2 файла а с другого 1 файл, восстановление выполняется успешно.
- При восстановление более одного удаленного файла с диска(ов) операция восстановления выполняется успешно.
Может придумаете что ни будь
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
StarEdik [?]
Если с диска удалить только один файл, то при восстановлении в корзине остается след файла
Какой след?
 

StarEdik

Новичок
Сообщения
365
Репутация
4
CreatoR [?]
После востановления в корзине остается сам " файл ".Но это не совсем "файл",так как он вторично не востанавливается.Наверно вам придется самому проверить.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481

StarEdik

Новичок
Сообщения
365
Репутация
4
CreatoR
Для проверки я делаю так -Запускаю скрипт, открываю корзину и оставляю его открыто.Удаляю с диска 1 файл au3 .Он появляется в корзине. Потом нажимаю F9. Хотя файл восстанавливается ,но в корзине его еще видна. При попытке восстановить с контекста вторично выдается ошибка.
[box title=Ошибка при перемещение файла или папки]
«Не удается переместить файл. Не удается произвести чтение из файла или с диска»
[/box]
Код:
HotKeySet("{F9}", "_RestoreFile")
HotKeySet("{Esc}", "_Exit")
$Name = RegRead('HKCR\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}', '')
ShellExecute('::{645FF040-5081-101B-9F08-00AA002F954E}', '', '', '', @SW_SHOW)
If WinWaitActive($Name, '', 5) Then
    Sleep(400)
    WinMove($Name, "", @DesktopWidth-210, 90, 180, 600)
EndIf
Sleep(200)
Run("Explorer.exe " & "C:\")
$sTitle = StringRegExpReplace("C:\", "^.*\\", "")
$hWin = WinWait('[REGEXPCLASS:(Cabinet|Explore)WClass;REGEXPTITLE:.*\Q' & $sTitle & '\E.*]', '', 5)
Sleep(200)
If $hWin Then
	WinMove ($sTitle, "", 10, 90,790,600 )
	WinSetOnTop($hWin, "", 1)
EndIf
Sleep(500)
;filewrite(C:\Testwith.au3', 'test')
FileClose(FileOpen("C:\Testwith.au3", 1))
 Sleep(1000)
FileRecycle("C:\Testwith.au3")
MsgBox(64,"Удаление файла в корзину","   Файл C:\Testwith.au3 удален в корзину     " & @CRLF & @CRLF & " Для вотановления файла нажмите клавишу F9   ")

While 1
	Sleep(100)
WEnd

Func _RestoreFile()
	_FileRecycleBinFileRestore('*.au3', 0, 0,'')
	_RefreshRecycled()
EndFunc

Func _RefreshRecycled()
	WinActivate($Name, '')
	Send("{F5}")
EndFunc

Func _FileRecycleBinEnumItems($sRoot = '')
    Local $oShellApp, $oRecycleBin, $oFolderItems, $oItem

    $oShellApp = ObjCreate('Shell.Application')
    $oRecycleBin = $oShellApp.NameSpace(10)

    If Not IsObj($oRecycleBin) Then
        Return SetError(1, 0, 0)
    EndIf

    Local $Ret, $Result[101][6] = [[0]]

    $sRoot = StringStripWS($sRoot, 3)

    If $sRoot > '' Then
        If StringInStr($sRoot, ':') Then
            $sRoot = StringRegExpReplace($sRoot, ':.*', '')
        Else
            $sRoot = ''
        EndIf

        If Not FileExists($sRoot & ':') Then
            Return SetError(1, 0, 0)
        EndIf
    EndIf

    $Ret = DllCall('shell32.dll', 'none', 'SHGetSettings', 'uint*', 0, 'dword', 2)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    $oFolderItems = $oRecycleBin.Items()

    For $oItem In $oFolderItems
        If ($sRoot > '') And ($sRoot <> StringLeft($oItem.Path, 1)) Then
            ContinueLoop
        EndIf

        $Result[0][0] += 1

        If $Result[0][0] > UBound($Result) - 1 Then
            ReDim $Result[$Result[0][0] + 100][UBound($Result, 2)]
        EndIf

        $Result[$Result[0][0]][0] = $oRecycleBin.GetDetailsOf($oItem, 0) ; Original name
        $Result[$Result[0][0]][1] = $oRecycleBin.GetDetailsOf($oItem, 1) ; Original path
        $Result[$Result[0][0]][2] = $oRecycleBin.GetDetailsOf($oItem, 2) ; Deleted date
        $Result[$Result[0][0]][3] = $oItem.Size ; Size
        $Result[$Result[0][0]][4] = FileGetAttrib($oItem.Path) ; Attributes
        $Result[$Result[0][0]][5] = $oItem.Path ; Recycle name

        If (Not $Ret[1]) And (Not StringInStr($Result[$Result[0][0]][4], 'D')) Then
            If StringInStr($Result[$Result[0][0]][5], '.') Then
                $Result[$Result[0][0]][0] &= StringRegExpReplace($Result[$Result[0][0]][5], '^.*\.', '.')
            EndIf
        EndIf
    Next

    ReDim $Result[$Result[0][0] + 1][UBound($Result, 2)]
    Return $Result
EndFunc

Func _FileRecycleBinFileRestore($sFile, $iFlag = 0, $iReplace = 0, $sRoot = '')
    Local $aData = _FileRecycleBinEnumItems($sRoot)

    If StringInStr($sFile, "*") Then
        $sFile = StringReplace($sFile, "*", ".*")
        $sFile = StringRegExpReplace($sFile, '([][\^\\+$(){}=!|:?]|\.[^*])', '\\\1')
    EndIf

    For $i = 1 To UBound($aData, 1) - 1
        $sOriginalFullName = $aData[$i][1] & '\' & $aData[$i][0]
        $sRecyclerFullName = $aData[$i][5]
        $sAtributes = $aData[$i][4]
        $sCompare = $sOriginalFullName

        If $iFlag <> 0 Then
            $sCompare = $sRecyclerFullName
        EndIf

        If $sCompare = $sFile Or StringRegExp($sCompare, $sFile & '$') Then
            If $sAtributes = 'D' Then
                DirMove($sRecyclerFullName, $sOriginalFullName, $iReplace)
            Else
                FileMove($sRecyclerFullName, $sOriginalFullName, $iReplace)
            EndIf
        EndIf
    Next
EndFunc

Func _Exit()
	Exit
EndFunc
Ну ничего.Придется обновить корзину.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
StarEdik [?]
Запускаю скрипт, открываю корзину и оставляю его открыто.Удаляю с диска 1 файл au3 .Он появляется в корзине. Потом нажимаю F9. Хотя файл восстанавливается ,но в корзине его еще видна.
Ну это видимо проблемы системы, и со скриптом никак не связано.
Функция восстановления не должна нести ответственность за обновление вида папки корзины :smile: .
 

StarEdik

Новичок
Сообщения
365
Репутация
4
CreatoR
Понятно.А есть ли возможность програмно обновлять корзину?
 
Верх