C#-Webサービスからのネットワークドライブの割り当て
-
07-07-2019 - |
質問
私たちは、マップされたネットワークドライブと対話するサードパーティプロセスを実行する必要があるWebサービスに取り組んでいます。そのため、このドライブをWebサービスからプログラムでマッピングする必要があります。
私はすでにWNetAddConnection2などを別のプロジェクト用のより良いクラスにラップしているので、すぐにコードを投げました。
Webサービスは、システムアカウントで実行される(IISではなく)UltiDev Cassiniで実行されています。次のエラーコードが表示されます:「指定されたデバイス名が無効です」毎回。また、web.configファイルで他のユーザーになりすましてみましたが、同じ結果になりました。
通常のユーザーアカウントでコンソールプログラムからコードを実行すると、ドライブは問題なくマップされます。
同等の" net use"の実行も試みました。 WNetAddConnectionとまったく同じ結果を持つC#からのコマンド。
Windowsサービスまたはシステムユーザーがネットワークドライブをマップできない理由を誰か知っていますか?
回避策を知っている人はいますか?システムの起動時にドライブをマッピングするだけで解決できますが、システム/偽装ユーザーはどのようにアクセスできますか?
UltiDev Cassiniのリンク: UltiDev
解決策: UltiDev CassiniサービスをAdministratorでログオンするように設定しましたが、すべてが機能しています。 ASP .Netの偽装は計画どおりに動作してはなりません。
解決
LOCAL_SYSTEMアカウントは、匿名のネットワーク上の資格情報。匿名(全員)が共有にアクセスできる場合、UNCネットワーク共有を使用してこの情報にアクセスできます。
CassiniをWindowsサービスとしてインストールすることもできます。別のユーザーで実行します。
他のヒント
ローカルシステムアカウントを使用している場合、それは本質的にネットワーク[foo]にアクセスできないと考えています。なりすましがあなたの唯一の実行可能な道だと思います。技術的には、共有に対するアクセス制御を、誰でも共有の読み取り/書き込みができる程度まで減らすことができますが、それは解決策よりも多くの問題をもたらします。
同じ問題がありました。この問題は、コードが実行されているアカウントが原因で発生します。次のクラスを使用して、これを回避できます。ファイルのアクセス/コピーに使用しているのと同じコードでドライブをマップする必要があります。使用するパターンは、ドライブが最初に接続されているかどうかを常に確認することです。その場合は、切断してから再接続します。そうでない場合は、接続するだけです。説明している問題は解決したようです。
public static class NetworkDrives
{
public static bool MapDrive(string DriveLetter, string Path, string Username, string Password)
{
bool ReturnValue = false;
if(System.IO.Directory.Exists(DriveLetter + ":\\"))
{
DisconnectDrive(DriveLetter);
}
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "net.exe";
p.StartInfo.Arguments = " use " + DriveLetter + ": " + '"' + Path + '"' + " " + Password + " /user:" + Username;
p.Start();
p.WaitForExit();
string ErrorMessage = p.StandardError.ReadToEnd();
string OuputMessage = p.StandardOutput.ReadToEnd();
if (ErrorMessage.Length > 0)
{
throw new Exception("Error:" + ErrorMessage);
}
else
{
ReturnValue = true;
}
return ReturnValue;
}
public static bool DisconnectDrive(string DriveLetter)
{
bool ReturnValue = false;
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "net.exe";
p.StartInfo.Arguments = " use " + DriveLetter + ": /DELETE";
p.Start();
p.WaitForExit();
string ErrorMessage = p.StandardError.ReadToEnd();
string OuputMessage = p.StandardOutput.ReadToEnd();
if (ErrorMessage.Length > 0)
{
throw new Exception("Error:" + ErrorMessage);
}
else
{
ReturnValue = true;
}
return ReturnValue;
}
}
マップされたドライブの代わりに、UNC共有を使用して接続できますか?
共有にアクセスできるユーザーになりすまします。
実際にこれを行ったことがありますが、1997年やDelphi 2でNT 3.51に勝つような非常に昔のことです
メモリから実行していますが、次のようになります。 Win APIを使用します:
WNetAddConnection2()
通話に関する情報: http:// msdn .microsoft.com / en-us / library / aa385413(VS.85).aspx
pInvoke.netからc#署名を取得できます: http:// www.pinvoke.net/default.aspx/mpr/WNetAddConnection2.html
設定に関する注意: サービスのドメインアカウントを設定し、ローカルシステムではなくそのアカウントのIDでサービスを実行する必要があると思います。ユーザー名とパスワードとしてnullを渡すと思います。
ローカルシステムがドメインアカウントのユーザー名とパスワードを渡すと、 サービスを実行できます-システムアカウントがネットワークアクセスを許可されているかどうかはまったくわかりません。
留意すべき一般的な概念は、「マップされたドライブ文字」はユーザーの概念であり、システムの概念ではないということです。そのため、JoeがWindowsコンピューターにログインすると、マップされたドライブがJoeユーザーアカウントに接続されます。 Windowsサービスが実行されている場合、通常はLOCAL_SYSTEM 'ユーザーアカウント'で実行されています。つまり、LOCAL_SYSTEMはJoeのマップされたドライブ文字を認識していません。
したがって、ネットワーク共有へのUNCアクセスは、Windowsサービス内から任意のリモートリソースにアクセスしようとするときの方法です。 「Joe」ユーザーアカウントのコンテキストでWindowsサービスを実行するか、「MyServiceAccount」などのダミーADアカウントを作成してそのアカウント権限をUNCに付与するか、偽装を使用してWindowsサービスは、偽装ハンドルでNetLogon()関数を使用してローカルワークステーションにログインし、そこからUNCにアクセスします。
それを行う方法はたくさんありますが、すべてユーザーアカウントに帰着するのは、マップされたドライブとUNCアクセスに関連付けられています。
幸運、この情報がお役に立てば幸いです!