PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2025 → Comment détruire définitivement un fichier sur disque.
Comment détruire définitivement un fichier sur disque.
Débuté par Jean Turcotte, 23 avr. 2025 13:33 - 10 réponses
Membre enregistré
1 275 messages
Posté le 23 avril 2025 - 13:33
Bonjour, est-ce que l'un d'entre-vous sais comment programmer une fonction pour détruire complétement un fichier Windows sur disque de facon à ce qu'il ne puisse être récupéré par un logiciel de récupération?

Merci!

--
Jean Turcotte
WX 2025
Membre enregistré
243 messages
Posté le 23 avril 2025 - 13:49
Bonjour,
Confronté à ce problème il y a quelques années, je n'ai pas trouvé de solution directe.
J'ai donc choisi de crypter le fichier avant de le supprimer.
Cdt
Membre enregistré
220 messages
Posté le 23 avril 2025 - 14:01
Bonjour,

C'est impossible. Il faut formatter tout le disque avec un formattage bas niveau et plusieurs fois pour que le fichier soit impossible à récupérer.

La solution de cryptage ne sert pas car on peut facilement récupérer une version antérieure du fichier (même après des années). Pour le système, le fichier crypté n'est rien qu'autre qu'un nouveau fichier avec la version non cryptée qui a été supprimée.
Membre enregistré
243 messages
Posté le 23 avril 2025 - 14:13
Dav a écrit :

> La solution de cryptage ne sert pas car on peut facilement récupérer une version antérieure du fichier (même après des années). Pour le système, le fichier crypté n'est rien qu'autre qu'un nouveau fichier avec la version non cryptée qui a été supprimée.


FAUX :
si la taille du fichier n'est pas modifiée, il ne sera pas créé de nouveau fichier
Il faut juste écrire des données (cryptées ou non) en respectant la taille originale

Pour information :
Jusqu’à ce que de nouvelles données soient écrites à l'emplacement physique du fichier supprimé, les données seront toujours présentes.
C’est ce que les outils de récupération de données (comme Recuva, DiskDrill, Glary Undelete, etc...) utilisent pour analyser votre disque et récupérer ces données.
Toutefois, lorsqu’un fichier existant est écrasé ou qu’un nouveau fichier est écrit dans le même espace physique que le fichier supprimé,
la récupération devient extrêmement improbable voir impossible étant donné que le contenu du fichier a été complètement remplacé par d’autres données.
CQFD
Message modifié, 23 avril 2025 - 14:24
Membre enregistré
1 275 messages
Posté le 23 avril 2025 - 19:14
Merci pour vos réponses.

Dommage que ce ne soit pas possible. Peut-on alors forcer une fragmentation des disques par programmation?

--
Jean Turcotte
WX 2025
Membre enregistré
243 messages
Posté le 23 avril 2025 - 21:09
Bonsoir,

Une "défragmentation" plutôt (avec consolidation de l'espace libre)

C'est possible en exécutant Defrag
Ex. pour défragmenter le disque C:
C:\Windows\System32\Defrag.exe /X C:

Cette commande doit être exécutée en "mode Administrateur"

A tester mais pas certain que ça résolve le problème initial

Cdt
Posté le 24 avril 2025 - 08:23
https://support.ccleaner.com/s/article/command-line-parameters-for-ccleaner-for-windows…

CCleaner.exe /DELETE "path_to_file(s)" /METHOD "0-3"
The Method parameter defines the secure deletion type:
0 - 1 Pass
1 - 3 Passes
2 - 7 Passes
3 - 35 Passes
Note: You cannot use /METHOD by itself. It must be preceded by /DELETE.

Bon dev.
Jean-Pierre
Membre enregistré
252 messages
Posté le 24 avril 2025 - 10:38
Jean Turcotte a écrit :
Bonjour, est-ce que l'un d'entre-vous sais comment programmer une fonction pour détruire complétement un fichier Windows sur disque de facon à ce qu'il ne puisse être récupéré par un logiciel de récupération?

Merci!

--
Jean Turcotte
WX 2025


Bonjour,

Vous demandez à ce que le fichier ne soit pas récupérable par un logiciel de récupération (je comprends par là un logiciel du commerce) et non un logiciel spécialisé utilisé dans l'industrie de la récupération de données.

Alors c'est très simple.
Le principe est de ne SURTOUT pas supprimer le fichier en question AVANT de faire cette opération :
Il suffit d'ouvrir le fichier en question avec la fonction fEcrit() https://doc.pcsoft.fr/fr-FR/?3036014&3036014 et d'y écrire une chaine quelconque à l'intérieur (par exemple des zéro) puis de le renommer avec un nom aléatoire et enfin de le supprimer avec la fonction fSupprime (sans option).
Cela suffit amplement à le détruire de façon à ce qu'il ne puisse être récupéré par des outils du commerce.
Maintenant si vous êtes parano, vous pouvez aussi (avant de le détruire) récupérer la taille du fichier (en nbr de caractères) pour que la chaine à écrire avec fEcrit() soit de la même longueur, mais bon, comme je dis tout dépends du niveau de sécurité que demande le client.

En gros c'est ce que explique Fabrice N.
Bon dev !
Membre enregistré
1 275 messages
Posté le 24 avril 2025 - 13:34
André STASZEWSKI a écrit :
Jean Turcotte a écrit :
Bonjour, est-ce que l'un d'entre-vous sais comment programmer une fonction pour détruire complétement un fichier Windows sur disque de facon à ce qu'il ne puisse être récupéré par un logiciel de récupération?

Merci!

--
Jean Turcotte
WX 2025

Bonjour,

Vous demandez à ce que le fichier ne soit pas récupérable par un logiciel de récupération (je comprends par là un logiciel du commerce) et non un logiciel spécialisé utilisé dans l'industrie de la récupération de données.

Alors c'est très simple.
Le principe est de ne SURTOUT pas supprimer le fichier en question AVANT de faire cette opération :
Il suffit d'ouvrir le fichier en question avec la fonction fEcrit() https://doc.pcsoft.fr/fr-FR/?3036014&3036014 et d'y écrire une chaine quelconque à l'intérieur (par exemple des zéro) puis de le renommer avec un nom aléatoire et enfin de le supprimer avec la fonction fSupprime (sans option).
Cela suffit amplement à le détruire de façon à ce qu'il ne puisse être récupéré par des outils du commerce.
Maintenant si vous êtes parano, vous pouvez aussi (avant de le détruire) récupérer la taille du fichier (en nbr de caractères) pour que la chaine à écrire avec fEcrit() soit de la même longueur, mais bon, comme je dis tout dépends du niveau de sécurité que demande le client.

En gros c'est ce que explique Fabrice N.
Bon dev !


Merci à vous tous, c'est exactement ce que je recherchais. :merci:

--
Jean Turcotte
WX 2025
Posté le 27 avril 2025 - 13:12
Bonjour
La commande powershell cypher peut s'avérer utile.

Mais les remarques de André et Fabrice m’ont inspiré pour traiter un seul fichier.
J’ai développé cette procédure et j’attends vos commentaires…

ElPato
Procedure DetruireFichier(CheminfichierSource est chaîne)

AvecTrace est un booléen=Vrai
Sablier(Vrai)
SI PAS fFichierExiste(CheminfichierSource) ALORS
SI AvecTrace ALORS Trace(CheminfichierSource+" pas trouvé")
RENVOYER Faux
FIN

disque est chaîne = fExtraitChemin(CheminfichierSource,fDisque)
repertoire est chaîne = fExtraitChemin(CheminfichierSource,fRépertoire)
SI disque~="" ALORS disque=fDisqueEnCours()
SI repertoire~="" ALORS repertoire=fExtraitChemin(fRepEnCours(),fRépertoire)

//création du nom du fichier final temporaire : il sera dans le même répertoire que le fichier à supprimer
//et créé avec un nom théoriquement unique au monde ! (en tout cas le temps de l'utiliser...)
CheminFichierDestination est chaîne = disque+repertoire+DonneGUID(guidBrut)

IDFichier est un entier
ResEcriture est un entier
texteDeRemplacement est chaîne ANSI
caractèreDeRemplacement est chaîne = "A"
dernierCaractère est chaîne = "Z"
TailleDuFichierSource est entier sur 8 octets = fTaille(CheminfichierSource)
TailleDuFichierDestination est entier sur 8 octets
TailleAnalysée est entier sur 8 octet = 1 000 000 000
NombreDeTours,compteur est entier
reste est entier

SI AvecTrace ALORS
Trace("Disque="+disque)
Trace("Répertoire="+repertoire)
Trace("Source="+CheminfichierSource)
Trace("Destination:"+CheminFichierDestination)
AffichageLignes("SOURCE",CheminfichierSource,TailleDuFichierSource)
FIN

SELON TailleDuFichierSource

CAS < TailleAnalysée
texteDeRemplacement = Complete(texteDeRemplacement,TailleDuFichierSource,caractèreDeRemplacement)
IDFichier = fOuvre(CheminfichierSource, foLectureEcriture)
SI IDFichier<>-1
ResEcriture = fEcrit(IDFichier,texteDeRemplacement,TailleDuFichierSource-1) // on écrase tous les octets (moins 1) du texte d'origine par le même caractère répété n fois
ResEcriture = fEcrit(IDFichier,dernierCaractère,1) // le dernier caractère est différent simplement pour vérification visuelle
SINON
SI AvecTrace ALORS Trace("Erreur écriture")
fFerme(IDFichier)
RENVOYER Faux
FIN
fFerme(IDFichier)

AUTRES CAS
IDFichier = fOuvre(CheminfichierSource,foLectureEcriture)
NombreDeTours = PartieEntière(TailleDuFichierSource/TailleAnalysée)
reste = TailleDuFichierSource-(TailleAnalysée* NombreDeTours)
texteDeRemplacement = Complete(texteDeRemplacement,TailleAnalysée,caractèreDeRemplacement)

SI IDFichier<>-1 ALORS
POUR compteur=1 À NombreDeTours
ResEcriture=fEcrit(IDFichier,texteDeRemplacement,TailleAnalysée)
SI ResEcriture<>-1 ALORS
SI AvecTrace ALORS Trace("tour="+compteur+"/"+NombreDeTours)
SINON
SI AvecTrace ALORS Trace("Erreur écriture")
fFerme(IDFichier)
RENVOYER Faux
FIN
FIN
ResEcriture = fEcrit(IDFichier,texteDeRemplacement,reste-1) // on écrase tous les octets (moins 1) du texte d'origine par le même caractère répété n fois
ResEcriture = fEcrit(IDFichier,dernierCaractère,1) //le dernier caractère est différent simplement pour vérification visuelle et testée
fFerme(IDFichier)
SINON
fFerme(IDFichier)
RENVOYER Faux
FIN
FIN


//on renomme le fichier source dans son nom bidon temporaire
SI fRenomme(CheminfichierSource,CheminFichierDestination) ALORS
TailleDuFichierDestination=fTaille(CheminFichierDestination)
SI TailleDuFichierSource=TailleDuFichierDestination ALORS //dernière vérification à tout hasard...
SI AvecTrace ALORS
AffichageLignes("DESTINATION",CheminFichierDestination,TailleDuFichierDestination)
AffichageLignesFinales("DESTINATION", CheminFichierDestination)
FIN
verif est chaîne //vraiment là j'en fais trop...
SI VerifDernierCaractère(CheminFichierDestination,dernierCaractère) ALORS
verif=Vrai
SINON
verif=Faux
FIN
SI AvecTrace ALORS
Info("Vérifiez la trace !")
FIN
SI fSupprime(CheminFichierDestination) ALORS
//tout est OK: opération terminée : ouf!
RENVOYER verif
SINON
SI AvecTrace ALORS Trace("Suppression impossible de "+CheminFichierDestination)
RENVOYER Faux
FIN
SINON
fSupprime(CheminFichierDestination)
SI AvecTrace ALORS Trace("Taille différente du source et de la destination")
RENVOYER Faux
FIN
SINON
SI AvecTrace ALORS Trace("renommage impossible de: "+ CheminfichierSource+RC+"en"+RC+ CheminFichierDestination)
RENVOYER Faux
FIN


PROCEDURE INTERNE AffichageLignes(Fichier,Cheminfichier,TailleDuFichier)
Trace("")
Trace("***************************************************************************************")
Trace("FICHIER "+Fichier+": Affichage des premières lignes pour comparaison")
Trace("***************************************************************************************")
Trace("")
IDFichier2 est entier = fOuvre(Cheminfichier)
c est un entier sur 8 octets
t est un chaîne ANSI
fPositionne(IDFichier2,0,fpDébut)
POUR c=1 À TailleDuFichier PAS 100
t=fLit(IDFichier2,100)
Trace(c,t)
SI c>=1000 ALORS
SORTIR
FIN
FIN
fFerme(IDFichier2)
FIN

PROCEDURE INTERNE AffichageLignesFinales(Fichier,Cheminfichier)

Trace("")
Trace("***************************************************************************************")
Trace("FICHIER "+Fichier+": Affichage des dernières lignes pour comparaison")
Trace("***************************************************************************************")
Trace("")
IDFichier3 est entier = fOuvre(Cheminfichier)
c est un entier sur 8 octets
t est un chaîne ANSI
fPositionne(IDFichier3,-100,fpFin)
t=fLit(IDFichier3,100)
Trace(c,t)
fFerme(IDFichier3)
FIN

PROCEDURE INTERNE VerifDernierCaractère(cheminFichier,dernier)
//verification finale sur le dernier caractère c'est la cerise sur le gateau
//mais quand le fichier est trop important comment vérifier que tous les caractères ont été modifiés ? en vérifiant les premiers et les derniers
//on en a la certitude
IDFichier1 est entier = fOuvre(cheminFichier)
t est un chaîne ANSI
fPositionne(IDFichier1,-1,fpFin)
t=fLit(IDFichier1,1)
fFerme(IDFichier1)
SI t=dernier
RENVOYER Vrai
FIN
RENVOYER Faux
FIN
Membre enregistré
1 275 messages
Posté le 28 avril 2025 - 13:52
ElPato a écrit :
Bonjour
La commande powershell cypher peut s'avérer utile.

Mais les remarques de André et Fabrice m’ont inspiré pour traiter un seul fichier.
J’ai développé cette procédure et j’attends vos commentaires…

ElPato
Procedure DetruireFichier(CheminfichierSource est chaîne)

AvecTrace est un booléen=Vrai
Sablier(Vrai)
SI PAS fFichierExiste(CheminfichierSource) ALORS
SI AvecTrace ALORS Trace(CheminfichierSource+" pas trouvé")
RENVOYER Faux
FIN

disque est chaîne = fExtraitChemin(CheminfichierSource,fDisque)
repertoire est chaîne = fExtraitChemin(CheminfichierSource,fRépertoire)
SI disque~="" ALORS disque=fDisqueEnCours()
SI repertoire~="" ALORS repertoire=fExtraitChemin(fRepEnCours(),fRépertoire)

//création du nom du fichier final temporaire : il sera dans le même répertoire que le fichier à supprimer
//et créé avec un nom théoriquement unique au monde ! (en tout cas le temps de l'utiliser...)
CheminFichierDestination est chaîne = disque+repertoire+DonneGUID(guidBrut)

IDFichier est un entier
ResEcriture est un entier
texteDeRemplacement est chaîne ANSI
caractèreDeRemplacement est chaîne = "A"
dernierCaractère est chaîne = "Z"
TailleDuFichierSource est entier sur 8 octets = fTaille(CheminfichierSource)
TailleDuFichierDestination est entier sur 8 octets
TailleAnalysée est entier sur 8 octet = 1 000 000 000
NombreDeTours,compteur est entier
reste est entier

SI AvecTrace ALORS
Trace("Disque="+disque)
Trace("Répertoire="+repertoire)
Trace("Source="+CheminfichierSource)
Trace("Destination:"+CheminFichierDestination)
AffichageLignes("SOURCE",CheminfichierSource,TailleDuFichierSource)
FIN

SELON TailleDuFichierSource

CAS < TailleAnalysée
texteDeRemplacement = Complete(texteDeRemplacement,TailleDuFichierSource,caractèreDeRemplacement)
IDFichier = fOuvre(CheminfichierSource, foLectureEcriture)
SI IDFichier<>-1
ResEcriture = fEcrit(IDFichier,texteDeRemplacement,TailleDuFichierSource-1) // on écrase tous les octets (moins 1) du texte d'origine par le même caractère répété n fois
ResEcriture = fEcrit(IDFichier,dernierCaractère,1) // le dernier caractère est différent simplement pour vérification visuelle
SINON
SI AvecTrace ALORS Trace("Erreur écriture")
fFerme(IDFichier)
RENVOYER Faux
FIN
fFerme(IDFichier)

AUTRES CAS
IDFichier = fOuvre(CheminfichierSource,foLectureEcriture)
NombreDeTours = PartieEntière(TailleDuFichierSource/TailleAnalysée)
reste = TailleDuFichierSource-(TailleAnalysée* NombreDeTours)
texteDeRemplacement = Complete(texteDeRemplacement,TailleAnalysée,caractèreDeRemplacement)

SI IDFichier<>-1 ALORS
POUR compteur=1 À NombreDeTours
ResEcriture=fEcrit(IDFichier,texteDeRemplacement,TailleAnalysée)
SI ResEcriture<>-1 ALORS
SI AvecTrace ALORS Trace("tour="+compteur+"/"+NombreDeTours)
SINON
SI AvecTrace ALORS Trace("Erreur écriture")
fFerme(IDFichier)
RENVOYER Faux
FIN
FIN
ResEcriture = fEcrit(IDFichier,texteDeRemplacement,reste-1) // on écrase tous les octets (moins 1) du texte d'origine par le même caractère répété n fois
ResEcriture = fEcrit(IDFichier,dernierCaractère,1) //le dernier caractère est différent simplement pour vérification visuelle et testée
fFerme(IDFichier)
SINON
fFerme(IDFichier)
RENVOYER Faux
FIN
FIN


//on renomme le fichier source dans son nom bidon temporaire
SI fRenomme(CheminfichierSource,CheminFichierDestination) ALORS
TailleDuFichierDestination=fTaille(CheminFichierDestination)
SI TailleDuFichierSource=TailleDuFichierDestination ALORS //dernière vérification à tout hasard...
SI AvecTrace ALORS
AffichageLignes("DESTINATION",CheminFichierDestination,TailleDuFichierDestination)
AffichageLignesFinales("DESTINATION", CheminFichierDestination)
FIN
verif est chaîne //vraiment là j'en fais trop...
SI VerifDernierCaractère(CheminFichierDestination,dernierCaractère) ALORS
verif=Vrai
SINON
verif=Faux
FIN
SI AvecTrace ALORS
Info("Vérifiez la trace !")
FIN
SI fSupprime(CheminFichierDestination) ALORS
//tout est OK: opération terminée : ouf!
RENVOYER verif
SINON
SI AvecTrace ALORS Trace("Suppression impossible de "+CheminFichierDestination)
RENVOYER Faux
FIN
SINON
fSupprime(CheminFichierDestination)
SI AvecTrace ALORS Trace("Taille différente du source et de la destination")
RENVOYER Faux
FIN
SINON
SI AvecTrace ALORS Trace("renommage impossible de: "+ CheminfichierSource+RC+"en"+RC+ CheminFichierDestination)
RENVOYER Faux
FIN


PROCEDURE INTERNE AffichageLignes(Fichier,Cheminfichier,TailleDuFichier)
Trace("")
Trace("***************************************************************************************")
Trace("FICHIER "+Fichier+": Affichage des premières lignes pour comparaison")
Trace("***************************************************************************************")
Trace("")
IDFichier2 est entier = fOuvre(Cheminfichier)
c est un entier sur 8 octets
t est un chaîne ANSI
fPositionne(IDFichier2,0,fpDébut)
POUR c=1 À TailleDuFichier PAS 100
t=fLit(IDFichier2,100)
Trace(c,t)
SI c>=1000 ALORS
SORTIR
FIN
FIN
fFerme(IDFichier2)
FIN

PROCEDURE INTERNE AffichageLignesFinales(Fichier,Cheminfichier)

Trace("")
Trace("***************************************************************************************")
Trace("FICHIER "+Fichier+": Affichage des dernières lignes pour comparaison")
Trace("***************************************************************************************")
Trace("")
IDFichier3 est entier = fOuvre(Cheminfichier)
c est un entier sur 8 octets
t est un chaîne ANSI
fPositionne(IDFichier3,-100,fpFin)
t=fLit(IDFichier3,100)
Trace(c,t)
fFerme(IDFichier3)
FIN

PROCEDURE INTERNE VerifDernierCaractère(cheminFichier,dernier)
//verification finale sur le dernier caractère c'est la cerise sur le gateau
//mais quand le fichier est trop important comment vérifier que tous les caractères ont été modifiés ? en vérifiant les premiers et les derniers
//on en a la certitude
IDFichier1 est entier = fOuvre(cheminFichier)
t est un chaîne ANSI
fPositionne(IDFichier1,-1,fpFin)
t=fLit(IDFichier1,1)
fFerme(IDFichier1)
SI t=dernier
RENVOYER Vrai
FIN
RENVOYER Faux
FIN


Si ça peut aider, voici le code de ma propre procédure de Destruction;
Procedure DetruireFichier(sFichier est une chaîne)

SI OuiNon("Voulez-vous détruire les fichiers sélectionnés?") = Oui ALORS
nIDFichier est un entier
nTaille est un entier = fTaille(sFichier)
sChaîneEcriture est une chaîne = Répète(0, nTaille)

sChemin est une chaîne = fExtraitChemin(sFichier, fRépertoire)
sNouveauNom est une chaîne = sChemin + "Null.txt"
fRenomme(sFichier, sNouveauNom)


// Ouverture du fichier
nIDFichier = fOuvre(sNouveauNom, foEcriture)
SI nIDFichier <> -1 ALORS

// Ecriture du fichier
// sChaîneEcriture contient la chaîne à écrire
SI fEcrit(nIDFichier, &sChaîneEcriture, Taille(sChaîneEcriture)) = Faux ALORS
RENVOYER Faux
FIN
// Fermeture du fichier
SI fFerme(nIDFichier) = 0 ALORS
SI fSupprime(sNouveauNom) = Faux ALORS
RENVOYER Faux
FIN
FIN
SINON
RENVOYER Faux
FIN

RENVOYER Vrai
FIN
RENVOYER Faux


--
Jean Turcotte
WX 2025