[C#]認証ありサーバーへのファイルアップロードのサンプル

便利なクラスはなかったので地道にWin32Apiで実装する。

Win32Api呼び出しクラス

//NativeMethods.cs
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace FileUploader
{
    internal static class NativeMethods
    {
        // 接続切断するWin32 API を宣言
        [DllImport("mpr.dll", EntryPoint = "WNetCancelConnection2", CharSet = CharSet.Unicode)]
        internal static extern int WNetCancelConnection2(string name, Int32 flags, bool force);
        // 認証情報を使って接続するWin32 API宣言
        [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2", CharSet = CharSet.Unicode)]
        internal static extern int WNetAddConnection2(ref NETRESOURCE netResource, string password, string username, Int32 flags);
        //WNetAddConnection2に渡す接続の詳細情報の構造体
        [StructLayout(LayoutKind.Sequential)]
        internal struct NETRESOURCE
        {
            public int Scope;//列挙の範囲
            public int Type;//リソースタイプ
            public int DisplayType;//表示オブジェクト
            public int Usage;//リソースの使用方法
            [MarshalAs(UnmanagedType.LPWStr)]
            public string LocalName;//ローカルデバイス名。使わないならNULL。
            [MarshalAs(UnmanagedType.LPWStr)]
            public string RemoteName;//リモートネットワーク名。使わないならNULL
            [MarshalAs(UnmanagedType.LPWStr)]
            public string Comment;//ネットワーク内の提供者に提供された文字列
            [MarshalAs(UnmanagedType.LPWStr)]
            public string Provider;//リソースを所有しているプロバイダ名
        }
    }
}

ファイルアップロードクラス

//FileUploader.cs

using System;
using System.IO;

namespace FileUploader
{
    public class FileUploader
    {

        #region enum
        enum Win32APIErrorCode
        {
            NO_ERROR = 0,
            ERROR_ACCESS_DENIED = 5,
            ERROR_BAD_NETPATH = 53,
            ERROR_BAD_DEV_TYPE = 66,
            ERROR_BAD_NET_NAME = 67,
            ERROR_ALREADY_ASSIGNED = 85,
            ERROR_INVALID_PASSWORD = 86,
            ERROR_BAD_DEVICE = 1200,
            ERROR_DEVICE_ALREADY_REMEMBERED = 1202,
            ERROR_CANNOT_OPEN_PROFILE = 1205,
            ERROR_BAD_PROFILE = 1206,
            ERROR_EXTENDED_ERROR = 1208,
            ERROR_NO_NET_OR_BAD_PATH = 1203,
            ERROR_SESSION_CREDENTIAL_CONFLICT = 1219,
            ERROR_NO_NETWORK = 1222,
            ERROR_NOT_CONNECTED = 2250,
            ERROR_OPEN_FILES = 2401,
            ERROR_DEVICE_IN_USE = 2404,
        };

        enum DwScope //列挙の範囲
        {
            ZERO = 0, //?
            RESOURCE_CONNECTED, //現在接続されたリソースを列挙する。dwUsageメンバーを指定できない。
            RESOURCE_GLOBALNET, //ネットワークに関するすべてのリソースを列挙する。
            RESOURCE_REMEMBERED, //接続を列挙する。dwUsageメンバーを指定できない。
            RESOURCE_RECENT,
            RESOURCE_CONTEXT,
        };

        enum DwType //リソースタイプ
        {
            RESOURCETYPE_ANY = 0x00, //すべてのリソース
            RESOURCETYPE_DISK = 0x01, //ディスクリソース
            RESOURCETYPE_PRINT = 0x02, //プリンタリソース
            RESOURCETYPE_RESERVED = 0x08,
            RESOURCETYPE_UNKNOWN = -0x01,
        };

        enum DwDisplayType //表示オブジェクト
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN, //ドメインオブジェクトを表示する
            RESOURCEDISPLAYTYPE_SERVER, //サーバオブジェクトを表示する
            RESOURCEDISPLAYTYPE_SHARE, //シェアオブジェクトを表示する
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        };

        enum DwUsage //リソースの使用方法
        {
            ZERO = 0x00,
            RESOURCEUSAGE_CONNECTABLE = 0x01, //接続可能なリソースであることを示す。lpRemoteNameメンバーによって示された名前はWNetAddConnection機能に通過できる。
            RESOURCEUSAGE_CONTAINER = 0x02, //リソースはコンテナリソースであることを示す。lpRemoteNameメンバーによって示された名前はWNetOpenEnum機能に通過できる。
            RESOURCEUSAGE_NOLOCALDEVICE = 0x04,
            RESOURCEUSAGE_SIBLING = 0x08,
            RESOURCEUSAGE_ATTACHED = 0x10,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        };
        #endregion

        // コンストラクタ
        public void Put(string IpAddress)
        {
            string m_remoteName = Path.Combine(Constants.NetworkPrefix, IpAddress, Constants.ShareName);
            // 接続情報を設定  
            NativeMethods.NETRESOURCE m_netResource = new NativeMethods.NETRESOURCE();
            m_netResource.Scope = (int)DwScope.ZERO;
            m_netResource.Type = (int)DwType.RESOURCETYPE_DISK;
            m_netResource.DisplayType = (int)DwDisplayType.RESOURCEDISPLAYTYPE_GENERIC;
            m_netResource.Usage = (int)DwUsage.ZERO;
            m_netResource.LocalName = null;
            m_netResource.RemoteName = m_remoteName;
            m_netResource.Provider = "";

            int ret = 0;

            //既に接続してる可能性があるので一旦切断する
            ret = NativeMethods.WNetCancelConnection2(m_remoteName, 0, true);
            if ("NO_ERROR" == Enum.GetName(typeof(Win32APIErrorCode), ret))
            {
                Console.WriteLine("認証済み: " + Enum.GetName(typeof(Win32APIErrorCode), ret));
            }
            else
            {
                Console.WriteLine("認証未済: " + Enum.GetName(typeof(Win32APIErrorCode), ret));
            }
            //共有フォルダに認証情報を使って接続
            ret = NativeMethods.WNetAddConnection2(ref m_netResource, Constants.Password, Constants.UserName, 0);
            if ("NO_ERROR" == Enum.GetName(typeof(Win32APIErrorCode), ret))
            {
                Console.WriteLine("認証成功: " + Enum.GetName(typeof(Win32APIErrorCode), ret));
                try
                {
                    File.Copy(Path.Combine(Constants.SourceFileDir, Constants.FileName), Path.Combine(Constants.NetworkPrefix, IpAddress, Constants.DestFileDir, Constants.FileName), true);
                    Console.WriteLine("コピー成功");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("コピー失敗: " + ex.Message);
                }
            }
            else
            {
                Console.WriteLine("認証失敗: " + Enum.GetName(typeof(Win32APIErrorCode), ret));
            }
        }
    }
}

 

コメント

タイトルとURLをコピーしました