Connecting to a remote shared folder results in a "multiple connections are not allowed" error, but when you try to disconnect the reasons "the connection does not exist",

I have a shared network folder \\some.domain.net\Shared , which contains several shared subfolders with different permissions for different users. I want to open connections to several subfolders from the same Windows account, but with different credentials - is it possible without having to disconnect other connections to the same resource first?

More precisely: in the C # method, I try to connect to a specific subfolder using WNetUseConnection() (p / invoke) as follows:

 ConnectToSharedFolder("\\some.domain.net\Shared\Subfolder1", user, password); // calls WNetUseConnection() internally 

This works fine as long as the connection to the root folder (i.e. \\some.domain.net\Shared ) or another shared subfolder (or, generally, to any folder on \\some.domain.net ) is already established at the time of WNetUseConnection() to connect to a subfolder. Suppose that before connecting to a subfolder, net use returns:

 Status Local Remote ------------------------------------------------ OK \\some.domain.net\Shared 

Now I want to also connect to the shared subfolder \\some.domain.net\Shared\Subfolder1 , as shown at the top of this post. This will result in a Windows 1219 error:

 Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again. 

Thus, Windows (Server 2008 R2) does not seem to recognize the difference between \\some.domain.net\Shared and \\some.domain.net\Shared\Subfolder1 , despite the various access credentials provided. However, trying to cancel the connection in case of error 1219 with

 WNetCancelConnection2(@"\\some.domain.net\Shared\Subfolder1", 0, true); // error 2250 

leads to error 2250:

 This network connection does not exist. 

So, I first need to manually cancel all open connections before \\some.domain.net\ , since it seems that only one can be opened at a time, however this does not seem very reliable, since another process can access the connected public folder in the same time.

Are there any ways to solve this problem and have active connections to several shared folders on the same remote computer?

+7
source share
4 answers

This is an old topic, but very relevant and problematic. I will try to shed light on this, because I have been dealing with such problems for a couple of years.

First of all: Windows does not allow you to connect to multiple subfolders in the same network share.

In second place: Windows identifies the connection by the remote name. Thus, you can establish more than one connection to the same server with different names, such as: www.serverName.com and 123.123.123.123 (via ip) - they will be considered as separate connections with different credentials.

So I decided to add an IP alias to my server. I created ten aliases for my server, and my application took the first IP address from the list, then if it was blocked, then the next, etc.

This solution is not very good, but it works. The problem is that you do not have access to the IP address of the server. What then? See the next item:

Last of all: Then the only solution is to disconnect the user after using the specified network share, and here all the other problems begin ... connections are used by many things that block others from entering the system. For example, someone opens a Word document from a network share - now you can’t disconnect! BUT net.exe will not show any connections! Another BUT, when you close a Word document after a while (about a minute), the connection automatically closes and allows new connections.

My job now is to find system elements that block connections and notify the user: close Word and you can log in. Hope this can be done.

PS. I all work with WinApi because net.exe is much slower and offers fewer options.

If someone needs source code:

 public ServerWinProcessor(string serverAddress) : base(serverAddress) { } [DllImport("mpr.dll")] public static extern int WNetAddConnection2(ref NETRESOURCE netResource, string password, string username, uint flags); [DllImport("mpr.dll")] public static extern int WNetCancelConnection2(string lpName, int dwFlags, bool fForce); [DllImport("mpr.dll")] public static extern int WNetOpenEnum(int dwScope, int dwType, int dwUsage, NETRESOURCE2 lpNetResource, out IntPtr lphEnum); [DllImport("Mpr.dll", EntryPoint = "WNetCloseEnum", CallingConvention = CallingConvention.Winapi)] private static extern int WNetCloseEnum(IntPtr hEnum); [DllImport("mpr.dll")] private static extern int WNetEnumResource(IntPtr hEnum, ref uint lpcCount, IntPtr buffer, ref uint lpBufferSize); public OperationResult LoginToNetworkShare(string userName, string password, string shareName) { return LoginToNetworkShare(userName, password, shareName, null); } public OperationResult LoginToNetworkShare(string userName, string password, string shareName, string shareDrive) { NETRESOURCE nr = new NETRESOURCE(); nr.dwType = RESOURCETYPE_DISK; nr.lpLocalName = shareDrive; nr.lpRemoteName = @"\\" + ServerAddress + @"\" + shareName; int result = WNetAddConnection2(ref nr, password, userName, CONNECT_TEMPORARY); return new OperationResult(result); } public Task<OperationResult> LoginToNetworkShareAsync(string userName, string password, string shareName, string shareDrive) { return Task.Factory.StartNew(() => { return LoginToNetworkShare(userName, password, shareName, shareDrive); }); } public OperationResult LogoutFromNetworkSharePath(string sharePath) { int result = WNetCancelConnection2(sharePath, CONNECT_UPDATE_PROFILE, true); return new OperationResult(result); } public OperationResult LogoutFromNetworkShare(string shareName) { int result = WNetCancelConnection2(@"\\" + ServerAddress + @"\" + shareName, CONNECT_UPDATE_PROFILE, true); return new OperationResult(result); } public OperationResult LogoutFromNetworkShareDrive(string driveLetter) { int result = WNetCancelConnection2(driveLetter, CONNECT_UPDATE_PROFILE, true); return new OperationResult(result); } private ArrayList EnumerateServers(NETRESOURCE2 pRsrc, int scope, int type, int usage, ResourceDisplayType displayType) { ArrayList netData = new ArrayList(); ArrayList aData = new ArrayList(); uint bufferSize = 16384; IntPtr buffer = Marshal.AllocHGlobal((int)bufferSize); IntPtr handle = IntPtr.Zero; int result; uint cEntries = 1; result = WNetOpenEnum(scope, type, usage, pRsrc, out handle); if (result == NO_ERROR) { do { result = WNetEnumResource(handle, ref cEntries, buffer, ref bufferSize); if (result == NO_ERROR) { Marshal.PtrToStructure(buffer, pRsrc); if (string.IsNullOrWhiteSpace(pRsrc.lpLocalName) == false && pRsrc.lpRemoteName.Contains(ServerAddress)) if (aData.Contains(pRsrc.lpLocalName) == false) { aData.Add(pRsrc.lpLocalName); netData.Add(new NetworkConnectionInfo(null, pRsrc.lpLocalName)); } if (aData.Contains(pRsrc.lpRemoteName) == false && pRsrc.lpRemoteName.Contains(ServerAddress)) { aData.Add(pRsrc.lpRemoteName); netData.Add(new NetworkConnectionInfo(pRsrc.lpRemoteName, null)); } if ((pRsrc.dwUsage & RESOURCEUSAGE_CONTAINER) == RESOURCEUSAGE_CONTAINER) netData.AddRange(EnumerateServers(pRsrc, scope, type, usage, displayType)); } else if (result != ERROR_NO_MORE_ITEMS) break; } while (result != ERROR_NO_MORE_ITEMS); WNetCloseEnum(handle); } Marshal.FreeHGlobal(buffer); return netData; } public void CloseAllConnections() { NETRESOURCE2 res = new NETRESOURCE2(); ArrayList aData = EnumerateServers(res, RESOURCE_CONNECTED, 0, 0, ResourceDisplayType.RESOURCEDISPLAYTYPE_NETWORK); foreach (NetworkConnectionInfo item in aData) { if (item.IsRemoteOnly) LogoutFromNetworkSharePath(item.RemoteName); else LogoutFromNetworkShareDrive(item.LocalName); } } } 

And other classes:

 public static class Consts { public const int RESOURCETYPE_DISK = 0x1; public const int CONNECT_TEMPORARY = 0x00000004; public const int CONNECT_UPDATE_PROFILE = 0x00000001; public const int RESOURCE_GLOBALNET = 0x00000002; public const int RESOURCE_CONNECTED = 0x00000001; public const int RESOURCEDISPLAYTYPE_SERVER = 0x00000002; public const int RESOURCEUSAGE_CONTAINER = 0x00000002; public const int NO_ERROR = 0x000; public const int ERROR_NOT_CONNECTED = 0x8CA; public const int ERROR_LOGON_FAILURE = 0x52E; public const int ERROR_SESSION_CREDENTIAL_CONFLICT = 0x4C3; public const int ERROR_ALREADY_ASSIGNED = 0x55; public const int ERROR_INVALID_PASSWORD = 0x56; public const int ERROR_INVALID_PARAMETER = 0x57; public const int ERROR_NO_MORE_ITEMS = 0x103; //public const int ERROR_BAD_PROFILE = 0x4B6; //public const int ERROR_CANNOT_OPEN_PROFILE = 0x4B5; //public const int ERROR_DEVICE_IN_USE = 0x964; //public const int ERROR_EXTENDED_ERROR = 0x4B8; //public const int ERROR_OPEN_FILES = 0x961; public enum ResourceDisplayType { RESOURCEDISPLAYTYPE_GENERIC, RESOURCEDISPLAYTYPE_DOMAIN, RESOURCEDISPLAYTYPE_SERVER, RESOURCEDISPLAYTYPE_SHARE, RESOURCEDISPLAYTYPE_FILE, RESOURCEDISPLAYTYPE_GROUP, RESOURCEDISPLAYTYPE_NETWORK, RESOURCEDISPLAYTYPE_ROOT, RESOURCEDISPLAYTYPE_SHAREADMIN, RESOURCEDISPLAYTYPE_DIRECTORY, RESOURCEDISPLAYTYPE_TREE, RESOURCEDISPLAYTYPE_NDSCONTAINER }; [StructLayout(LayoutKind.Sequential)] public struct NETRESOURCE { public int dwScope; public int dwType; public int dwDisplayType; public int dwUsage; public string lpLocalName; public string lpRemoteName; public string Comment; public string lpProvider; } [StructLayout(LayoutKind.Sequential)] public class NETRESOURCE2 { public int dwScope = 0; public int dwType = 0; public ResourceDisplayType dwDisplayType = 0; public int dwUsage = 0; public string lpLocalName = null; public string lpRemoteName = null; public string lpComment = null; public string lpProvider = null; }; } 

And the last one:

 public class NetworkConnectionInfo { public string RemoteName { get; set; } public string LocalName { get; set; } public bool IsRemoteOnly { get; set; } public NetworkConnectionInfo(string remoteName, string localName) { RemoteName = remoteName; LocalName = localName; if (string.IsNullOrWhiteSpace(localName)) IsRemoteOnly = true; } } 

You do not need OperationResult, it is just a container of errors, it is not needed. The ServerProcessorBase base class contains only one serverAddress field.

IMPORTANT: This is a problem if you do not configure it correctly: the CONNECT_TEMPORARY option. If not installed, then Windows will remember the mapped drives and try to connect them after the computer restarts due to an error: it is not possible to connect some drives :) annoying :)

+4
source

OK - this is a problem. He gives a couple of suggested solutions; both sound a little decoy to me, but maybe everything is fine. This seems to be a design behavior (probably security concerns).

Greetings -

+2
source

I want to share the solution that I used for error code 1219 when mapping a drive to a shared path using WNetCancelConnection2() , although this is a different function call, I believe this approach can solve.

First of all, you need to make sure your computers are networked.

If it is in a domain:

Your username should be [DomainName] \ [UserName], sometimes you can just use [UserName].

 var userName = string.IsNullOrEmpty(credentials.Domain) ? credentials.UserName : string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName); 

If he is in a working group:

Your username must be [ServerName] \ [UserName], never use [UserName].

Here ServerName is the hostname of your shared path.

 var userName = string.Format(@"{0}\{1}", serverMachineName, credentials.UserName); 

Note The workgroup solution only works if the transmitted username is the current login username. If you use Windows Service, just change the log as with user credentials

0
source

This is really very annoying and something Microsoft had to fix a long time ago.

However, this bad feature does not always appear. I managed to map three different subdirectories on the same server using different remote credentials from the same Windows user (Windows 10/64-bit Pro), and this worked for years, appearing on every boot. I used the device mapper in Explorer. When it works, it will work, but as soon as a change occurs, for example, the password of one of the remote users will be changed, and this problem may also occur. It also appears when Windows cannot map a specific drive due to an incorrect password, and then captures the credentials of the next remote user and tries to map the device. If this user is confirmed by the server, it seems that Windows will not be able to map the device for which the following remote user credentials were intended. The notion that it is sometimes possible to display subdirectories of a server by the same Windows user using both different and identical credentials of a remote user indicates that this behavior is not strictly controlled by Windows.

Unfortunately, this makes Windows less usable than necessary.

0
source

All Articles