2016-08-05 12 views
0

Ich habe einen Dienst zum Verschieben von Dateien aus einem Arbeitsordner in einen Sicherungsordner. Die Ordner befinden sich auf einer Netzwerkfreigabe. Daher öffnen wir manchmal eine Datei mit einem Notizblock, um sie zu betrachten. Leute sind nicht (gut, sollten nicht) redigieren, nur schauen.So entfernen Sie eine Dateisperre

Wenn wir versuchen, die Datei zu verschieben, erhalte ich die Erlaubnis verweigert. Ich suche nach einer Möglichkeit in C#, eine Dateisperre zu erzwingen, damit der Dienst die Datei in den Sicherungsordner verschieben kann.

+1

ist dies auf Windows? Wenn Sie kritische Dateien haben, dann machen Sie sie für andere Benutzer schreibgeschützt, andernfalls kann jeder Prozess sie sperren. – muratgu

+0

Hört sich an, als würde ich sie ** kopieren, anstatt sie zu bewegen? move löscht die Dateien nach dem Kopieren aus dem Quellordner. – Slai

Antwort

1

Sie müssen P/Invoke verwenden. Dies sind die Funktionen, die Sie kümmern uns um:

[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
static extern int NetFileEnum(string servername, string basepath, string username, int level, ref IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, IntPtr resume_handle); 

[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
static extern int NetFileClose(string servername, int id); 

[DllImport("Netapi32.dll", SetLastError = true)] 
static extern int NetApiBufferFree(IntPtr buffer); 

Hier einige Code ähnlich dem, was ich mit Erfolg verwendet habe:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
struct FILE_INFO_3 
{ 
    public int fi3_id; 
    public int fi3_permission; 
    public int fi3_num_locks; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string fi3_pathname; 
    [MarshalAs(UnmanagedType.LPWStr)] 
    public string fi3_username; 
} 

private static FILE_INFO_3[] GetLockedFiles(string server, string path) 
{ 
    const int MAX_PREFERRED_LENGTH = -1; 

    int dwReadEntries; 
    int dwTotalEntries; 
    IntPtr pBuffer = IntPtr.Zero; 
    FILE_INFO_3 pCurrent = new FILE_INFO_3(); 
    List<FILE_INFO_3> files = new List<FILE_INFO_3>(); 

    int dwStatus = NetFileEnum(server, path, null, 3, ref pBuffer, MAX_PREFERRED_LENGTH, out dwReadEntries, out dwTotalEntries, IntPtr.Zero); 
    if (dwStatus == 0) 
    { 
     for (int dwIndex = 0; dwIndex < dwReadEntries; dwIndex++) 
     { 
      IntPtr iPtr = new IntPtr(pBuffer.ToInt32() + (dwIndex * Marshal.SizeOf(pCurrent))); 
      pCurrent = (FILE_INFO_3)Marshal.PtrToStructure(iPtr, typeof(FILE_INFO_3)); 
      files.Add(pCurrent); 
     } 
    } 

    NetApiBufferFree(pBuffer); 

    return files.ToArray(); 
} 

static void Main(string[] args) 
{ 
    FILE_INFO_3[] lockedFiles = GetLockedFiles("someservername", @"C:\somepath"); 

    foreach (FILE_INFO_3 lockedFile in lockedFiles) 
    { 
     int dwStatus = NetFileClose(_serverName, lockedFile.fi3_id); 
     // Check dwStatus for success here 
    } 
} 

EDIT: Wie der OP festgestellt unten in den Kommentaren, wenn Wenn Sie 64-Bit kompilieren, müssen Sie ToInt64 anstelle von ToInt32 verwenden. Weitere Informationen finden Sie unter here.

+0

Cool, ich habe ihnen eine Chance gegeben. – BCarlson

+0

Jemand erklärt den Downvote? – itsme86

+0

Ich habe nicht abgestimmt, aber ich denke, dass einige Dateien beschädigt oder unvollständig bleiben können? Wahrscheinlich ist es sicherer, die Datei einfach zu kopieren, ohne sie zu schließen. – Slai