.net - Kan du forklare, hvorfor DirectoryInfo.GetFiles producerer denne IOException?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har en WinForms klient-server-app, der kører på et Novell-netværk, der producerer følgende fejl, når du opretter forbindelse til den enlige Windows 2003-server på netværket:


TYPE: System.IO.IOException
MSG: Logon failure: unknown user name or bad password.

SOURCE: mscorlib
SITE: WinIOError

  at System.IO.\_\_Error.WinIOError(Int32 errorCode, String maybeFullPath)
  at System.IO.Directory.InternalGetFileDirectoryNames(String path,
    String userPathOriginal, String searchPattern, Boolean includeFiles, 
    Boolean includeDirs, SearchOption searchOption)
  at System.IO.DirectoryInfo.GetFiles(String searchPattern, 
    SearchOption searchOption)
  at System.IO.DirectoryInfo.GetFiles(String searchPattern)
  at Ceoimage.Basecamp.DocumentServers.ClientAccessServer.SendQueuedFiles(
    Int32 queueId, Int32 userId, IDocQueueFile[] queueFiles)
  at Ceoimage.Basecamp.ScanDocuments.DataModule.CommitDocumentToQueue(
    QueuedDocumentModelWithCollections doc, IDocQueueFile[] files)


Kundens netværksadministrator styrer Windows Server-forbindelsen manuelt ved at synkronisere arbejdssteds brugernavn og adgangskode med en lokal bruger på serveren. Den ulige ting ved fejlen er, at brugeren kan skrive til serveren både før og efter fejlen, alle uden at logge ind.


Kan du forklare, hvorfor fejlen opstår og tilbyde en løsning?

Bedste reference


Jeg har det samme problem, når jeg prøver at få adgang til filsystemet til en Windows-server i et andet domæne. Problemet er, at den brugerkonto, som programmet kører under, ikke har adgang til den eksterne server. Windows gør ekstra arbejde bag kulisserne for at gøre det ser problemfrit ud, når du bruger Windows Stifinder, fordi det gætter på, at dine fjernbetjeningsoplysninger matcher dine lokale legitimationsoplysninger.


Hvis du kortlægger et drev lokalt til den eksterne server, skal du bruge det lokalt mappede drev i din kode, du bør ikke have problemet. Hvis du ikke kan t kortlægge et drev, men du kan svært kodes de legitimationsoplysninger, der skal bruges til fjernbetjeningen server, så kan du bruge denne kode:


using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Company.Security
{
    public class ImpersonateUser : IDisposable
    {
        [DllImport("advapi32.dll", SetLastError=true)]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

        [DllImport( "kernel32", SetLastError = true )]
        private static extern bool CloseHandle(IntPtr hObject);

        private IntPtr userHandle = IntPtr.Zero;
        private WindowsImpersonationContext impersonationContext;

        public ImpersonateUser( string user, string domain, string password )
        {
            if ( ! string.IsNullOrEmpty( user ) )
            {
                // Call LogonUser to get a token for the user
                bool loggedOn = LogonUser( user, domain, password,
                    9 /*(int)LogonType.LOGON32\_LOGON\_NEW\_CREDENTIALS*/,
                    3 /*(int)LogonProvider.LOGON32\_PROVIDER\_WINNT50*/,
                    out userHandle );
                if ( !loggedOn )
                    throw new Win32Exception( Marshal.GetLastWin32Error() );

                // Begin impersonating the user
                impersonationContext = WindowsIdentity.Impersonate( userHandle );
            }
        }

        public void Dispose()
        {
            if ( userHandle != IntPtr.Zero )
                CloseHandle( userHandle );
            if ( impersonationContext != null )
                impersonationContext.Undo();
        }
    }
}


Derefter kan du få adgang til den eksterne server ved at gøre dette:


using ( new ImpersonateUser( "UserID", "Domain", "Password" ) )
{
    // Any IO code within this block will be able to access the remote server.
}

Andre referencer 1


For VB.Net udviklere (som mig) her er VB.Net versionen:


Imports System
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Security.Principal

Namespace Company.Security
    Public Class ImpersonateUser
        Implements IDisposable

        <DllImport("advapi32.dll", SetLastError:=True)> \_
        Private Shared Function LogonUser(ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String, ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As IntPtr) As Integer
        End Function

        <DllImport("kernel32", SetLastError:=True)> \_
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As Boolean
        End Function

        Private userHandle As IntPtr = IntPtr.Zero
        Private impersonationContext As WindowsImpersonationContext

        Public Sub New(ByVal user As String, ByVal domain As String, ByVal password As String)
            If Not String.IsNullOrEmpty(user) Then
                Dim loggedOn As Integer = LogonUser(user, domain, password, 9, 3, userHandle)
                If Not loggedOn = 1 Then
                    Throw New Win32Exception(Marshal.GetLastWin32Error())
                End If
                impersonationContext = WindowsIdentity.Impersonate(userHandle)
            End If
        End Sub

        Public Sub Dispose() Implements System.IDisposable.Dispose
            If userHandle <> IntPtr.Zero Then
                CloseHandle(userHandle)
            End If
            If impersonationContext IsNot Nothing Then
                impersonationContext.Undo()
            End If
        End Sub

    End Class
End Namespace


Og brug det som:


using New ImpersonateUser( "UserID", "Domain", "Password" ) 
    ' ... your code here
End Using

Andre referencer 2


Jeg synes, du bør forsøge at reproducere problemet, og end at bruge en pakkemonitor til at se netværkstrafikken og se på forskellen mellem svigt situationen og succes situationen.


Skriv derefter en applikation, der bruger de rå api fra vinduer (P/Invokes) for at gengive din fejlssituation og forsøge at finde hvilke parametre der forårsager fejlen. Hvis du er i stand til at løse problemet, end det bare drejer sig om finde ud af, hvordan man får komponenterne til at gøre det, du vil have.


Andre retninger du kan se på (efter at du stabilt kan reproducere problemet):



  • Brug procesovervågning til at logge alle api-opkald og se, hvor fejlen kommer fra.

  • Prøv det på en ren VM/Maskine og prøv at reproducere den der

  • Deaktiver virusscanneren

  • Opdater novell klienten


Andre referencer 3


IMHO, det ser ud til at være en slags bivirkning ved at forfriskende et udløbsautentifikationsmærke (eller noget sådant). [6]


Jeg er som en Active Directory-bruger, der har internetadgang via en proxy (blæksprutte), surfet uden problemer, indtil jeg (med tilfældige mellemrum) får en fejl om manglende legitimationsoplysninger, som er løst ved en sideopdatering i browseren, så fungerer alt fint indtil næste fejl.

Andre referencer 4


Der findes et Microsoft-eksempel på denne adresse: https://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext(v=vs.110).aspx[7]


Men det siger i deres eksempel: 'I Windows Vista og senere skal denne prøve køres som administrator.'


Så denne løsning er kun god, hvis brugeren kører koden er admin på de fleste platforme.