访问 Samba 共享,无驱动器映射,带 IP 地址 - C#

发布于 2024-12-22 09:27:35 字数 6972 浏览 1 评论 0原文

我正在尝试访问需要身份验证的 samba 共享。我不想映射驱动器。

我目前正在使用 samba 共享该主机名,该主机名已在 DNS 中注册。它不适用于普通 IP 地址。

我已经做了一些工作,使其同时工作(添加到 Windows 主机文件)

这是我在下面使用的代码:

public class PinvokeWindowsNetworking
{
    #region Consts
    const int RESOURCE_CONNECTED = 0x00000001;
    const int RESOURCE_GLOBALNET = 0x00000002;
    const int RESOURCE_REMEMBERED = 0x00000003;

    const int RESOURCETYPE_ANY = 0x00000000;
    const int RESOURCETYPE_DISK = 0x00000001;
    const int RESOURCETYPE_PRINT = 0x00000002;

    const int RESOURCEDISPLAYTYPE_GENERIC = 0x00000000;
    const int RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001;
    const int RESOURCEDISPLAYTYPE_SERVER = 0x00000002;
    const int RESOURCEDISPLAYTYPE_SHARE = 0x00000003;
    const int RESOURCEDISPLAYTYPE_FILE = 0x00000004;
    const int RESOURCEDISPLAYTYPE_GROUP = 0x00000005;

    const int RESOURCEUSAGE_CONNECTABLE = 0x00000001;
    const int RESOURCEUSAGE_CONTAINER = 0x00000002;


    const int CONNECT_INTERACTIVE = 0x00000008;
    const int CONNECT_PROMPT = 0x00000010;
    const int CONNECT_REDIRECT = 0x00000080;
    const int CONNECT_UPDATE_PROFILE = 0x00000001;
    const int CONNECT_COMMANDLINE = 0x00000800;
    const int CONNECT_CMD_SAVECRED = 0x00001000;

    const int CONNECT_LOCALDRIVE = 0x00000100;
    #endregion

    #region Errors
    const int NO_ERROR = 0;

    const int ERROR_ACCESS_DENIED = 5;
    const int ERROR_ALREADY_ASSIGNED = 85;
    const int ERROR_BAD_DEVICE = 1200;
    const int ERROR_BAD_NET_NAME = 67;
    const int ERROR_BAD_PROVIDER = 1204;
    const int ERROR_CANCELLED = 1223;
    const int ERROR_EXTENDED_ERROR = 1208;
    const int ERROR_INVALID_ADDRESS = 487;
    const int ERROR_INVALID_PARAMETER = 87;
    const int ERROR_INVALID_PASSWORD = 1216;
    const int ERROR_MORE_DATA = 234;
    const int ERROR_NO_MORE_ITEMS = 259;
    const int ERROR_NO_NET_OR_BAD_PATH = 1203;
    const int ERROR_NO_NETWORK = 1222;

    const int ERROR_BAD_PROFILE = 1206;
    const int ERROR_CANNOT_OPEN_PROFILE = 1205;
    const int ERROR_DEVICE_IN_USE = 2404;
    const int ERROR_NOT_CONNECTED = 2250;
    const int ERROR_OPEN_FILES = 2401;

    private struct ErrorClass
    {
        public int num;
        public string message;
        public ErrorClass(int num, string message)
        {
            this.num = num;
            this.message = message;
        }
    }


    // Created with excel formula:
    // ="new ErrorClass("&A1&", """&PROPER(SUBSTITUTE(MID(A1,7,LEN(A1)-6), "_", " "))&"""), "
    private static ErrorClass[] ERROR_LIST = new ErrorClass[] {
        new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"), 
        new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"), 
        new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"), 
        new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"), 
        new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"), 
        new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"), 
        new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), 
        new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"), 
        new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"), 
        new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"), 
        new ErrorClass(ERROR_MORE_DATA, "Error: More Data"), 
        new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"), 
        new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"), 
        new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"), 
        new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"), 
        new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"), 
        new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"), 
        new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), 
        new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"), 
        new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"), 
    };

    private static string getErrorForNumber(int errNum)
    {
        try
        {
            foreach (ErrorClass er in ERROR_LIST)
            {
                if (er.num == errNum) return er.message;
            }
            return "Error: Unknown, " + errNum;
        }
        catch (Exception _ex)
        {
            Console.WriteLine(String.Format("Error: (Pinvoke) Getting Error. Error Number: {0} Exception: {1}", errNum, _ex));
        }
        return "Error: Unknown, " + errNum;
    }
    #endregion

    [DllImport("Mpr.dll")]
    private static extern int WNetUseConnection(
        IntPtr hwndOwner,
        NETRESOURCE lpNetResource,
        string lpPassword,
        string lpUserID,
        int dwFlags,
        string lpAccessName,
        string lpBufferSize,
        string lpResult
        );

    [DllImport("Mpr.dll")]
    private static extern int WNetCancelConnection2(
        string lpName,
        int dwFlags,
        bool fForce
        );

    [StructLayout(LayoutKind.Sequential)]
    private class NETRESOURCE
    {
        public int dwScope = 0;
        public int dwType = 0;
        public int dwDisplayType = 0;
        public int dwUsage = 0;
        public string lpLocalName = "";
        public string lpRemoteName = "";
        public string lpComment = "";
        public string lpProvider = "";
    }


    public static string connectToRemote(string remoteUNC, string username, string password)
    {
        try
        {
            return connectToRemote(remoteUNC, username, password, false);
        }
        catch (Exception _ex)
        {
            Console.WriteLine("Error: (Pinvoke) Getting Error connectToRemote" + _ex);
        }
        return connectToRemote(remoteUNC, username, password, false);
    }

    public static string connectToRemote(string remoteUNC, string username, string password, bool promptUser)
    {
        try
        {
            NETRESOURCE nr = new NETRESOURCE();
            nr.dwType = RESOURCETYPE_DISK;
            nr.lpRemoteName = remoteUNC;
            //          nr.lpLocalName = "F:";

            int ret;
            if (promptUser)
                ret = WNetUseConnection(IntPtr.Zero, nr, "", "", CONNECT_INTERACTIVE | CONNECT_PROMPT, null, null, null);
            else
                ret = WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);

            if (ret == NO_ERROR) return null;
            return getErrorForNumber(ret);
        }
        catch (Exception _ex)
        {
            Console.WriteLine("Error: (Pinvoke) Getting Error connectToRemote" + _ex);
        }
        return "Error: (Pinvoke) Getting Error connectToRemote";
    }

    public static string disconnectRemote(string remoteUNC)
    {
        int ret = WNetCancelConnection2(remoteUNC, CONNECT_UPDATE_PROFILE, false);
        if (ret == NO_ERROR) return null;
        return getErrorForNumber(ret);
    }
}

那么有什么想法吗?

提前致谢!

I'm trying to access a samba share that requires authentication. I do not want the drive to be mapped.

I currently have this working with samba shares that the host-name is registered with the DNS. It will not work with a plain IP address.

I've done some work rounds to make it work in the mean time (adding to windows hosts file)

This is the code I'm using below:

public class PinvokeWindowsNetworking
{
    #region Consts
    const int RESOURCE_CONNECTED = 0x00000001;
    const int RESOURCE_GLOBALNET = 0x00000002;
    const int RESOURCE_REMEMBERED = 0x00000003;

    const int RESOURCETYPE_ANY = 0x00000000;
    const int RESOURCETYPE_DISK = 0x00000001;
    const int RESOURCETYPE_PRINT = 0x00000002;

    const int RESOURCEDISPLAYTYPE_GENERIC = 0x00000000;
    const int RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001;
    const int RESOURCEDISPLAYTYPE_SERVER = 0x00000002;
    const int RESOURCEDISPLAYTYPE_SHARE = 0x00000003;
    const int RESOURCEDISPLAYTYPE_FILE = 0x00000004;
    const int RESOURCEDISPLAYTYPE_GROUP = 0x00000005;

    const int RESOURCEUSAGE_CONNECTABLE = 0x00000001;
    const int RESOURCEUSAGE_CONTAINER = 0x00000002;


    const int CONNECT_INTERACTIVE = 0x00000008;
    const int CONNECT_PROMPT = 0x00000010;
    const int CONNECT_REDIRECT = 0x00000080;
    const int CONNECT_UPDATE_PROFILE = 0x00000001;
    const int CONNECT_COMMANDLINE = 0x00000800;
    const int CONNECT_CMD_SAVECRED = 0x00001000;

    const int CONNECT_LOCALDRIVE = 0x00000100;
    #endregion

    #region Errors
    const int NO_ERROR = 0;

    const int ERROR_ACCESS_DENIED = 5;
    const int ERROR_ALREADY_ASSIGNED = 85;
    const int ERROR_BAD_DEVICE = 1200;
    const int ERROR_BAD_NET_NAME = 67;
    const int ERROR_BAD_PROVIDER = 1204;
    const int ERROR_CANCELLED = 1223;
    const int ERROR_EXTENDED_ERROR = 1208;
    const int ERROR_INVALID_ADDRESS = 487;
    const int ERROR_INVALID_PARAMETER = 87;
    const int ERROR_INVALID_PASSWORD = 1216;
    const int ERROR_MORE_DATA = 234;
    const int ERROR_NO_MORE_ITEMS = 259;
    const int ERROR_NO_NET_OR_BAD_PATH = 1203;
    const int ERROR_NO_NETWORK = 1222;

    const int ERROR_BAD_PROFILE = 1206;
    const int ERROR_CANNOT_OPEN_PROFILE = 1205;
    const int ERROR_DEVICE_IN_USE = 2404;
    const int ERROR_NOT_CONNECTED = 2250;
    const int ERROR_OPEN_FILES = 2401;

    private struct ErrorClass
    {
        public int num;
        public string message;
        public ErrorClass(int num, string message)
        {
            this.num = num;
            this.message = message;
        }
    }


    // Created with excel formula:
    // ="new ErrorClass("&A1&", """&PROPER(SUBSTITUTE(MID(A1,7,LEN(A1)-6), "_", " "))&"""), "
    private static ErrorClass[] ERROR_LIST = new ErrorClass[] {
        new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"), 
        new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"), 
        new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"), 
        new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"), 
        new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"), 
        new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"), 
        new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), 
        new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"), 
        new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"), 
        new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"), 
        new ErrorClass(ERROR_MORE_DATA, "Error: More Data"), 
        new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"), 
        new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"), 
        new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"), 
        new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"), 
        new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"), 
        new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"), 
        new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), 
        new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"), 
        new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"), 
    };

    private static string getErrorForNumber(int errNum)
    {
        try
        {
            foreach (ErrorClass er in ERROR_LIST)
            {
                if (er.num == errNum) return er.message;
            }
            return "Error: Unknown, " + errNum;
        }
        catch (Exception _ex)
        {
            Console.WriteLine(String.Format("Error: (Pinvoke) Getting Error. Error Number: {0} Exception: {1}", errNum, _ex));
        }
        return "Error: Unknown, " + errNum;
    }
    #endregion

    [DllImport("Mpr.dll")]
    private static extern int WNetUseConnection(
        IntPtr hwndOwner,
        NETRESOURCE lpNetResource,
        string lpPassword,
        string lpUserID,
        int dwFlags,
        string lpAccessName,
        string lpBufferSize,
        string lpResult
        );

    [DllImport("Mpr.dll")]
    private static extern int WNetCancelConnection2(
        string lpName,
        int dwFlags,
        bool fForce
        );

    [StructLayout(LayoutKind.Sequential)]
    private class NETRESOURCE
    {
        public int dwScope = 0;
        public int dwType = 0;
        public int dwDisplayType = 0;
        public int dwUsage = 0;
        public string lpLocalName = "";
        public string lpRemoteName = "";
        public string lpComment = "";
        public string lpProvider = "";
    }


    public static string connectToRemote(string remoteUNC, string username, string password)
    {
        try
        {
            return connectToRemote(remoteUNC, username, password, false);
        }
        catch (Exception _ex)
        {
            Console.WriteLine("Error: (Pinvoke) Getting Error connectToRemote" + _ex);
        }
        return connectToRemote(remoteUNC, username, password, false);
    }

    public static string connectToRemote(string remoteUNC, string username, string password, bool promptUser)
    {
        try
        {
            NETRESOURCE nr = new NETRESOURCE();
            nr.dwType = RESOURCETYPE_DISK;
            nr.lpRemoteName = remoteUNC;
            //          nr.lpLocalName = "F:";

            int ret;
            if (promptUser)
                ret = WNetUseConnection(IntPtr.Zero, nr, "", "", CONNECT_INTERACTIVE | CONNECT_PROMPT, null, null, null);
            else
                ret = WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);

            if (ret == NO_ERROR) return null;
            return getErrorForNumber(ret);
        }
        catch (Exception _ex)
        {
            Console.WriteLine("Error: (Pinvoke) Getting Error connectToRemote" + _ex);
        }
        return "Error: (Pinvoke) Getting Error connectToRemote";
    }

    public static string disconnectRemote(string remoteUNC)
    {
        int ret = WNetCancelConnection2(remoteUNC, CONNECT_UPDATE_PROFILE, false);
        if (ret == NO_ERROR) return null;
        return getErrorForNumber(ret);
    }
}

So Any ideas ?

Thanks in Advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筱武穆 2024-12-29 09:27:35

如前所述: 访问 Windows 共享在会话打开之前通过 UNC 路径

这有点重复,但简短的版本是使用 UNC 路径:

\\hostnameorIP\sharename\folder\within\share\file.txt

你应该能够像 C# 中的任何其他文件一样对待它,并且无需映射就可以了。这也可以直接在 Windows 资源管理器中运行。我一直这样做,因为如果与共享的连接很慢(对我来说确实如此),工作中的映射会导致我的电脑和其他一些 Windows 资源管理器的运行速度变慢。

比如:

using System.IO;
FileStream lFileStream = new FileStream(@"\\hostnameorIP\sharename\folder\within\share\file.txt",...);

// Do stuff with it

应该可以正常工作。

As mentioned: Access to a windows share through UNC path, before the session opening

This is kind of a duplicate, but the short version is to use UNC paths:

\\hostnameorIP\sharename\folder\within\share\file.txt

You should be able to treat it like any other file in C# and be fine, without mapping. This also works directly in Windows explorer. I do it all the time because mapping at work causes My computer and some other Windows Explorer things to run slower if the connection to the share is slow (which for me, it is).

Something like:

using System.IO;
FileStream lFileStream = new FileStream(@"\\hostnameorIP\sharename\folder\within\share\file.txt",...);

// Do stuff with it

Should work fine.

べ映画 2024-12-29 09:27:35

远程服务器实际上是 Samba 服务器,还是某种其他类型的 SMB 服务器(如 Windows)?

Samba 将允许通过 IP 地址进行连接,但大多数其他 SMB 服务器(如 Windows)通常不允许。并要求您有 NetBIOS 名称。

Is the remote server actually a Samba server, or some other sort of SMB server (like Windows) ?

Samba will allow connections by IP address, but most other SMB servers (like Windows) often do not. And require you to have the NetBIOS name.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文