トップ回答者
All Users\Documentsにファイルをインストールする方法

質問
回答
-
あいこ さんからの引用 初めに教えていただいた方法ですが、私まだまだ初心者のため具体的にどのようなコードをかけばそれが実現できるのかがまだ理解できておりません・・・
教えていただいたMSDNライブラリを参考にしてもう少し調べてみます!
私が言おうとしていたやり方は…
対象マシンに.NETが入っている前提とします。(入っていなければ事前に入れるか、「必須コンポーネント」としてセットアップに含められます。)
以下はすでに試されてるかとは思いますが…
セットアッププロジェクトのファイルシステムエディタで「対象コンピュータ上のファイルシステム」を右クリックしてコンテクストメニューで「特殊フォルダの追加」で「カスタムフォルダ」を追加しそれを選択して
プロパティウィンドウのDefaultLocationで[CommonAppDataFolder]と入力してください。
そこにさらにサブフォルダを追加します。名前をAAAAAとします。これがアプリケーションデータファイルを入れるフォルダです。
必要ならばファイルや更なるサブディレクトリを追加してください。
同じソリューションにクラスライブラリプロジェクトを作成します。Class1.csは消してください。
そのプロジェクトを右クリックしてコンテクストメニューで「追加」「コンポーネント」を選択します。
「新しい項目の追加」ダイアログで「インストーラクラス」を選択して「追加」して下さい。たとえば名前をMyInstallerとします。
コードビューでそれを表示します。
public partial class MyInstaller : Installerの{}なかで
public overrideと入力しスペースを押すとIntelliSenseによっていくつかメソッドが表示されます。
このうち、InstallとCommitを選択してください。
Code Snippetpublic override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
}
public override void Commit(System.Collections.IDictionary savedState)
{
base.Commit(savedState);
}
ファイルの冒頭に以下を追加しておいてください。
Code Snippetusing System.IO;
using System.Security.Principal;
using System.Security.AccessControl;
Commitを以下のように実装してください
Code Snippetconst string FOLDER_NAME = "AAAAA";
public override void Commit(System.Collections.IDictionary savedState)
{
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
if (wp.IsInRole(WindowsBuiltInRole.Administrator))
{
string dataFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), FOLDER_NAME);
DirectoryInfo di = new DirectoryInfo(dataFolderPath);
SecurityIdentifier users_sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
DirectorySecurity dsec = di.GetAccessControl();
dsec.AddAccessRule(
new FileSystemAccessRule(users_sid,
FileSystemRights.Modify,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly,
AccessControlType.Allow));
di.SetAccessControl(dsec);
}
base.Commit(savedState);
}
セットアッププロジェクトに戻り、「ファイルシステムエディタ」で先ほど作成したクラスライブラリプロジェクトの「プライマリ出力」を「アプリケーションフォルダ」追加しておきます。
「カスタム動作エディタ」にて、「インストール」と「確定」のノードを右クリックして「カスタム動作の追加」で「アプリケーションフォルダ」から先ほどのクラスライブラリプロジェクトを選択してください。「インストール」と「確定」のそれぞれのノードの下にそれが現れます。
これをビルドしてインストールすれば、AAAAA配下のファイルが、Usresのユーザでも「変更」できるようになると思います。
あとは上記コードにあるキーワードをMSDNライブラリ等で参照して適切にカスタマイズしてみてください。
TO:皆様、ツッコミお待ちしています…
すべての返信
-
外池です。C#ですか。よかった。私がお答えする方法は、C#でも、VBでも共通です。
で、まず、前提条件ですが、
1) ご希望のフォルダーは使いません。
2) アプリケーションそのものが直接管理する方式ですので、インストーラーで設定の保存の方式を確認することはできるかもしれませんが、変更は難しいと思います。
3) Visual Studio 2005以降のC#です。
4) 制限ユーザーも使えるかどうかは、未確認です。
で、C#のアプリのプロジェクトで、ソリューションエクスプローラを見ると、Propertiesのフォルダーのようなものがありますよね?
これをダブルクリックすれば、アプリケーション、ビルド、ビルドイベントなどのタブがある画面が現れるのはご存知だと思いますが、その中の設定のタブを使えば、アプリケーション全体の設定も、ユーザーごとの設定も、できます。プリミティブが型も保管できますし、オブジェクト(おそらく、シリアライズ可能なクラスのオブジェクトなのだと思う)であれば、状態を丸ごと保管することも可能です。
前提条件が受け入れられるものであれば・・・、お役に立てると思います。
-
外池です。
初期値(ビルドしたときに最初に用意される値)は、特に、プリミティブ型の設定値であれば、ご覧頂いている設定画面でそのまま書き込めばOKです。
で、アプリの中で読み出すときには、My.Settings.xxxxと、xxxxのところに設定画面で用いた「名前」をつけて、あと、適当に代入文にすれば、設定の読み出しも、設定の書き込みもできます。あとは、My.Settings.Saveとすれば保存できます。
詳しくは、
http://msdn2.microsoft.com/ja-jp/library/c9db58th.aspx
ただ・・・、ドキュメントは、すべて、Visual Basicのドキュメント扱いになってますね。C#でも問題ないハズですが。
-
外池です。すいません、問題アリでした。
訂正します。
C#の場合は、Myは使えなくて、Properties.Settingsをつかって、しかも、インスタンスを用意するか、あるいは、Defaultを使うか。
http://www.microsoft.com/japan/msdn/vs05/vcsharp/SettingsCS_RL.aspx
-
権限付与を行うインストーラクラスdllかexeを作成して、カスタム動作で呼び出すとかどうでしょうか。
DirectoryInfoなどからDirectorySecurityオブジェクトを得てFileSystemAccessRuleオブジェクトを追加してDirectoryInfoに戻せばよいと思います。
詳しくはMSDNライブラリをご参照ください。
DirectorySecurity クラス
http://msdn2.microsoft.com/ja-jp/library/system.security.accesscontrol.directorysecurity.aspxFileSecurity クラス
http://msdn2.microsoft.com/ja-jp/library/system.security.accesscontrol.filesecurity.aspx
-
インストーラですよね?
だと、残念ですが、設定方法はありません(自分でプログラム的に設定する以外の選択肢はない)。
OS 的には、CSIDL_COMMON_DOCUMENTS(SHGetSpecialFolderPath API などで取得) が該当する場所ですので、Custom Actions(VSのカスタム動作ではない)を用いてセットアップすることは可能ですが、この場合、C/C++ でDLLを作る必要があり、その追加をVSセットアップ上から行うことができません(できないのは、VSセットアップの問題であって、WindowsInstallerの問題ではありません)。
ORCAで変更するなど、ビルド後に面倒な処理を施せばできますが、あまりお勧めできません(ビルドコマンドにスクリプトで埋め込みするという方法もありますが...)。
さて、インストーラ側はともかくとして、アプリケーション側ですが、該当フォルダを取り出すメソッドは .NET Framework には用意されていませんが、問題ありませんか?
.NET Framework が用意している既定のフォルダで用意しているのは、System.Environment.SpecialFolder 列挙体 です。
3.5 でも変わり映えしませんが、どちらにしても、該当フォルダはなく、すべてのユーザーで共有できるフォルダは、CommonApplicationData となります。
もし、こちらのフォルダでも問題ないのであれば、WindowsInstaller としても同じフォルダを指定できます。
ですが、VSセットアップはなぜか対応していません。
そのため、VSセットアップで上記フォルダを指定したい場合は
-
セットアッププロジェクトでファイルシステムビューを開く
-
ツリーの対象コンピュータ上のファイルシステムで右メニューから特別なフォルダ->カスタム フォルダを作成
-
名前を適当なものにする(表示されるわけではないので、恥ずかしくない程度であれば何でもよい)
-
DefaultLoation に[CommonAppDataFolder]をセット
-
Property も同じ値(全部大文字になります)をセット(別の名称でもかまいません)
という形で、間接的に設定します。
実際にインストールしてみたわけではないので、本当にうまくいくかどうかは確認が必要ですが、ビルドしたmsiを見る限りではこれでセットアップできると思います。
-
-
外池です。申し訳ありません。わたしも、とっちゃん様と同じ意見になりました。
私なら・・・、インストーラーで設定してやるよりも、アプリで、初回起動時に、独自のフォルダーを探しにいって、なければ、設定保存用のフォルダーを作って、かつ、設定用のファイルを書き出してやります。
では、「独自のフォルダーをどこに置くか?」となれば、
アプリ自身が存在する場所(Program Filesの下のどこか)か、あるいは、
Documents and Settings\All Users\Application Dataのどこかか、
という感じになるでしょう。どちらも、管理者でなくても、Userは、ファイルの作成・書き込みと、フォルダーの作成・データの追加が許可されています。
・・・・、うーん、ファイルの上書き保存は、OKなのでしょうか。(今、断言できません・・・。どなたか、ヘルプ)
-
外池 さんからの引用 Documents and Settings\All Users\Application Dataのどこかか、
という感じになるでしょう。どちらも、管理者でなくても、Userは、ファイルの作成・書き込みと、フォルダーの作成・データの追加が許可されています。
・・・・、うーん、ファイルの上書き保存は、OKなのでしょうか。(今、断言できません・・・。どなたか、ヘルプ)
>All Users\Application Data
既定では既存ファイルの変更ができないんですよ…
過去スレッド「アプリケーション設定情報の保存場所」
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2548032&SiteID=7
-
-
"All Users\Application Data"や"All Users\Documents"は、「ファイルを作った人が、そのファイルを他の人に見せるためのフォルダ」というような位置付けなので、この中に、上位からのアクセス権を継承したフォルダやファイルを作ると、おおざっぱに言って、「ファイルの所有者(≒作成者)とAdministratorsがフルコントロール、それ以外の人が読み取り専用」というアクセス権が設定されます(所有者であれば、制限ユーザーであっても書き込み可です)。で、参考になるであろう"All Users\Application Data\Microsoft"のアクセス権を見てみると、上位フォルダからは継承せず、直接設定してあります(All Users\Application Data\Microsoft\Dr Watsonなんかだと、Everyoneフルコントロールだったりします)。
ということで、設定ファイルを置くために、"All Users\Application Data"の中にアプリケーション名でフォルダを作り、このフォルダのアクセス権を、アプリケーションのポリシーにあわせて設定するというのが順当なのではないかと思います。
-
>IIJIMASさま
メッセージありがとうございます。
初めに教えていただいた方法ですが、私まだまだ初心者のため具体的にどのようなコードをかけばそれが実現できるのかがまだ理解できておりません・・・
教えていただいたMSDNライブラリを参考にしてもう少し調べてみます!
>佐伯浩介さま
メッセージありがとうございます。
フォルダのアクセス権をアプリケーションから設定する方法はわかるのですが、
インストール時のフォルダ作成時に設定する方法がわかりません・・・
インストールは管理者権限で行われるので、インストール後に、作成したフォルダのアクセス権を変更するような処理をはしらせればよいのでしょうか?
よろしくお願いします。
-
あいこ さんからの引用 フォルダのアクセス権をアプリケーションから設定する方法はわかるのですが、
インストール時のフォルダ作成時に設定する方法がわかりません・・・
インストールは管理者権限で行われるので、インストール後に、作成したフォルダのアクセス権を変更するような処理をはしらせればよいのでしょうか?
VSセットアップでしたよね?
残念ながら、VSセットアップでは、アクセス権の設定項目が用意されていません。
#おそらく大半のインストール作業で必要とされないからだとは思いますが...WindowsInstallerとしては、LockPermissions Table でアクセス権の設定ができるようにはなっています。
ただ、その知識レベルが、Native API でのOS設定が可能な知識レベルという非常にハードルの高いものとなっているので、実際に利用するとなるとかなり厳しいかもしれません。
その上、ORCAなりで後付けしないとだめですし...
-
あいこ さんからの引用 初めに教えていただいた方法ですが、私まだまだ初心者のため具体的にどのようなコードをかけばそれが実現できるのかがまだ理解できておりません・・・
教えていただいたMSDNライブラリを参考にしてもう少し調べてみます!
私が言おうとしていたやり方は…
対象マシンに.NETが入っている前提とします。(入っていなければ事前に入れるか、「必須コンポーネント」としてセットアップに含められます。)
以下はすでに試されてるかとは思いますが…
セットアッププロジェクトのファイルシステムエディタで「対象コンピュータ上のファイルシステム」を右クリックしてコンテクストメニューで「特殊フォルダの追加」で「カスタムフォルダ」を追加しそれを選択して
プロパティウィンドウのDefaultLocationで[CommonAppDataFolder]と入力してください。
そこにさらにサブフォルダを追加します。名前をAAAAAとします。これがアプリケーションデータファイルを入れるフォルダです。
必要ならばファイルや更なるサブディレクトリを追加してください。
同じソリューションにクラスライブラリプロジェクトを作成します。Class1.csは消してください。
そのプロジェクトを右クリックしてコンテクストメニューで「追加」「コンポーネント」を選択します。
「新しい項目の追加」ダイアログで「インストーラクラス」を選択して「追加」して下さい。たとえば名前をMyInstallerとします。
コードビューでそれを表示します。
public partial class MyInstaller : Installerの{}なかで
public overrideと入力しスペースを押すとIntelliSenseによっていくつかメソッドが表示されます。
このうち、InstallとCommitを選択してください。
Code Snippetpublic override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
}
public override void Commit(System.Collections.IDictionary savedState)
{
base.Commit(savedState);
}
ファイルの冒頭に以下を追加しておいてください。
Code Snippetusing System.IO;
using System.Security.Principal;
using System.Security.AccessControl;
Commitを以下のように実装してください
Code Snippetconst string FOLDER_NAME = "AAAAA";
public override void Commit(System.Collections.IDictionary savedState)
{
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
if (wp.IsInRole(WindowsBuiltInRole.Administrator))
{
string dataFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), FOLDER_NAME);
DirectoryInfo di = new DirectoryInfo(dataFolderPath);
SecurityIdentifier users_sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
DirectorySecurity dsec = di.GetAccessControl();
dsec.AddAccessRule(
new FileSystemAccessRule(users_sid,
FileSystemRights.Modify,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly,
AccessControlType.Allow));
di.SetAccessControl(dsec);
}
base.Commit(savedState);
}
セットアッププロジェクトに戻り、「ファイルシステムエディタ」で先ほど作成したクラスライブラリプロジェクトの「プライマリ出力」を「アプリケーションフォルダ」追加しておきます。
「カスタム動作エディタ」にて、「インストール」と「確定」のノードを右クリックして「カスタム動作の追加」で「アプリケーションフォルダ」から先ほどのクラスライブラリプロジェクトを選択してください。「インストール」と「確定」のそれぞれのノードの下にそれが現れます。
これをビルドしてインストールすれば、AAAAA配下のファイルが、Usresのユーザでも「変更」できるようになると思います。
あとは上記コードにあるキーワードをMSDNライブラリ等で参照して適切にカスタマイズしてみてください。
TO:皆様、ツッコミお待ちしています…