📁

C# - C:\ProgramData と Everyoneフルコントール

に公開

はじめに

本記事では、Windows の C:\ProgramData フォルダについて記載します。
その後、関連する情報として、フォルダのアクセス権限を Everyone フルコントールにする C# サンプルコードを掲載します。

テスト環境

ここに記載した情報/ソースコードは、Visual Studio Community 2022 を利用した下記プロジェクトで生成したモジュールを Windows 11 24H2 で動作確認しています。

  • Windows Forms - .NET Framework 4.8
  • Windows Forms - .NET 8
  • WPF - .NET Framework 4.8
  • WPF - .NET 8

データ格納フォルダ

特殊フォルダ

https://learn.microsoft.com/ja-jp/dotnet/api/system.environment.specialfolder

プロダクト(アプリケーション)のデータ格納フォルダとして、以下が定義されています。

  • Environment.SpecialFolder.CommonApplicationData
    • すべてのユーザが使用するプロダクト固有のデータを格納する共通フォルダ
    • 通常は全ユーザで書き込み可能ですが、特定の条件下では管理者権限が必要となる場合もあります
    • 実体バス:C:\ProgramData
    • 隠しフォルダとして扱われているため、エクスプローラでは「隠しファイル:表示」にしないと表示されません
  • Environment.SpecialFolder.ApplicationData
    • カレントユーザのプロダクト固有のデータを格納するフォルダ
    • 該当ユーザにフルコントールが付与されています
    • 実体バス:C:\Users\<ユーザ名>\AppData\Roaming
string programdata = Environment.GetFolderPath(
                       Environment.SpecialFolder.CommonApplicationData);
string appdata = Environment.GetFolderPath(
                       Environment.SpecialFolder.ApplicationData);
Console.WriteLine($"CommonApplicationData: {programdata}");
Console.WriteLine($"ApplicationData: {appdata}");

各プロダクトでは、これらのフォルダ下に 会社名\プロダクト名 もしくは プロダクト名 というフォルダを作成して、各種データを格納します。

会社名:Hoge、プロダクト名:FooBar
 C:\ProgramData\Hoge\Foobar
 C:\Users\<ユーザ名>\AppData\Roaming\Hoge\Foobar

データ格納フォルダをインストールフォルダと別に用意する理由のひとつは、プロダクトのアンインストール時にデータを維持できるようにするためです。

CommonApplicationData

一般的には、インストーラ(UAC により昇格された管理者権限で実行)によって、CommonApplicationData 配下にプロダクト用のフォルダを作成し、用途に応じたサブフォルダを作成します。
これらは、用途にあわせて、次のようなアクセス権限を設定します。

対象サブフォルダの用途 アクセス権限
構成ファイルやテンプレートなど参照のみのデータを格納 一般ユーザは読み取りのみ可
ログや共有データなど更新するデータを格納 Everyone フルコントール

Windows の基本的な設計方針としては、ApplicationData を使用してユーザごとに変化するデータ(設定ファイル、キャッシュなど)を管理することが推奨されています。
この場合、インストール時に作成された初期設定を CommonApplicationData 配下に格納し、アプリケーション初回起動時にユーザの ApplicationData にコピーして、以降はユーザごとに個別に管理するといった方法が考えられます。

一方で、CommonApplicationData を用いて、すべてのユーザが共有して更新可能なデータを扱うこともあります。
この場合、インストーラによって対象フォルダやそのサブフォルダに Everyone フルコントールを明示的に付与することで、全ユーザでの書き込みを保証することができます。

Everyone フルコントール

// 指定フォルダを Everyone フルコントール
// 権限不足とならないように管理者権限で実行が望ましい
private void SetFullAccessForFolder(string folder)
{
  // フォルダ存在確認
  if (!Directory.Exists(folder))
  {
    try
    {
      // 対象フォルダ存在しないので作成
      Directory.CreateDirectory(folder);
    }
    catch (UnauthorizedAccessException)
    {
      // TODO - 権限不足
      Console.WriteLine("フォルダ作成エラー: 権限不足");
      return;
    }
    catch (SecurityException)
    {
      // TODO - セキュリティ例外
      Console.WriteLine("フォルダ作成エラー: セキュリティ例外");
      return;
    }
  }

  try
  {
    // Everyone
    var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

    // 現在のアクセス権取得
    var directoryInfo = new DirectoryInfo(folder);
    var security = directoryInfo.GetAccessControl();
    // LINQ を利用してすでに Everyone フルコントロール権限があるか判定
    bool bAlready = security
            .GetAccessRules(true, true, typeof(SecurityIdentifier))
            .Cast<FileSystemAccessRule>()
            .Any(rule => rule.IdentityReference.Value == everyone.Value
              && (rule.FileSystemRights & FileSystemRights.FullControl)
                                           == FileSystemRights.FullControl);
    // 未付与時にフルコントロール付与
    if (!bAlready)
    {
      var newRule = new FileSystemAccessRule(
            everyone, FileSystemRights.FullControl,
            InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
            PropagationFlags.None, AccessControlType.Allow);
      // アクセス権限付与
      security.AddAccessRule(newRule);
      directoryInfo.SetAccessControl(security);
    }
  }
  catch (UnauthorizedAccessException)
  {
    // TODO - 権限不足
    Console.WriteLine("アクセス権制御エラー: 権限不足");
    return;
  }
  catch (SecurityException)
  {
    // TODO - セキュリティ例外
    Console.WriteLine("アクセス権制御エラー: セキュリティ例外");
    return;
  }
}

以下のように利用します。

string programdata = Environment.GetFolderPath(
                       Environment.SpecialFolder.CommonApplicationData);
string company = "Hoge";            // TODO
string product = "FooBar";          // TODO
string settings = "CommonSettings"; // TODO

SetFullAccessForFolder($@"{programdata}\{company}\{product}\{settings}");

出典

本記事は、2025/06/23 Qiita 投稿記事の転載です。

C# - C:\ProgramData と Everyoneフルコントール

Discussion