Dot-Net

你能解釋一下為什麼 DirectoryInfo.GetFiles 會產生這個 IOException 嗎?

  • February 27, 2018

我有一個在 Novell 網路上執行的 WinForms 客戶端-伺服器應用程序,當連接到網路上的唯一 Windows 2003 Server 時會產生以下錯誤:

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)

客戶的網路管理員通過手動將工作站使用者名和密碼與伺服器上的本地使用者同步來管理 Windows Server 連接。該錯誤的奇怪之處在於,使用者可以在錯誤之前和之後都寫入伺服器,而無需顯式登錄。

您能解釋為什麼會發生錯誤並提供解決方案嗎?

嘗試訪問不同域中的 Windows 伺服器的文件系統時,我遇到了同樣的問題。問題是執行程序的使用者帳戶無權訪問遠端伺服器。當您使用 Windows 資源管理器時,Windows 在幕後做了額外的工作以使其看起來無縫,因為它猜測您的遠端憑據將匹配您的本地憑據。

如果您將驅動器本地映射到遠端伺服器,然後在程式碼中使用本地映射的驅動器,則應該沒有問題。如果您無法映射驅動器,但可以硬編碼用於遠端伺服器的憑據,則可以使用以下程式碼:

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();
       }
   }
}

然後您可以通過執行以下操作訪問遠端伺服器:

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

引用自:https://stackoverflow.com/questions/582988