通常のフォルダと違って共有フォルダの場合、認証が必要な場合があります。
ユーザー認証が設定されている場合の方法を紹介します。
WNetAddConnection2A 関数/WNetCancelConnection2 関数
usingの設定は以下のようにします。
using System;
using System.Runtime.InteropServices;
共有フォルダのコネクションを追加する「WNetAddConnection2A 」関数とコネクションを切断する「WNetCancelConnection2 」関数です。
//認証情報を使って接続するWin32 API宣言
[DllImport("mpr.dll", EntryPoint = "WNetAddConnection2", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int WNetAddConnection2(ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, Int32 dwFlags);
//接続切断するWin32 API を宣言
[DllImport("mpr.dll", EntryPoint = "WNetCancelConnection2", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int WNetCancelConnection2(string lpName, Int32 dwFlags, bool fForce);
WNetAddConnection2で使う接続情報の構造体が以下です。
//WNetAddConnection2に渡す接続の詳細情報の構造体
[StructLayout(LayoutKind.Sequential)]
internal struct NETRESOURCE
{
public int dwScope; //列挙の範囲
public int dwType; //リソースタイプ
public int dwDisplayType; //表示オブジェクト
public int dwUsage; //リソースの使用方法
[MarshalAs(UnmanagedType.LPWStr)]
public string lpLocalName; //ローカルデバイス名。使わないならNULL。
[MarshalAs(UnmanagedType.LPWStr)]
public string lpRemoteName; //リモートネットワーク名。使わないならNULL
[MarshalAs(UnmanagedType.LPWStr)]
public string lpComment; //ネットワーク内の提供者に提供された文字列
[MarshalAs(UnmanagedType.LPWStr)]
public string lpProvider; //リソースを所有しているプロバイダ名
}
まずはこれらをクラスの先頭に記述します。
共有フォルダへのアクセス
では実際にアクセスするソースコードを記述します。
// 接続情報を設定
NETRESOURCE netResource = new NETRESOURCE();
netResource.dwScope = 0;
netResource.dwType = 1;
netResource.dwDisplayType = 0;
netResource.dwUsage = 0;
netResource.lpLocalName = ""; // ネットワークドライブにする場合は"z:"などドライブレター設定
netResource.lpRemoteName = share_name;
netResource.lpProvider = "";
int ret = 0;
try
{
//既に接続してる場合があるので一旦切断する
ret = WNetCancelConnection2(share_name, 0, true);
//共有フォルダに認証情報を使って接続
ret = WNetAddConnection2(ref netResource, password, userId, 0);
}
catch (Exception)
{
//エラー処理
return false;
}
//共有フォルダにアクセス可能なのでフォルダがあるかチェックする
if (System.IO.Directory.Exists(share_name) == true)
{
return true;
}
else
{
return false;
}
ユーザーIDとパスワードが変わった時のことを考え、一度切断しています。
コネクションが確立されれば、あとは普通にアクセスできます。
基本的にはこれで終わりです。
アクセスするためのクラスを作成してみました。
共有フォルダへアクセスするためのクラスサンプル
using System;
using System.Runtime.InteropServices;
namespace ShareFolder
{
internal static class ShareFolderAccessClass
{
//認証情報を使って接続するWin32 API宣言
[DllImport("mpr.dll", EntryPoint = "WNetAddConnection2", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int WNetAddConnection2(ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, Int32 dwFlags);
//接続切断するWin32 API を宣言
[DllImport("mpr.dll", EntryPoint = "WNetCancelConnection2", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int WNetCancelConnection2(string lpName, Int32 dwFlags, bool fForce);
//WNetAddConnection2に渡す接続の詳細情報の構造体
[StructLayout(LayoutKind.Sequential)]
internal struct NETRESOURCE
{
public int dwScope;//列挙の範囲
public int dwType;//リソースタイプ
public int dwDisplayType;//表示オブジェクト
public int dwUsage;//リソースの使用方法
[MarshalAs(UnmanagedType.LPWStr)]
public string lpLocalName;//ローカルデバイス名。使わないならNULL。
[MarshalAs(UnmanagedType.LPWStr)]
public string lpRemoteName;//リモートネットワーク名。使わないならNULL
[MarshalAs(UnmanagedType.LPWStr)]
public string lpComment;//ネットワーク内の提供者に提供された文字列
[MarshalAs(UnmanagedType.LPWStr)]
public string lpProvider;//リソースを所有しているプロバイダ名
}
/// <summary>
/// 共有フォルダの存在チェック
/// </summary>
/// <param name="share_name"></param>
/// <param name="userId"></param>
/// <param name="password"></param>
/// <returns></returns>
public static bool ShareDirectoryExists(string share_name, string userId = "", string password = "")
{
//フォルダが存在するかチェックする
if (System.IO.Directory.Exists(share_name) == false)
{
// 接続情報を設定
NETRESOURCE netResource = new NETRESOURCE();
netResource.dwScope = 0;
netResource.dwType = 1;
netResource.dwDisplayType = 0;
netResource.dwUsage = 0;
netResource.lpLocalName = ""; // ネットワークドライブにする場合は"z:"などドライブレター設定
netResource.lpRemoteName = share_name;
netResource.lpProvider = "";
int ret = 0;
try
{
//既に接続してる場合があるので一旦切断する
ret = WNetCancelConnection2(share_name, 0, true);
//共有フォルダに認証情報を使って接続
ret = WNetAddConnection2(ref netResource, password, userId, 0);
}
catch (Exception)
{
//エラー処理
return false;
}
if (System.IO.Directory.Exists(share_name) == true)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
/// <summary>
/// 共有フォルダ内にファイルがあるかチェック
/// </summary>
/// <param name="file"></param>
/// <param name="userId"></param>
/// <param name="password"></param>
/// <returns></returns>
public static bool ShareFileExists(string file, string userId = "", string password = "")
{
//アップロード先のフォルダが存在するかチェックする
if (ShareDirectoryExists(System.IO.Path.GetDirectoryName(file), userId, password) == false)
{
return false;
}
else
{
if (System.IO.File.Exists(file) == true)
{
return true;
}
else
{
return false;
}
}
}
/// <summary>
/// ファイルのコピー
/// </summary>
/// <param name="src"></param>
/// <param name="dest"></param>
/// <param name="userId"></param>
/// <param name="password"></param>
public static void SetShareDirectoryToFile(string src, string dest, string userId = "", string password = "")
{
try
{
//とりあえずコピーできるかやってみる
System.IO.File.Copy(src, dest, true);
}
//認証に失敗すると UnauthorizedAccessException が発生する(Exceptionでキャッチしてもいいかも)
catch (UnauthorizedAccessException)
{
//ファイル存在チェックの時点で共有フォルダ認証済みになる
if (ShareFileExists(src, userId, password) == false) return;
if (ShareFileExists(dest, userId, password) == false) return;
//ファイルコピー
System.IO.File.Copy(src, dest, true);
}
}
}
}
まとめ
この記事が皆様のお役にたてたら幸いです。
コメント