none
Accès a repertoire C:\Users\monrep\AppData\Local\Application Data refusé RRS feed

  • Discussion générale

  • Je développe actuellement une application de copie de fichiers tout fonctionne sauf lorsque je tente de copier certains répertoires

    impossible de trouver le bon code pour les permissions d'accès

    j'utilise VS Express 2013 pour Desktop en vb sur Windows 8.1

    Message d'erreur

    Une exception non gérée du type 'System.UnauthorizedAccessException' s'est produite dans mscorlib.dll

    Informations supplémentaires : L'accès au chemin d'accès 'C:\Users\Claude\AppData\Local\Application Data' est refusé.

    Merci pour vos conseils

    Commentaire ;

    Hello programmeurs:-)

    Voici une de mes routines qui sert à copier tous les fichiers d'1 répertoire dans un autre avec la même arborescence

    Chsource est le répertoire à copier

    Chdest est le chemin où copier les fichiers et leurs répertoires

    Chdest2 est le même chemin où est ajouté le chemin des répertoires de la source pour que (par exemple) l'arborescence soit la même que celle qui est copiée

    textbox1.text sert à l'affichage pendant la copie

    Imports System.IO

    Imports System.IO.Directory

    Public Class Form1

        Dim ChDest2, Chdest, Chsource As String

        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        End Sub

       

    Private Sub CfichTrep()

            'exemple

            Chsource = "C:\Users\Claude\Favorites"

            Chdest = "D:\EssaiCopie"

            Dim txtFiles = EnumerateFiles(Chsource, "*.*", SearchOption.AllDirectories)

            For Each CurrentFile As String In txtFiles

              
    ChDest2 = Chdest & Mid(CurrentFile, 3, Len(CurrentFile))

              
    My.Computer.FileSystem.CopyFile(CurrentFile,ChDest2, True)

              
    TextBox1.Text = CurrentFile.ToString

              
    My.Application.DoEvents()

            Next CurrentFile

          
    TextBox1.Text =
    "Copie terminée"

        End Sub

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

          
    CfichTrep()

        End Sub

    End Class


    • Modifié cjardinf samedi 7 juin 2014 16:25
    • Type modifié Aurel Bera vendredi 13 juin 2014 11:18 disc
    samedi 7 juin 2014 07:56

Toutes les réponses

  • Bonjour,

    J'ai eu le même problème récemment mais avec les dossiers "favoris, mes images et vidéos" qui se trouve dans le dossier "mes documents" et qui sont en fait des dossiers cachés/protégés et des "reparsepoint" (des raccourcis ou "points d'analyse"), bref tous ça pour te dire qu'il faut utiliser le "try, catch, end try".

    Dans un premier temps assure toi que t'exécute bien ton VS en mode "admin"

    Ensuite comme je l'ai appris dans ce forum, certain dossier ne peuvent se copier directement, t'es obligé de faire une fonction générale qui analysera et copiera tous les fichiers et sous dossier de ton dossier voulu.

    Voici mon code que j'utilise pour une copie des dossiers que je veux dans chaque profil se trouvant sur le pc.

    Ce code copie le dossier "chrome" se trouvant dans appdata de chaque profil.

    Le sub "copierdossier" est la fonction générale que j'utilise pour chaque copie de dossier de chaque profil et ici dans l'exemple le dossier Chrome.

     Sub Copie_Google()
            Dim Profil As String
            Dim Users As String = My.Application.GetEnvironmentVariable("USERPROFILE").Substring(0, My.Application.GetEnvironmentVariable("USERPROFILE").LastIndexOf("\"))
            For Each Profil In System.IO.Directory.GetDirectories(Users)
                Dim di As New DirectoryInfo(Profil)
                Dim NomProfil As String = di.Name
                Dim Profildestination As String = (Drive & NomPC & "\Profils\" & NomProfil)
                Dim checkFile As System.IO.DirectoryInfo
                checkFile = My.Computer.FileSystem.GetDirectoryInfo(Users & "\" & NomProfil & "\AppData\Local\Google\")
                Dim attributeReader As System.IO.FileAttributes
                attributeReader = checkFile.Attributes
    
                If Directory.Exists(Users & "\" & NomProfil & "\AppData\Local\Google") Then
                    My.Computer.FileSystem.CreateDirectory(Drive & NomPC & "\Profils\" & NomProfil & "\AppData\Local\Google\")
                    Try
                        If (attributeReader And System.IO.FileAttributes.ReparsePoint) = System.IO.FileAttributes.ReparsePoint Then
    
                            Continue For
                        Else
                            CopierDossier(New DirectoryInfo(Users & "\" & NomProfil & "\AppData\Local\Google"), New DirectoryInfo(Profildestination & "\AppData\Local\Google\"))
                        End If
                    Catch erreur As Exception
                        My.Computer.FileSystem.WriteAllText(Drive & NomPC & "\Erreurs.txt", vbCrLf & "-" & erreur.Message & vbCrLf, True)
                    End Try
                End If
            Next
        End Sub
    
    
    
    
    Sub CopierDossier(source As DirectoryInfo, destination As DirectoryInfo)
            destination.Create()
            ' Copier tous les fichiers du répertoire
            For Each fichier In source.GetFiles()
                Try
                    If (fichier.Attributes And FileAttributes.ReparsePoint) = FileAttributes.ReparsePoint Then
                        ' Ignorer le fichier
                        Continue For
                    Else
                        ' Copier le fichier
                        fichier.CopyTo(destination.FullName + fichier.Name, FileIO.UIOption.AllDialogs)
                    End If
                Catch erreur As Exception
                    My.Computer.FileSystem.WriteAllText(Drive & NomPC & "\Erreurs.txt", vbCrLf & "-" & erreur.Message & vbCrLf, True)
                End Try
            Next
            ' Copier récursivement les fichiers du répertoire
            For Each répertoire In source.GetDirectories()
                If (répertoire.Attributes And FileAttributes.ReparsePoint) = FileAttributes.ReparsePoint Then
                    Continue For
                Else
                    CopierDossier(répertoire, New DirectoryInfo(destination.FullName + répertoire.Name + "\"))
                End If
            Next
        End Sub

    A la place de "reparsepoint" tu peux mettre "systeme ou hidden"

    Dans mon exemple si le code rencontre une erreur il la récupère (catch) et l'inscrit dans un fichier texte qui se trouve dans le dossier de destination de la copie et qui porte le nom du pc.

    Pour info j'utilise VS2010Express je sais pas si cela peu avoir une incidence sur le code.

    En espérant avoir été assez clair.

    ++


    • Modifié Bylliboy lundi 9 juin 2014 10:48
    lundi 9 juin 2014 10:47
  • Je voulais rajouter un petit point qui est en fait un problème que je rencontre avec la copie de google.

    Lorsque la copie de google s'effectue et qu'en même temps j'utilise internet (donc google chrome) il m'inscrit un message d'erreur comme quoi tel fichier ne peut être copier car en cours d'utilisation.

    J'aimerai donc utiliser la même astuce que pour les reparsepoint mais je ne trouve rien pour les fichiers en cours d'utilisation du genre "isbusy".

    J'ai déjà posé la question dans un autre de mes poste.

    lundi 9 juin 2014 10:56
  • Bonjour,

    Merci beaucoup pour ta réponse Bylliboy.
    Effectivement, avec ce code il est possible d'éviter des fichiers à l'accès refusé, j'ai déjà commencé avec "System.IO.FileAttributes.Hidden", mais ton code est beaucoup plus élaboré.
    Je vais voir ce que ca donne.

    Pour le dernier point ca me fait pareil pour un fichier ;
    C:\Users\Claude\NTUSER.DAT
    et je cherche la réponse.


    Enfin, j'ai beaucoup recherché, expérimenté sur le site msdn dans tous ce qui est System.Security.Permissions, avec FileIOPermission mais je n'ai pas trouvé, si quelqu'un peut me guider dans ce qui est permission sur ce type de répertoire.
    Merci

    lundi 9 juin 2014 14:09
  • Est ce que t'es administrateur de ta machine?

    Pour le fichier NTUSER.DATA c'est un fichier système protégé, essaye donc avec "System.IO.FileAttributes.syteme"

    lundi 9 juin 2014 14:51
  • Oui, Bylliboy, administrateur et je programme en vb depuis 1997

     J'ai réussi avec

    Or (attributeReader AndSystem.IO.FileAttributes.System) = System.IO.FileAttributes.System _ 

    pour passer NTUSER.DATA

    En règle générale avec System.IO.FileAttributes beaucoup de repertoires se trouve accessibles, mais pas encore tous, bien que je n'ai pas testé toutes les options (System.IO.FileAttributes...)

    A +

    lundi 9 juin 2014 17:12
  • Bonjour

    Mettez chaque copie d'un fichier dans un try & catch. C'est 100% sur, s'il plante pour un fichier ca vas fonctionner avec le suivant.
    J'utilise souvent des fichiers BD SQL Serveur (mdf/ldf) qui même si ne sont pas fichiers système/caches, on ne peut pas les copier. Le plus probable il y a des autres fichiers avec comportement similaire.

    Bien cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mardi 10 juin 2014 07:11
  • Bonjour,

    J'ai essayé la méthode « Mettez chaque copie d'un fichier dans un try & catch » mais pas avec un succès total, notamment en voulant copier C:\Users.
    Je continue à croire que c'est une classe comme "system.security.permissions.fileiopermission" avec

    "system.security.permissions.fileiopermissionaccess, énumération" qui pourrait résoudre ce problème, Mais dans msdn les exemples sont très très succincts.

    En résumé : Si quelqu'un peut me guider à propos des autorisations de copie complète de C:\Users.
    Merci.

    A+

    mercredi 11 juin 2014 19:40
  • En effet vous voulez contourner les contraintes de sécurité. Si c’était possible assez simple, cela indique une sécurité faible.  Gardez le try/catch car toujours on peut avoir des fichiers qui ne peut pas être copiées et essayez de démarrer votre application en tant qu’administrateur.

    Bien cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    jeudi 12 juin 2014 06:13
  • Merci Aurel BERA

    Mon développement avance..., en évitant les répertoires et fichiers à accès refusé.

    Puisque effectivement le traitement par permission ne se présente pas simplement.

    A+

    Cdlt

    • Modifié cjardinf mercredi 25 juin 2014 17:52
    samedi 14 juin 2014 04:41
  • Bonjour
    J'ai trouvé une méthode.

    Un controle qui permet l'accès à tous les répertoires est le controle d'arborescence Treeview, il liste tout, même un disque entier.
    Mais cependant l'accès à la copie directe est toujours refusé pour les répertoires ou fichiers affichant "access denied..."
    Une solution est de contourner le problème en copiant toute l'arborescence dans un fichier par une 1ère routine.
    Ensuite, il suffit de lire le fichier ligne par ligne et de lancer la copie en même temps.
    Pour cette 2ème routine "on error resume next" est le plus performant, il permet (contrairement à son habitude pour ce problème) autant d'accès que la fonction de copie de Windows (celle de l'explorateur) elle-même.
    et l'avantage c'est qu'il n'y a aucun arrêt durant la copie.

    la routine que j'ai faite nécessite un Form, un treeview (TreeView1), un textbox (TextBox1) un bouton (Button1)
    et ce code :


    Imports System
    Imports System.IO


    Public Class Form1

        Dim LireFic As StreamReader
        Dim Chfic, Leslignes As String
        Dim ChDest2, Chdest, Affch As String


        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
          
            'répertoire destination (à créer par vous avant de lancer ce programme !)
            Chdest = "D:\EssaiCopie"
           
            'emplacement et nom du fichier
            Chfic = "D:\EssaiCopie\ListeRepF"
            'supprime le fichier, contenant le répertoire précédemment copié, si il existe.
            If File.Exists(Chfic) Then
                File.Delete(Chfic)
            End If
            'répertoire à copier
            Dim Rep As String = "C:\Users" 'par exemple
            'lister le répertoire dans le fichier
            Arborescence(Rep, TreeView1.Nodes.Add(Rep))
            'copier le répertoire
            LCfich()
        End Sub

       

        Sub Arborescence(ByVal sDossier As String, ByRef sNode As TreeNode)
            'lister le répertoire dans le fichier

            Try
                Dim ListeFichiers() As String = Directory.GetFiles(sDossier)
                Dim Fichier As String = Nothing
                Dim NodeParent As TreeNode
                Dim Node As TreeNode
                NodeParent = sNode
                TextBox1.Text = "Préparation en cours patientez..." 'vous pouvez déployer l'arborescence pendant la préparation
                For Each Fichier In ListeFichiers
                    'mise en arborescence dans le treeview
                    Node = NodeParent.Nodes.Add(Path.GetFileName(Fichier))
                    'entrée de l'ensemble du répertoire à copier dans le fichier ListeRepF
                    '(pour le lire si vous le souhaitez, utilisez Wordpad ou similaire et enlevez le retour automatique à la ligne)
                    My.Computer.FileSystem.WriteAllText(Chfic, Fichier & vbCrLf, True)
                    My.Application.DoEvents()
                Next Fichier
                Dim SousDossiers() As String = Directory.GetDirectories(sDossier)
                Dim SousDossier As String = Nothing
                For Each SousDossier In SousDossiers
                    'mise en arborescence dans le treeview
                    sNode = NodeParent.Nodes.Add(SousDossier)
                    Arborescence(SousDossier, sNode)
                Next SousDossier
            Catch
            End Try

            TextBox1.Text = "Préparation terminée"

        End Sub

        Private Sub LCfich()
            'copier le répertoire

            'pour lire le fichier
            LireFic = New StreamReader(Chfic)
            'lit la 1ère ligne
            Leslignes = LireFic.ReadLine
            'mise en forme répertoire de destination
            ChDest2 = Chdest & Mid(Leslignes, 3, Len(Leslignes))
            'gestion des erreurs
            On Error Resume Next
            'copie du 1er fichier
            If Leslignes <> "" Then My.Computer.FileSystem.CopyFile(Leslignes, ChDest2, True)
            'lit les autres lignes et copie les fichiers
            Do While Not Leslignes Is Nothing
                Leslignes = LireFic.ReadLine
                ChDest2 = Chdest & Mid(Leslignes, 3, Len(Leslignes))
                If Leslignes <> "" Then My.Computer.FileSystem.CopyFile(Leslignes, ChDest2, True)
                'affichage
                Affch = Leslignes
                If Len(Affch) > 100 Then Affch = Mid(Affch, 1, 50) & "..." & Microsoft.VisualBasic.Right(Affch, 50)
                TextBox1.Text = Affch
                My.Application.DoEvents()
            Loop
            LireFic.Close()

            TextBox1.Text = "Copie terminée"

        End Sub

    End Class

    Après, en mettant l'arborescence du répertoire de destination copiée, dans un autre fichier, il est possible de connaître les fichiers qui n'ont pas été copiés,
    Ainsi, le ratio pour mon répertoire Users est de 1,41% de fichiers pas copiés...
    Tandis que pour la copie  d'un répertoire normal avec cette routine il n'y a pas ces pertes.

    Cette routine de démonstration est fiable et rapide, elle peut être adaptée (Treeview est puissant et très souple).
    Si une autre fonction permet la même chose, je veux bien la connaître, ma recherche continue.
    Et aussi, puisque c'est le forum vb microsoft :-) si quelqu'un connaît une solution à ce problème avec la classe system.security.permissions.fileiopermissionaccess, énumération ou similaire elle m'intéresse...

    mercredi 25 juin 2014 17:55
  • Bonjour,

    Je viens de découvrir ce thread super intéressant. Super intéressant car je m'était déjà heurté à ce genre de problème.

    Il y a 2 points à voir dans votre demande :

    Point 1 : vous tentez d'accéder aux données d'un autre utilisateur, ce que le système ne permet pas, d'où l'exception obtenue. Par contre cela n'aurait posé aucun problème si c'était les données correspondant à l'utilisateur en cours. Par exemple, si vous êtes connecté en tant qu'utilisateur "claude", alors la fonction Environment.GetFolderPath utilisée avec Environment.SpecialFolder.LocalApplicationData vous aurait bien renvoyé le chemin 'C:\Users\Claude\AppData\Local\Application Data'. Mais en l'occurrence, vous n'êtes pas connecté en tant que 'claude'.

    Point 2 : il s'agit du problème que j'avais rencontré aussi, c'est que lorsque l'on fait un appel à "EnumerateFiles" avec l'option "SearchOptions.AllDirectories" et qu'il se produit une exception, alors l'énumération s'arrête aussitôt alors qu'on aurait souhaité qu'elle fasse une action sur l'exception (tracer par exemple) mais que ça continue l'énumération. En fait, il faut voir une chose : là où ça s'arrête, ce n'est pas lorsque la méthode essaie d'accéder au premier fichier mais lorsqu'elle essaie d'accéder au sous-répertoire en lecture avant de commencer à lire le premier fichier.

    Alors je vois que vous avez voulu contourner le problème en essayant de recopier à chaque fois les sous-arborescences, ce qui, à mon avis, n'est pas une bonne solution car cela va poser des problèmes de lenteur.

    Ce que j'avais fait pour contourner ce problème, c'est écrire ma propre fonction d'extension "EnumerateFiles" et je lui passais comme paramètre un delegate de type "Action(Of Exception)" ce qui me permettait de pouvoir lui dire qu'est-ce que je veux faire lorsqu'une exception est levée dans un sous-répertoire.
    L'idée de cette fonction, est de faire des appels récursifs de la méthode normale "EnumerateFiles" avec l'option "TopDirectoryOnly". Ainsi, je place cet appel dans un try, et sur le "catch" j'appelle la méthode de délégué passé en paramètre, et en plus je peux continuer l'énumération.

    Cela évite ainsi de devoir faire des recopies de dossiers inutilement, qu'en pensez-vous?


    Philippe

    jeudi 26 juin 2014 07:28
  • Merci Philippe, cependant j'ai trouvé la solution (voir ma réponse précédente).
    Je l'adapte actuellement à mon programme de copie avec différentes idées, tableau de chaîne string pour remplacer le fichier, affichage classique d'un pgme de copie, fonction à utilisée etc.

    Merci à tous encore.

    jeudi 26 juin 2014 11:25
  • Merci Philippe, cependant j'ai trouvé la solution (voir ma réponse précédente).
    Je l'adapte actuellement à mon programme de copie avec différentes idées, tableau de chaîne string pour remplacer le fichier, affichage classique d'un pgme de copie, fonction à utilisée etc.

    Merci à tous encore.

    Vous devriez vraiment regarder le contenu de ma réponse avec attention et prendre connaissance du contenu car je vous explique dedans que votre solution risque de manquer de performance (essayer de recopier des sous-dossiers inutilement est coûteux) et que j'ai une solution moins coûteuse. Avez-vous bien regardé ma réponse?

    J'insiste pour être sûr que vous n'ayez pas de regrets au cas où...

    Cordialement,


    Philippe

    jeudi 26 juin 2014 14:19
  • Maintenant que je peux copier l'ensemble de c:\users sans être dérangé par les exceptions, je peux comme vous dites trier les sous-répertoires vraiment utiles afin d'alléger la copie.

    Ca fait partie de la suite de mon programme de copie.

    Cdlt

    vendredi 27 juin 2014 16:14