3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

(.Net)Windows共有フォルダのセッションの切断する

.Net アプリケーションからWindows共有フォルダのセッションを切断する方法です。

GUIだと、コンピュータの管理 から 共有フォルダ→セッション→セッション右クリック→セッションを閉じる ということを .Net アプリケーションからしたいわけです。

コマンドプロンプトから、net session \\コンピュータ名 /delete でセッションを切断することができるので、当初 .Net アプリからこのコマンドをキックしようと思ったのですが、これが自身のPCにしかできません。また、コンピュータ名での指定しかできません。

今回の要件は .Net 側からリモートのファイルサーバの共有フォルダセッションを解除したいということです。(つまり、.NETアプリが動くPCとファイルサーバが別コンピュータ)。そして、ユーザのほとんどはターミナルサーバからログインしており、特定のユーザだけ削除したいのです。

そこで、結局 Windows APINetSessionDel 関数を使うことにしました。このAPIだとリモートのコンピュータに対して、ユーザのPC名、ユーザ名を指定してセッション切断ができます。

下記のような感じでセッション切断できます。(C#)

///

/// セッションを閉じる

///

/// サーバ名(\\servernameの形式) null なら自身を表す。

/// クライアントホスト名(\\servernameの形式)NULL を指定すると、username パラメータで指定されたユーザーのすべてのセッションは、servername パラメータで指定されたサーバーから削除

/// ユーザ名。NULL を指定すると、UncClientName パラメータで指定されたクライアント名に関係する、すべてのユーザーのセッションが終了

/// Win32エラーコード

public static NET_API_STATUS CloseSession(string strServerName, string strClientHostName, string strUserName) {

StringBuilder strBulSvname = null ;

if (! String.IsNullOrEmpty(strServerName) )

strBulSvname = new StringBuilder(strServerName);

 

StringBuilder strBulClientHostName = null;

if ( ! String.IsNullOrEmpty(strClientHostName))

strBulClientHostName= new StringBuilder(strClientHostName);

 

StringBuilder strBulUserName = null;

if ( ! String.IsNullOrEmpty(strUserName))

strBulUserName = new StringBuilder(strUserName);

 

NET_API_STATUS res = NetSessionDel(strBulSvname, strBulClientHostName, strBulUserName);

 

Console.WriteLine(res.ToString());

return res;

 

}

 

//WindowsAPI使用定義

[DllImport("netapi32.dll" ,CharSet= CharSet.Unicode)]

private static extern NET_API_STATUS NetSessionDel(

StringBuilder servername,

StringBuilder UncClientName,

StringBuilder username);

///

/// Lmcons.h

/// #define NET_API_STATUS DWORD

///

public enum NET_API_STATUS : uint {

NERR_Success = 0,

///

This computer name is invalid.

NERR_InvalidComputer = 2351,

///

This operation is only allowed on the primary domain controller of the domain.

NERR_NotPrimary = 2226,

///

This operation is not allowed on this special group.

NERR_SpeGroupOp = 2234,

///

This operation is not allowed on the last administrative account.

NERR_LastAdmin = 2452,

///

The password parameter is invalid.

NERR_BadPassword = 2203,

///

The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.

NERR_PasswordTooShort = 2245,

///

The user name could not be found.

NERR_UserNotFound = 2221,

 

ERROR_ACCESS_DENIED = 5,

ERROR_NOT_ENOUGH_MEMORY = 8,

ERROR_INVALID_PARAMETER = 87,

ERROR_INVALID_NAME = 123,

ERROR_INVALID_LEVEL = 124,

ERROR_MORE_DATA = 234,

ERROR_SESSION_CREDENTIAL_CONFLICT = 1219

}

NET_API_STATUS res にはNetSessionDelの戻りのWindowsエラーコードが返ります。

エラーコードのメッセージを取得するには、(.Net)WindowsAPIのエラーコードからメッセージを取得するを参照してください。

注意点として、切断対象とするクライアントホスト名ですが、コンピュータの管理のセッションで出てくるコンピュータ名じゃないとダメなようです。(ここがコンピュータ名とIPアドレスとの時があるので。。。)

ですので、(.Net)共有フォルダにアクセスしているセッションを取得するでセッション情報を取ってきて、それのComputerNameの値を使うのがいいかもしれません。

また、NetSessionDelの引数を全てNULLにするとエラーになりました。クライアントコンピュータ名かユーザ名かはどちらかは指定しないといけないのかもしれません。

MSDNによると「Administrators または Account Operators ローカルグループのメンバだけがこの関数を実行できる」とのことです。

一般ユーザで使う場合は(.Net)別ユーザでプロセスを起動するで書いたようにAdministrator権限でmsgをキックするようにするといいと思います。

参考:

net sessionコマンドでパソコンに接続しているセッションを切断する :ITpro net sessionコマンドで切断する場合です。