2008年7月28日月曜日

.NET Vista対応 その4 任意のフォルダでファイルを共有する

UACはProgram FilesフォルダやWindowsフォルダへの書き込みを制限しています。
制限フォルダへの書き込みには管理者権限での許可が必要です。
Vista対応 その1

制限フォルダ以外の他のフォルダではUACはどのように機能するのでしょうか?
まずファイルの作成者は作成したファイルへの書き込み、読み込み、削除が可能です。
ファイルの作成者以外は読込みは可能ですが、書き込み・削除はUACによりリダイレクトされます。

具体例
1、ユーザAがC:/ProgramDataにファイルを作成します。

2、ユーザBがユーザAの作成したファイルを読み込みます。
読み込みは制限されていないのでC:/ProgramDataのファイルが読込まれます。

3、ユーザBがユーザAの作成したファイルに対して書き込みを行います。
UACによりC:/Users/ユーザB/AppData/Local/VirtualStore/ProgramDataにリダイレクトされます。

4、ユーザBが再度ユーザAの作成したファイルを読み込みます。
UACはリダイレクト先(C:/Users/ユーザB/AppData/Local/VirtualStore/ProgramData)に該当ファイルを探しに行き、3で作成されたファイルを読み込みます。

5、ユーザAがC:/ProgramDataのファイルを読み込みます。
もちろんユーザBが追記した内容は表示されません。


Vistaでは、基本的に他のユーザが作成したフォルダおよびファイルは閲覧のみで編集することができません。
他のユーザが作成したフォルダおよびファイルをすべてのユーザで共有するには、フォルダまたはファイルのアクセス権限を変更します。
すべてのユーザおよびネットワーク上のすべてのユーザで共有するには「Everyone」のアクセス権限を変更します。
ネットワーク上のユーザーと共有しない場合は「Users」のアクセス権限を変更します。



フォルダまたはファイルのアクセス権限を手動で変更するには



■方法その1
1、共有したいフォルダまたはファイルを右クリックし「共有」をクリックします。
2、グループ名またはユーザー名を入力します。
3、アクセス許可レベルを「閲覧者」、「投稿者」、「共同所有者」のいずれかを設定します。

閲覧者:共有ファイルの表示が可能。追加、変更、削除はできない
投稿者:共有ファイルの表示、追加が可能。自分が投稿したファイルのみ変更または削除できる
共同所有者:共有ファイルの表示、追加、変更、削除が可能


■方法その2
1、共有したいフォルダまたはファイルを右クリックし「プロパティ」をクリックします。
2、共有タブを選択し、「詳細な共有」ボタンをクリックします。
3、「このフォルダを共有する」チェックボックスをチェックONにし、「アクセス許可」ボタンをクリックします。
4、「追加」ボタンをクリックし、グループ名またはユーザ名を追加します。
3、アクセス許可レベルを「読取」、「変更」、「フルコントロールを適宜チェックONに設定します。



フォルダまたはファイルのアクセス権限をプログラムから変更するには



■ファイルのアクセス権限を変更する
Imports System.IO
Imports System.Security.AccessControl

Public Class Form1
'「C:/ProgramData/Test.txt」ファイルのアクセス権限を変更します。
'「Users」グループに「フルコントロール」を設定します。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
Try
Dim fileName As String _
= System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Test.txt")

AddFileSecurity(fileName, "Users", FileSystemRights.FullControl, AccessControlType.Allow)

Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

Private Sub AddFileSecurity(ByVal fileName As String, _
ByVal account As String, _
                            ByVal rights As FileSystemRights, _
ByVal controlType As AccessControlType)

Dim fSecurity As FileSecurity = File.GetAccessControl(fileName)

Dim accessRule As New FileSystemAccessRule(account, rights, controlType)

fSecurity.AddAccessRule(accessRule)

File.SetAccessControl(fileName, fSecurity)

End Sub

End Class


■フォルダのアクセス権限を変更する

Imports System.IO
Imports System.Security.AccessControl

Public Class Form1
'「C:/ProgramData/Test」フォルダのアクセス権限を変更します。
'「Users」グループに「フルコントロール」を設定します。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
Try
Dim dirName As String _
= System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "User")

AddDirectorySecurity(dirName, "Users", FileSystemRights.FullControl, AccessControlType.Allow)

Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

Private Sub AddDirectorySecurity(ByVal DirName As String, _
ByVal Account As String, _
ByVal Rights As FileSystemRights, _
ByVal ControlType As AccessControlType)

Dim dirInfo As New DirectoryInfo(DirName)

Dim dirSecurity As DirectorySecurity = dirInfo.GetAccessControl()

'このフォルダ、サブフォルダおよびファイルにアクセス権限を適用
Dim rule As New FileSystemAccessRule(Account, _
Rights, _
InheritanceFlags.ContainerInherit Or InheritanceFlags.ObjectInherit, _
PropagationFlags.None, _
AccessControlType.Allow)

dirSecurity.AddAccessRule(rule)

dirInfo.SetAccessControl(dirSecurity)

End Sub

End Class

※FileSystemAccessRuleコンストラクタのInheritanceFlags、PropagationFlags引数は、設定するアクセス権限の適用範囲に応じて適宜変更します。
適用先InheritanceFlagsPropagationFlags
このフォルダのみNoneNone
このフォルダとファイルObjectInheritNone
このフォルダとサブフォルダContainerInheritNone
このフォルダ、サブフォルダ、およびファイルContainerInherit | ObjectInheritNone
ファイルのみObjectInheritInheritOnly
サブフォルダのみContainerInheritInheritOnly
サブフォルダとファイルのみContainerInherit | ObjectInheritInheritOnly

適用先の確認は、アクセス権限を設定したフォルダを右クリックし、プロパティをクリックします。
セキュリティタブを選択し、「詳細設定」ボタンをクリックし、表示されたウィンドウで確認できます。



インストーラでフォルダを作成しアクセス権限を変更するには


インストーラでCommonApplicationDataにアプリケーション用データフォルダを作成し、アクセス権限を適宜設定します。アンインストール時に作成したフォルダは削除されます。
CommonApplicationDataはVistaでは「C:/ProgramData」、XPでは「C:\Documents and Settings\All Users\Application Data」となります。


CommonApplicationDataに「Test」フォルダを作成し、そのサブフォルダとファイルのアクセス権限を「Usersグループ、フルコントロール」に設定します。

1、セットアッププロジェクトのファイルシステムエディタで「対象コンピュータ上のファイルシステム」を右クリックし「特殊フォルダの追加」で「カスタムフォルダ」を追加します。
2、「カスタムフォルダ」を選択し、DefaultLocationプロパティを「[CommonAppDataFolder]」とします。
3、そこにさらにサブフォルダを追加し、Nameプロパティを「Test」、AlwaysCreateプロパティを「True」に設定します。
4、以下のクラスを定義したクラスライブラリをソリューションに追加します。
5、セットアッププロジェクトのファイルシステムエディタで、アプリケーションフォルダに4で作成したクラスライブラリのプライマリ出力を追加します。
6、カスタム動作の確定ノードに5で作成したクラスライブラリのプライマリ出力を追加します。
5、セットアッププロジェクトをビルドし、作成したmsiをOrcaで編集します。
6、CustomActionテーブルのActionフィールドが「xxxx.commit」のデータのTypeフィールド値に2048を加算します。
  インストーラは管理者権限で実行されるが、カスタム動作に管理者権限が与えられないため、Orcaで管理者権限を与えます。

Imports System.IO
Imports System.Security.AccessControl

Public Class Installer1
Inherits System.Configuration.Install.Installer

Public Overrides Sub Commit(ByVal savedState As System.Collections.IDictionary)

Dim dirName As String _
= System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Test")     

Dim dirInfo As New DirectoryInfo(DirName)

Dim dirSecurity As DirectorySecurity = dirInfo.GetAccessControl()

'サブフォルダとファイルのみにアクセス権限を適用
Dim rule As New FileSystemAccessRule("Users", _
FileSystemRights.FullControl, _
InheritanceFlags.ContainerInherit Or InheritanceFlags.ObjectInherit, _
PropagationFlags.InheritOnly, _
AccessControlType.Allow)

dirSecurity.AddAccessRule(rule)

dirInfo.SetAccessControl(dirSecurity)

MyBase.Commit(savedState)
End Sub
End Class

0 件のコメント: