2010-08-26 5 views
2

J'utilise C# pour l'application WinForms dans VS2010 et je devais créer un répertoire dans lequel le chemin était trop grand pour les méthodes .NET (limite de 248 caractères, je crois) et fonctionnait à travers les suggestions de google pour utiliser le Unicode Win32 CreateDirectory(). Je l'avais d'abord essayé d'appeler à l'aide d'Unicode et passé paramètres, mais après plusieurs tentatives infructueuses, j'ai réduit le code et je EXACTEMENT en utilisant le code trouvé ici:Aide en utilisant PInvoke CreateDirectory() en C#

http://www.pinvoke.net/default.aspx/Structures/SECURITY_ATTRIBUTES.html

Je reçois toujours la même erreur:

System.AccessViolationException a été interceptée Message = Tentative de lecture ou d'écriture de la mémoire protégée. C'est souvent une indication que l'autre mémoire est corrompue.

Certes, je ne sais rien à propos de l'appel des fonctions Win32, je suis vraiment juste en train de tirer ce que je peux trouver en ligne et en essayant d'apprendre. Quelqu'un peut-il me dire ce que je fais mal? Suppression du code non essentiel pour la question, j'ai:

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Configuration; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Security.AccessControl; 
using System.Text; 

namespace RFCGenerator 
{ 

    [StructLayout(LayoutKind.Sequential)] 
    public struct SECURITY_ATTRIBUTES 
    { 
     public int nLength; 
     public IntPtr lpSecurityDescriptor; 
     public int bInheritHandle; 
    } 

    public class RFC 
    { 

     [DllImport("kernel32.dll")] 
     static extern bool CreateDirectory(string lpPathName, SECURITY_ATTRIBUTES lpSecurityAttributes); 

     protected void CopyDirectory(Uri Source, Uri Destination) 
     { 

      SECURITY_ATTRIBUTES lpSecurityAttributes = new SECURITY_ATTRIBUTES(); 
      DirectorySecurity security = new DirectorySecurity(); 
      lpSecurityAttributes.nLength = Marshal.SizeOf(lpSecurityAttributes); 
      byte[] src = security.GetSecurityDescriptorBinaryForm(); 
      IntPtr dest = Marshal.AllocHGlobal(src.Length); 
      Marshal.Copy(src, 0, dest, src.Length); 
      lpSecurityAttributes.lpSecurityDescriptor = dest; 
      string path = @"C:\Test"; 
      CreateDirectory(path, lpSecurityAttributes); 
     } 
    } 
} 

MISE À JOUR: en utilisant la suggestion de Hans, je l'ai fait que cela fonctionne au niveau local. Cependant, lorsque je tente de créer un répertoire en utilisant une adresse UNC, comme en passant:

path = @"\\mydomain.com\foo\bar\newfolder" 

-je obtenir maintenant:

System.ComponentModel.Win32Exception a été capturé message = Le nom de fichier, nom de répertoire, ou la syntaxe d'étiquette de volume est incorrecte

J'ai vérifié que \\ mydomain.com \ foo \ bar \ existe.

SOLUTION:

En utilisant le code de Hans et une modification mineure pour vérifier si elle est un chemin UNC (référence: http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx, sous "Longueur maximale du chemin Limitation"):

string UnicodePath = (path.StartsWith(@"\\")) ? @"\\?\UNC\" + (path.Remove(0, 2)) : @"\\?\" + path; 
if (!CreateDirectory(UnicodePath, IntPtr.Zero)) 
    throw new System.ComponentModel.Win32Exception(); 
+0

question rapide: Avez-vous essayé de changer dans la racine du lecteur C, puis de définir path = "Test"? Cela fait longtemps que j'ai travaillé avec l'API Win32 dans la capacité, mais je crois me rappeler que l'API Win32 ne fonctionne que sur les composants de chemin, pas sur le chemin complet. – DevSolo

Répondre

4

Vous n'utilisez pas Version Unicode, qui nécessite CharSet = CharSet.Unicode dans la déclaration [DllImport]. De plus, la création de répertoires avec des noms longs n'a rien à voir avec l'attribut de sécurité. Vous devez préfixer le nom avec @"\\?\". Ainsi:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes); 
... 
if (!CreateDirectory(@"\\?\" + path, IntPtr.Zero)) 
    throw new Win32Exception(); 
+0

Fantastique - merci beaucoup, Hans. J'ai défini le jeu de caractères Unicode et utilisé le "\\? \" À l'origine, mais je les ai supprimés pour simplifier mes tests. C'était l'attribut de sécurité qui me donnait apparemment l'erreur. Cependant, je rencontre maintenant un nouveau problème. Je vais ajouter à mon message original. – heath

+0

Votre question est la même. Commencez un nouveau sujet pour une nouvelle question. –

+0

Désolé, il m'a fallu un moment pour mettre à jour. – heath