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; //? or required TBD 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 } }