Programa para borrar archivos desde MSDOS y pasen a la papelera

Iniciado por wyxchari, 11 Noviembre 2015, 11:40 AM

0 Miembros y 1 Visitante están viendo este tema.

wyxchari

Me interesa un programa que haga desde MSDOS:
programa pepe.txt
que mueva el archivo automáticamente a la papelera.

En Windows, las papeleras tienen un nombre exclusivo del usuario con muchos números y además puede ser recycled (con D) según la versión de Windows c:\recycler\1-2-3-3433-343434-343434 por tanto hablaré de Windows XP que es el que tengo.

Para entrar en esas rutas, usar dir /a /x que muestra todos los archivos incluso ocultos y /x para que muestre nombres cortos y poder escribirlos rápido al hacer "cd".

En ese directorio hay un fichero oculto llamados INFO2 que tiene el registro de archivos borrados, otro llamado desktop.ini que tiene las propiedades de la carpeta que indican que es una papelera y una serie de ficheros llamados DXNNN.EXT que son los ficheros almacenados que se borraron. La X es la unidad donde estaba el archivo, NNN es un número correlativo y EXT es la extensión original.

He visto que hay gente que cree que en bat puede usarse la papelera para guardar archivos borrados, pero es falso. Aunque se copien archivos dentro de esas carpetas, no se actualiza el archivo INFO2 y luego al consultar la papelera desde el Explorador de Windows, no aparecen.

Sería posible vaciar la papelara desde .bat y hasta incluso seudorestaurar archivos dejando la copia en la papelera, pero nunca meterlos sin tocar el INFO2.

Opciones para construir el programa de borrado de un archivo desde MSDOS a través de la papelera:
1.- Crear una papelera alternativa en bat donde mover los archivos, que puede ser incluso c:\recycled, pero ya digo de antemano que poner un archivo ahí no actualiza INFO2 y no sale en la papelera realmente.
Hay que crear programa llamado "delp.bat" y meterlo en alguna ruta de búsqueda del PATH:
@echo off
move /y %* \recycler

El solito se encarga de buscar la unidad si es C:, D:...
2.- Usar la papelera de Windows y tras mover el archivo habría que tocar el INFO2. Para ello puede usarse el manual de la estructura del archivo INFO2 y la papelera de Windows: http://www.bandwidthco.com/whitepapers/compforensics/windows/Forensic%20Analysis%20of%20Microsoft%20Windows%20Recycle%20Bin%20Records.pdf

Sigo con el punto 2.

UNICODE Recycled Name File                        Variable, NULL terminated                     Start of Record+0x11C    

- Crear un programa que lea INFO2 para hacer pruebas. Ya hay uno llamado "rifiuti" pero necesito programarlo desde 0 para que sea la base de los añadidos a INFO2.
Código (vb) [Seleccionar]
Const lonreg = &H320
Private Type FILETIME
       dwLowDateTime As Long
       dwHighDateTime As Long
End Type
Private Type SYSTEMTIME
       wYear As Integer
       wMonth As Integer
       wDayOfWeek As Integer
       wDay As Integer
       wHour As Integer
       wMinute As Integer
       wSecond As Integer
       wMilliseconds As Integer
End Type
Private Declare Function FileTimeToSystemTime Lib "kernel32" _
(lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long
Private Declare Function FileTimeToLocalFileTime Lib "kernel32" _
(lpFileTime As FILETIME, lpLocalFileTime As FILETIME) As Long
Private Sub Form_Activate()
Dim udtFileTime As FILETIME
Dim udtFileTime2 As FILETIME
Dim udtSystemTime As SYSTEMTIME

Dim a As String * lonreg
x = 1
Open "d:\recycler\S-1-5-~1\info2" For Random As 1 Len = lonreg
ultireg = Fix(LOF(1) / lonreg)
aju = lonreg - &H10

otro1:
DoEvents
If x > ultireg Then GoTo sale
Get 1, x, a
a = Right(a, aju) ' Ajuste registro por cabecera fichero
If Mid(a, 5, 1) = Chr(0) Then GoTo otro3 ' Descarta los ya borrados

n1 = Mid(a, 5, InStr(5, a, Chr(0)) - 5)
Print "Nombre: "; n1

pp = &H108: GoSub saca
Print "Identificación: "; nn

q = Asc(Mid(a, &H10D, 1)) + Asc("A")
Print "Disco: "; Chr(q)

pp = &H110: GoSub saca
udtFileTime.dwLowDateTime = nn
pp = &H114: GoSub saca
udtFileTime.dwHighDateTime = nn
FileTimeToLocalFileTime udtFileTime, udtFileTime2
FileTimeToSystemTime udtFileTime2, udtSystemTime
q = udtSystemTime.wDay & "/" & udtSystemTime.wMonth & "/" & udtSystemTime.wYear
q = q & " " & udtSystemTime.wHour & ":" & udtSystemTime.wMinute
Print "Fecha borrado: "; q

pp = &H118: GoSub saca
Print "Tamaño físico en disco: "; nn

Print

otro3:
x = x + 1
GoTo otro1

saca:
n = ""
For f = pp + 1 To pp + 4
n2 = Hex(Asc(Mid(a, f, 1)))
If Len(n2) = 1 Then n2 = "0" & n2
n = n2 & n
Next f
nn = Val("&h" & n)
If nn < 0 Then nn = nn + 65536
Return

sale:
Close
End Sub

wyxchari

#1
= Cambiar los get de los registros por put y probar que funciona.
- Leer los datos necesarios del archivo a borrar y guardarlos.
- Buscar un identificador disponible dentro de info2.
- Renombrar el archivo.
- Mover el archivo a la papelera.
- Anexar el nuevo registro a info2.

En construcción........................

Eleкtro

#2
Si estás utilizando Visual Basic 6, ¿por que publicas el post en la sección de Scripting?.




Cita de: wyxchari en 11 Noviembre 2015, 11:40 AMEn Windows, las papeleras tienen un nombre exclusivo del usuario con muchos números y además puede ser recycled (con D) según la versión de Windows c:\recycler\1-2-3-3433-343434-343434 por tanto hablaré de Windows XP que es el que tengo.

Los números a los que te refieres son identificadores únicos de usuario o SID (Security Identifier), para poder identificar a que usuario pertenece cada cual.

A menos que estés bajo el obsoleto Windows XP, el directorio de la papelera no se llamará "Recycler\Recycled".

Cuando mueves un archivo a la papelera, éste está "dentro de la papelera", puedes acceder a dicho archivo de manera normal, y eliminarlo definitivamente (o restaurarlo) de manera normal. (no se si en XP también)




¿Como mover un archivo a la papelera del sistema en VB6?

    Bien creando una instancia de un objeto Windows shell object:
    https://www.daniweb.com/programming/software-development/threads/416417/delete-a-file-and-go-in-recycle-bin-using-vb6

    O bien usando la WinAPI:
    http://www.freevbcode.com/ShowCode.asp?ID=76

Saludos








wyxchari

#3
Cita de: Eleкtro en 12 Noviembre 2015, 13:56 PM
1.- Si estás utilizando Visual Basic 6, ¿por que publicas el post en la sección de Scripting?.
2.- ¿Como mover un archivo a la papelera del sistema en VB6?
1.- Lo siento. Fallo mío. Empecé hablando de .bat tras leer mensajes de uso de la papelera desde .bat y terminé programando en VB6.
2.- Redefino el proyecto anterior, gracias a ti, porque me han servido mucho esos enlaces. De hecho, lo acabé ayer y ha quedado de maravilla. El programa en VB6 se llama "delp.exe" y lo meto en C:\windows para que pille PATH. Desde MSDOS se usa igual que "del" sólo que "delp" borra y mete en la papelera automáticamente. Dejo el código que va con la referencia activada de Microsoft Scripting Runtime:
Código (vb) [Seleccionar]
Private Type SHFILEOPSTRUCT
       hwnd As Long
       wFunc As Long
       pFrom As String
       pTo As String
       fFlags As Integer
       fAnyOperationsAborted As Long
       hNameMappings As Long
       lpszProgressTitle As String
End Type
Private Const FO_DELETE = &H3
Private Const FOF_ALLOWUNDO = &H40
Private Const FOF_NOCONFIRMATION = &H10
Private Declare Function SHFileOperation Lib "shell32.dll" _
Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long
Public fso As New FileSystemObject
Private Sub Form_Load()
Dim cc As String
cc = Command$
If cc = "" Or Dir(cc) = "" Then GoTo sale
cc = fso.GetAbsolutePathName(cc)
If Dir(cc) = "" Then GoTo sale

a = MoveToRecycleBin(cc, True) ' Debe tener la ruta completa. True evita confirmación
If a Then MsgBox "Error: " & cc

sale:
End
End Sub
Public Function MoveToRecycleBin _
(FileSpec As String, Optional NoConfirm As Boolean = False) _
As Long
'FileSpec "C:\myfile.txt" or directory/wildcard combination C:\*.txt

Dim WinType_SFO As SHFILEOPSTRUCT
Dim lRet As Long
Dim lFlags As Long

lFlags = FOF_ALLOWUNDO
If NoConfirm Then lFlags = lFlags Or FOF_NOCONFIRMATION

With WinType_SFO
   .wFunc = FO_DELETE
   .pFrom = FileSpec
   .fFlags = lFlags
End With

lRet = SHFileOperation(WinType_SFO)
MoveToRecycleBin = lRet

End Function


Eleкtro

#4
@wyxchari

¿Lo único que buscas es una manera de compilar un exe para usarlo mediante interfáz por linea de comandos para enviar archivos a la papelera de reciclaje?.

En ese caso, quizás esto no viene a cuento, pero ya que primero empezaste con Batch y luego con VB6, imagino que la razón es por que solo buscabas una manera de lograrlo, pues bien, entonces a modo de sugerencia te recomiendo que olvides el viejo VB6, y en su lugar lo hagas en un lenguaje óptimo como por ejemplo VB.Net para evitar trastear con código no administrado e inseguro, y tener cierto control sobre lo que haces en otros aspectos generales.

Esto es un ejemplo de aplicación de consola que no toma más de 10 minutos de desarrollo en Vb.Net, como ves es muy simple a la vez que efectivo con el uso adicional de comodines, el código proporciona bastante seguridad y es sencillo de entender. Lo puedes extender a tu gusto:



Código (vbnet) [Seleccionar]
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Text
Imports Microsoft.VisualBasic.FileIO

Module Module1

   Public Sub Main()

       Dim args As IEnumerable(Of String) = Environment.GetCommandLineArgs.Skip(1)
       Dim arg As String = args.FirstOrDefault
       Dim files As New List(Of String)

       Console.OutputEncoding = Encoding.GetEncoding("Windows-1252")

       If Not (args.Any) Then
           Console.WriteLine("Debe especificar un archivo.")
           Environment.Exit(1)

       ElseIf (args.Count <> 1) Then
           Console.WriteLine("Demasiados argumentos.")
           Environment.Exit(1)

       ElseIf arg.StartsWith("*"c) Then
           files.AddRange(Directory.GetFiles(".\", arg, IO.SearchOption.TopDirectoryOnly))
           If (files.Count < 1) Then
               Console.WriteLine("Ningún archivo encontrado.")
               Environment.Exit(1)
           End If

       ElseIf Not File.Exists(arg) Then
           Console.WriteLine("El archivo especificado no existe.")
           Environment.Exit(1)

       Else
           files.Add(arg)

       End If

       Try
           files.ForEach(Sub(filepath As String)
                             My.Computer.FileSystem.DeleteFile(filepath, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin)
                             Console.WriteLine(String.Format("Archivo borrado: {0}", filepath))
                         End Sub)

       Catch ex As Exception
           Console.WriteLine(ex.Message)
           Environment.Exit(1)

       End Try

       Environment.Exit(0)

   End Sub

End Module


Saludos