我过去几天一直试图将文件放入我的应用程序中的samba共享文件夹中。
到目前为止故事
我获取了UNCAccessWithCredentials
找到的here类的副本,并在我的存储库中引用了它。该课程使用NetApi32.dll
我编写了以下代码来检查是否存在连接,如果没有,则创建连接。
bool available = UNCConnection.IsNetworkPathAvailable(WebConfigurationManager.AppSettings[@"ExportFilePath"]);
string uncpath = WebConfigurationManager.AppSettings[@"ExportFilePath"];
string user = WebConfigurationManager.AppSettings["ExportUser"];
string password = WebConfigurationManager.AppSettings["ExportPassword"];
string domain = @"";
string filePath = uncpath + @"\exportFile" + ".txt";
if (!available)
{
using (UNCAccessWithCredentials unc = new UNCAccessWithCredentials())
{
var x = unc.NetUseWithCredentials(uncpath, user, domain, password);
if (x)
{
CsvContext cc = new CsvContext();
cc.Write(
chargesForExport,
filePath,
outputFileDescription);
}
else
{
var error = unc.GetStatusCodeDefinition(unc.LastError);
throw new Exception(String.Format("The following error occured whilst writing to the creditors folder: {0}", error));
}
}
}
else
{
CsvContext cc = new CsvContext();
cc.Write(
chargesForExport,
filePath,
outputFileDescription);
}
问题
通过IIS Express在调试中运行时,这没有问题。
我从cmd行运行'net use'并在unc.NetUseWithCredentials
之前 - 没有连接
在 - 连接期间
使用后 - 无连接
当我在完全成熟的IIS上部署到实时或本地托管时,我看到错误代码'1326',我相信这意味着ERROR_LOGON_FAILURE
。这些凭据肯定有效,因为我可以使用它们浏览到该文件夹,我可以使用它们将网络驱动器映射到此文件夹,它们与我在调试时使用的凭据相同。
我尝试了什么
我已尝试映射网络共享,使用netuse / delete关闭所有现有连接,将IIS应用程序池中的标识更改为自定义帐户,管理员或我的个人AD帐户都没有区别。我还运行了caspol将策略设置为完全信任,但我仍然看到错误 1326 。
我不明白为什么在运行IIS Express时这种方法运行得很好,但是当我在完整的IIS上托管它时,我只看到错误 1326 。
有人能在这看到问题吗??
UNCAccessWithCredentials Class
public class UNCAccessWithCredentials : IDisposable
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct USE_INFO_2
{
internal LPWSTR ui2_local;
internal LPWSTR ui2_remote;
internal LPWSTR ui2_password;
internal DWORD ui2_status;
internal DWORD ui2_asg_type;
internal DWORD ui2_refcount;
internal DWORD ui2_usecount;
internal LPWSTR ui2_username;
internal LPWSTR ui2_domainname;
}
[DllImport("NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern NET_API_STATUS NetUseAdd(
LPWSTR UncServerName,
DWORD Level,
ref USE_INFO_2 Buf,
out DWORD ParmError);
[DllImport("NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern NET_API_STATUS NetUseDel(
LPWSTR UncServerName,
LPWSTR UseName,
DWORD ForceCond);
private bool disposed = false;
private string sUNCPath;
private string sUser;
private string sPassword;
private string sDomain;
private int iLastError;
/// <summary>
/// A disposeable class that allows access to a UNC resource with credentials.
/// </summary>
public UNCAccessWithCredentials()
{
}
/// <summary>
/// The last system error code returned from NetUseAdd or NetUseDel. Success = 0
/// </summary>
public int LastError
{
get { return iLastError; }
}
public void Dispose()
{
if (!this.disposed)
{
NetUseDelete();
}
disposed = true;
GC.SuppressFinalize(this);
}
/// <summary>
/// Connects to a UNC path using the credentials supplied.
/// </summary>
/// <param name="UNCPath">Fully qualified domain name UNC path</param>
/// <param name="User">A user with sufficient rights to access the path.</param>
/// <param name="Domain">Domain of User.</param>
/// <param name="Password">Password of User</param>
/// <returns>True if mapping succeeds. Use LastError to get the system error code.</returns>
public bool NetUseWithCredentials(string UNCPath, string User, string Domain, string Password)
{
sUNCPath = UNCPath;
sUser = User;
sPassword = Password;
sDomain = Domain;
return NetUseWithCredentials();
}
private bool NetUseWithCredentials()
{
uint returncode;
try
{
USE_INFO_2 useinfo = new USE_INFO_2();
useinfo.ui2_remote = sUNCPath;
useinfo.ui2_username = sUser;
useinfo.ui2_domainname = sDomain;
useinfo.ui2_password = sPassword;
useinfo.ui2_asg_type = 0;
useinfo.ui2_usecount = 1;
uint paramErrorIndex;
returncode = NetUseAdd(null, 2, ref useinfo, out paramErrorIndex);
iLastError = (int)returncode;
return returncode == 0;
}
catch
{
iLastError = Marshal.GetLastWin32Error();
return false;
}
}
/// <summary>
/// Ends the connection to the remote resource
/// </summary>
/// <returns>True if it succeeds. Use LastError to get the system error code</returns>
public bool NetUseDelete()
{
uint returncode;
try
{
returncode = NetUseDel(null, sUNCPath, 2);
iLastError = (int)returncode;
return (returncode == 0);
}
catch
{
iLastError = Marshal.GetLastWin32Error();
return false;
}
}
~UNCAccessWithCredentials()
{
Dispose();
}
public string GetStatusCodeDefinition(int errorCode)
{
var test = (StatusCodeDefinitions)errorCode;
return test.ToString();
}
}