PSTW_CentralizeSystem/Areas/MMS/Models/NetworkAccessService.cs

128 lines
4.3 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.ComponentModel;
using System.Threading;
public class NetworkShareAccess : IDisposable
{
private readonly string _networkPath;
private readonly string _username;
private readonly string _password;
private bool _isConnected = false;
private static readonly object _lock = new object();
public NetworkShareAccess(string networkPath, string username, string password)
{
_networkPath = networkPath?.Trim().Replace('/', '\\') ?? throw new ArgumentNullException(nameof(networkPath));
if (!_networkPath.StartsWith(@"\\"))
throw new ArgumentException("Network path must start with \\\\");
_username = username ?? throw new ArgumentNullException(nameof(username));
_password = password ?? throw new ArgumentNullException(nameof(password));
}
public void ConnectToNetworkPath()
{
lock (_lock)
{
if (_isConnected) return;
int retries = 0;
while (retries < 3)
{
try
{
var netResource = new NetResource
{
Scope = ResourceScope.GlobalNetwork,
ResourceType = ResourceType.Disk,
DisplayType = ResourceDisplayType.Share,
RemoteName = _networkPath
};
int result = WNetAddConnection2(netResource, _password, _username, 0);
if (result == 0)
{
_isConnected = true;
Console.WriteLine($"Connected to {_networkPath}");
return;
}
if (result == 1219) // Multiple connections
{
WNetCancelConnection2(_networkPath, 0, true);
Thread.Sleep(1000);
retries++;
continue;
}
throw new IOException($"Failed to connect. Error {result}: {GetNetworkErrorDescription(result)}");
}
catch
{
if (++retries >= 3) throw;
Thread.Sleep(1000);
}
}
}
}
public void DisconnectFromNetworkShare()
{
lock (_lock)
{
if (!_isConnected) return;
try
{
int result = WNetCancelConnection2(_networkPath, 0, true);
if (result != 0)
Console.WriteLine($"Warning: Disconnect failed (Error {result})");
}
finally
{
_isConnected = false;
}
}
}
public void Dispose() => DisconnectFromNetworkShare();
private string GetNetworkErrorDescription(int errorCode) => errorCode switch
{
5 => "Access denied",
53 => "Network path not found",
67 => "Network name not found",
85 => "Network connection already exists",
86 => "Invalid password",
1219 => "Multiple connections to a server or shared resource not allowed",
_ => new Win32Exception(errorCode).Message
};
[DllImport("mpr.dll", CharSet = CharSet.Unicode)]
private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);
[DllImport("mpr.dll", CharSet = CharSet.Unicode)]
private static extern int WNetCancelConnection2(string name, int flags, bool force);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private class NetResource
{
public ResourceScope Scope;
public ResourceType ResourceType;
public ResourceDisplayType DisplayType;
public int Usage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
private enum ResourceScope { Connected = 1, GlobalNetwork, Remembered, Recent, Context }
private enum ResourceType { Any = 0, Disk = 1, Print = 2, Reserved = 8 }
private enum ResourceDisplayType { Generic = 0x0, Domain = 0x01, Server = 0x02, Share = 0x03, File = 0x04, Group = 0x05 }
}