2014-01-07 46 views
6

共有ネットワークフォルダ\\some.domain.net\Sharedがあります。同じWindowsアカウントから複数のサブフォルダへの接続を開きたいが、異なる資格情報を使用したい - これは、最初に同じ共有への他の接続を切断しなくても可能ですか? C#の方法において、Iは、のようにして(P /呼び出し)WNetUseConnection()を使用して特定のサブフォルダに接続しよう:リモート共有フォルダに接続すると「複数の接続が許可されていません」というエラーが発生しますが、切断しようとすると「接続が存在しません」というメッセージが表示されます。

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

これは限り接続がないように正常に動作正確に

すでににサブフォルダを接続するためにWNetUseConnection()呼び出しの瞬間にルートフォルダ(すなわち\\some.domain.net\Shared)のいずれかまたは共有サブフォルダ(または、一般的には、​​上の任意のフォルダへ)を設立しました。すなわち、サブフォルダに接続する前にnet useリターンをそのことを考慮してください。

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

今私は、この記事の上部に示すように、共有のサブフォルダ\\some.domain.net\Shared\Subfolder1に接続したいです。これは、Windowsのエラー1219になります:

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. 

ように、Windows(Server 2008 R2を)提供される異なるアクセス証明書にもかかわらず、\\some.domain.net\Shared\\some.domain.net\Shared\Subfolder1の違いを認識していないようです。ただし、エラー2250で

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

結果を用いて、エラー1219の場合の接続を解除しようとしている:

This network connection does not exist. 

ことだから、私が最初に手動として\\some.domain.net\に開いているすべての接続を解除する必要があるだろうと思われます一度に1つしか開くことができないように見えますが、同時に別のプロセスが接続された共有フォルダにアクセスしているため、これは非常に頑強ではありません。

これを解決し、同じリモートマシン上の複数の共有フォルダにアクティブな接続がある方法はありますか?

+0

私はこれをまっすぐにしています:ルート共有に接続していて、そのサブフォルダに接続しようとしています。両方の接続で異なる資格情報を使用していますか? –

+0

@simonatrcl:正しい、はい。私はどちらの場合も同じWindowsアカウントから接続を確立していますが、指定された実際の認証情報は異なります:root1フォルダのuser1/password1とサブフォルダのuser2/password2 - これらは、 '。 – w128

+0

これをもう少し調べた後、それは確かに "設計上の問題"ですが、それは私には意味をなさないが、不具合のように見えます。 – w128

答えて

1

OK - thisが問題です。それはいくつかの解決策を提示します。どちらも私に少し面倒な音がしますが、あなたにとってはいいかもしれません。この動作は設計上のもの(おそらくセキュリティ上の配慮)のようです。

乾杯 -

+0

ありがとうございますが、残念ながら方法1は状況を解決せず、方法2は私には受け入れられません。 – w128

3

これは古いトピックですが、実際は問題があります。私は数年前からこのような問題を扱ってきたので、それに光を当てようとします。

まず、 Windowsでは、1つのネットワーク共有内の複数のサブフォルダに接続することはできません。

次のすべて: Windowsはリモート名で接続を識別しています。 同じサーバーに複数の接続を確立するには、 www.serwerName.comと123.123.123.123(ip)を使用します。これらは異なる資格情報を持つ別々の接続として扱われます。

私の解決策は、私のserwerにエイリアスIPを追加することでした。私は私のserwerの10エイリアスを作成して、私のアプリはリストから最初にIPを取っていた場合は、それがブロックされた場合は、次の等。

このソリューションはあまり良くはありませんが動作します。問題は、あなたがserwer IPにアクセスできないときです。それでは?すべての

最終::次のポイントを参照してください はその後、唯一の解決策は、指定されたネットワーク共有を使用した後、ユーザーを切断することであり、ここに...接続は、ログインして他の人をブロックしている多くのものが使用している他のすべての問題を開始するために。たとえば、誰かがネットワーク共有からWord文書を開く - 今すぐ切断することはできません!しかし、net.exeは接続を表示しません!もう1つのBUTは、ある時間(約1分)後にWord文書を閉じると自動的に閉じられ、新しい接続を許可します。

私の仕事は、接続をブロックし、ユーザーに通知しているシステムの要素を見つけることに向けられています。Wordを閉じると、ログインできます。 うまくいくことができます。

PS。私はWinApiですべて動作しています。cos net.exeははるかに遅く動作し、オプションも少なくなっています。あなたはそれだけの単純なエラーコンテナですOperationResult必要いけない

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; 
    } 
    } 

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; 
    }; 
    } 

、ラス1誰かがソースコードを必要とする場合

、 必要ありません。 基本クラスServerProcessorBaseには、serverAddressフィールドが1つだけ含まれています。

重要:CONNECT_TEMPORARYオプションを正しく設定しないと、問題メーカーになります。設定されていない場合、ウィンドウにはマウントされたドライブが記憶され、コンピュータの再起動後に接続しようとします。エラーの原因:ドライブを接続できません:)

0

エラーコードこれは別の関数呼び出しでも、WNetCancelConnection2()を使用して共有パスでドライブをマッピングしている間に、私はこのアプローチが解決するかもしれないと感じています。

まず、ネットワーク上のコンピュータの構成を確認する必要があります。それは、ドメイン内にある場合

あなたのユーザ名が\ [ユーザー名]、[ドメイン名]である必要があり、時にはあなたは、単に[ユーザー名]を使用することができます。

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

それがワークグループ内にある場合:

ユーザー名は、[サーバー名] \ [ユーザー名]は、[ユーザー名]を使用しないでなければなりません。

ここで、ServerNameは共有パスのホスト名です。

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

:ワークグループのソリューションは、渡されたユーザ名が現在のログインユーザ名である場合にのみ機能します。 Windowsサービスを使用している場合は、特定のユーザー資格情報と同様にログオンを変更してください。

関連する問題