以下のような方法でファイルにデータを書き込むプログラムを手に入れました。
public void ExportToFile(string filename)
{
using(FileStream fstream = new FileStream(filename,FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine(text);
}
}
プログラムを実行すると私はエラーが出ます:
未処理の例外:System.UnauthorizedAccessException:パス 'mypath'へのアクセスが拒否されました。 System.IO .__ Error.WinIOError(Int32エラーコード、文字列maybeFullPath) System.IO.FileStream.Init(Stringパス、FileModeモード、FileAccessアクセス、 nt32権限、Boolean useRights、FileShare共有、Int32 bufferSize、FileOptions オプション、SECURITY_ATTRIBUTES secAttrs、String msgPath、Boolean bFromProxy) System.IO.FileStream..ctor(Stringパス、FileModeモード、FileAccessアクセス) FileShare共有、Int32 bufferSize、FileOptionsオプション、文字列msgPath、Boolea bFromProxy)
質問:これを把握するために必要なコードは何ですか?また、どのようにアクセスを許可するのですか?
更新:
に基づいてコードを修正しましたこの答え時代遅れのメソッドを取り除くために。
これを確認するには、Security名前空間を使用できます。
public void ExportToFile(string filename)
{
var permissionSet = new PermissionSet(PermissionState.None);
var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
permissionSet.AddPermission(writePermission);
if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine("sometext");
}
}
else
{
//perform some recovery action here
}
}
それらの許可を得る限りでは、あなたはどういうわけかあなたにそれをするようにユーザに依頼しなければならないでしょう。あなたがプログラム的にこれを行うことができれば、それから私達全員は困っているでしょう;)
あなたのコードが次のことをしたとき:
あなたはパーミッションが変更されるリスクを冒します。1そして2実行時にシステムで他に何が起きるのか予測できないためです。したがって、コードは次のような状況に対処する必要があります。UnauthorisedAccessException以前に権限を確認した場合でも、がスローされます。
そのことに注意してください保安管理者classはCASのアクセス許可を確認するために使用され、現在のユーザーが指定された場所に(ACLおよびACEを介して)書き込みアクセス権を持っているかどうかを実際には確認しません。など、IsGrantedローカルで実行しているアプリケーションに対しては常にtrueを返します。
例(に由来するジョシュの例):
//1. Provide early notification that the user does not have permission to write.
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
if(!SecurityManager.IsGranted(writePermission))
{
//No permission.
//Either throw an exception so this can be handled by a calling function
//or inform the user that they do not have permission to write to the folder and return.
}
//2. Attempt the action but handle permission changes.
try
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
writer.WriteLine("sometext");
}
}
catch (UnauthorizedAccessException ex)
{
//No permission.
//Either throw an exception so this can be handled by a calling function
//or inform the user that they do not have permission to write to the folder and return.
}
トリッキーですお勧めしません生のACLに基づいてフォルダから有効なアクセス許可をプログラム的に計算しようとします。System.Security.AccessControlクラス)。 Stack Overflowやその他のWebに関する他の回答では、許可が許可されているかどうかを知るためにアクションを実行することをお勧めします。このpostはパーミッションの計算を実行するために必要なものをまとめたもので、これをやめさせるには十分なはずです。
MaxOvrdrvのその修正版コード。
public static bool IsReadable(this DirectoryInfo di)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = di.GetAccessControl().GetAccessRules(true, true, typeof(SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (UnauthorizedAccessException uae)
{
Debug.WriteLine(uae.ToString());
return false;
}
bool isAllow = false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) &&
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) &&
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return isAllow;
}
public static bool IsWriteable(this DirectoryInfo me)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (UnauthorizedAccessException uae)
{
Debug.WriteLine(uae.ToString());
return false;
}
bool isAllow = false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) &&
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) &&
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) &&
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) &&
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return isAllow;
}
すみません、しかし前の解決策のどれも私を助けませんでした。私は両方の側をチェックする必要があります:SecurityManagerとSOパーミッション。私はJoshコードと私の答えで多くのことを学びましたが、私はRakeshコードを使う必要があると思います(彼のおかげで)。たった一つのバグ:私は彼がAllowだけをチェックし、Denyパーミッションをチェックしないことを発見しました。だから私の提案は:
string folder;
AuthorizationRuleCollection rules;
try {
rules = Directory.GetAccessControl(folder)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
} catch(Exception ex) { //Posible UnauthorizedAccessException
throw new Exception("No permission", ex);
}
var rulesCast = rules.Cast<FileSystemAccessRule>();
if(rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Deny)
|| !rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Allow))
throw new Exception("No permission");
//Here I have permission, ole!
これはクローズされていないので、私は何かが彼らのためにきちんと動いていることを望んでいる人のために新しいエントリーを提出したいと思います...そしてコード自体をデバッグして見つけるためにDirectoryServicesを使って使用する適切なコードは、ここで私はあらゆる状況で私のために働くことがわかったものです...私のソリューションはDirectoryInfoオブジェクトを拡張することに注意してください...:
public static bool IsReadable(this DirectoryInfo me)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (Exception ex)
{ //Posible UnauthorizedAccessException
return false;
}
bool isAllow=false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadPermissions)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Read) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAndExecute) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.ReadPermissions)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return isAllow;
}
public static bool IsWriteable(this DirectoryInfo me)
{
AuthorizationRuleCollection rules;
WindowsIdentity identity;
try
{
rules = me.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
identity = WindowsIdentity.GetCurrent();
}
catch (Exception ex)
{ //Posible UnauthorizedAccessException
return false;
}
bool isAllow = false;
string userSID = identity.User.Value;
foreach (FileSystemAccessRule rule in rules)
{
if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference))
{
if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Deny)
return false;
else if ((rule.FileSystemRights.HasFlag(FileSystemRights.Write) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) ||
rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) ||
rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles)) && rule.AccessControlType == AccessControlType.Allow)
isAllow = true;
}
}
return me.IsReadable() && isAllow;
}
これらのどれも私のために働きませんでした..彼らはそうでなくても、彼らは本当のように戻ります。問題は、現在のプロセスのユーザー権限に対して利用可能な権限をテストする必要があるということです。これはファイル作成権限をテストするためのもので、書き込みアクセスをテストするにはFileSystemRights句を 'Write'に変更するだけです。
/// <summary>
/// Test a directory for create file access permissions
/// </summary>
/// <param name="DirectoryPath">Full directory path</param>
/// <returns>State [bool]</returns>
public static bool DirectoryCanCreate(string DirectoryPath)
{
if (string.IsNullOrEmpty(DirectoryPath)) return false;
try
{
AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
WindowsIdentity identity = WindowsIdentity.GetCurrent();
foreach (FileSystemAccessRule rule in rules)
{
if (identity.Groups.Contains(rule.IdentityReference))
{
if ((FileSystemRights.CreateFiles & rule.FileSystemRights) == FileSystemRights.CreateFiles)
{
if (rule.AccessControlType == AccessControlType.Allow)
return true;
}
}
}
}
catch {}
return false;
}
次のコードブロックを試して、ディレクトリに書き込みアクセス権があるかどうかを確認できます。
FileSystemAccessRuleを確認します。
string directoryPath = "C:\\XYZ"; //folderBrowserDialog.SelectedPath;
bool isWriteAccess = false;
try
{
AuthorizationRuleCollection collection = Directory.GetAccessControl(directoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule rule in collection)
{
if (rule.AccessControlType == AccessControlType.Allow)
{
isWriteAccess = true;
break;
}
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
//handle notifications
}
うわー...このスレッドには低レベルのセキュリティコードがたくさんあります - そのほとんどは私にはうまくいきませんでした - 私はその過程で多くを学びましたが。私が学んだことの1つは、このコードの大部分は、ユーザーごとのアクセス権を求めるアプリケーションを対象としていないということです。これは、管理者がプログラムで権利を変更したいためです。ではないよいこと。開発者として、私はAdministratorとして実行することによって「簡単な方法」を使用することはできません - 私はコードを実行するマシン上の1人でも、ユーザーでもありません。 - それらは私の状況のためのものではなく、そしておそらく大部分のランクおよびファイル開発者のためのものでもないでしょう。
この種の質問のほとんどのポスターのように - 私も最初はそれが「ハッキー」だと感じました - それ以来私はそれを試してみることは完全に大丈夫だと思いました。私が得た情報では、その権利が実際に何であるのかがわかりませんでした。以下のコード - やった。
Private Function CheckUserAccessLevel(folder As String) As Boolean
Try
Dim newDir As String = String.Format("{0}{1}{2}",
folder,
If(folder.EndsWith("\"),
"",
"\"),
"LookWhatICanDo")
Dim lookWhatICanDo = Directory.CreateDirectory(newDir)
Directory.Delete(newDir)
Return True
Catch ex As Exception
Return False
End Try
終了機能
SecurityManager.IsGranted
方法。それは使用することを支持して4.0で廃止されましたPermissionSets
。上のコードはそれほど変わってはいけませんが、PermissionSet
一度に確認できるのは1つの権限だけです。 - Josh