이전 주제이지만 실제로는 문제가 많습니다. 내가 몇 년 동안 그런 문제를 다루었 기 때문에 나는 그것에 약간의 빛을 두려고 노력할 것이다.
우선 : Windows에서는 하나의 네트워크 공유에서 여러 하위 폴더에 연결할 수 없습니다.
두 번째로 : Windows가 원격 이름으로 연결을 식별하고 있습니다. 따라서 서로 다른 이름을 사용하여 같은 서버에 둘 이상의 연결을 설정할 수 있습니다. www.serwerName.com 및 123.123.123.123 (ip 기준) - 이들은 서로 다른 자격 증명으로 별도의 연결로 처리됩니다.
내 솔루션은 내 serwer에 별칭 IP를 추가하는 것이 었습니다. 내 serwer의 별칭을 10 개 만들었고 내 응용 프로그램이 목록에서 첫 번째 IP를 가져온 다음 차단 된 경우 다음 등.
이 솔루션은 좋지 않지만 작동합니다. 문제는 당신이 serwer IP에 접근 할 수 없을 때입니다. 그 때 무엇? 다음 지점을 확인하십시오 :
마지막으로 : 다음 유일한 해결책은 지정된 네트워크 공유를 사용한 후 사용자의 연결을 끊는 것입니다. 여기에 다른 모든 문제가 시작됩니다 ... 로그인이 다른 사람을 차단하는 많은 것들에 의해 사용됩니다. 예를 들어 누군가가 네트워크 공유에서 Word 문서를 엽니 다. 이제 연결을 끊을 수 없습니다. 하지만 net.exe는 연결을 표시하지 않습니다! 또 다른하지만 몇 분 (약 1 분) 후에 Word 문서를 닫을 때 자동으로 닫히고 새로운 연결을 허용합니다.
내 작업이 이제 연결을 차단하고 사용자에게 알리는 시스템 시스템 요소를 찾으라는 지시가 내려집니다. Word를 닫으면 로그인 할 수 있습니다. 잘하면 할 수 있습니다.
추신. 나는 WinApi cos net.exe로 모든 작업을하고 있는데 훨씬 느리게 작동하고 옵션도 적다.
누군가가 소스 코드를 필요로하는 경우 :
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);
}
}
}
그리고 다른 클래스 :
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;
};
}
그리고 라스 하나
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;
}
}
당신은 그냥 단순한 오류 컨테이너 OperationResult 필요 없어요를 , 필요하지 않습니다. 기본 클래스 ServerProcessorBase에는 하나의 필드 serverAddress 만 포함됩니다.
중요 : CONNECT_TEMPORARY 옵션을 올바르게 설정하지 않으면 문제가 발생합니다. 설정되지 않은 경우, 창문이 탑재 된 드라이브를 기억하고 오류의 원인이 ofcource 컴퓨터를 다시 시작 후에 다시 연결을 시도합니다 : 일부 드라이브를 연결할 수 없습니다 : 억세스 할수 :)
루트 공유에 연결 했으므로 해당 폴더의 하위 폴더에 연결하려고합니다. . 두 연결에 대해 서로 다른 자격 증명을 사용하고 있습니까? –
@simonatrcl : 정확함, 예. 두 경우 모두 동일한 Windows 계정에서 연결을 설정하고 있지만 실제 지정된 자격 증명은 다릅니다. 루트 폴더의 경우 user1/password1이고 하위 폴더의 경우 user2/password2 - 이들은 'net use'에 전달하는 것과 동일한 자격 증명입니다 '. – w128
조금 더 조사한 후에는 나에게 어떤 의미가 없지만 결함에 의한 것처럼 보일지라도 확실히 "디자인상의"문제 일 것 같습니다. – w128