2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2025-06-22

はじめに

本記事では、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

Visual Studio 2022 - .NET Framework 4.8 は、C# 7.3 が既定です。
このため、サンプルコードは、C# 7.3 機能範囲で記述しています。

データ格納フォルダ

特殊フォルダ

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

  • 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 に格納して、アンインストール時にデータを保持することで、再インストール時に前回選択した情報を再利用することができます。
CommonApplicationData を利用するプロダクトの場合、アンインストール時に、保存されているデータを削除するかを確認して、削除を行うこともあります。

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;
  }
}

directoryInfo.GetAccessControl という記述にすることで、.NET Framework と .NET で利用可能なサンプルコードとしています。
このコードは、.NET Framework と .NET で機能は等価ですが、実装が異なります。
.NET Framework の場合、DirectoryInfo インスタンスメソッド として提供されていて、直接呼び出す形態です。
.NET の場合、DirectoryInfo インスタンスメソッドは廃止され、FileSystemAclExtensions による拡張メソッドとして提供されます。

public static DirectorySecurity GetAccessControl(
                                 this DirectoryInfo directoryInfo)

ここで this DirectoryInfo という記述が、拡張メソッドであることを示しています。
つまり、DirectoryInfo のインスタンスに対して直接呼び出せるように見えますが、実際には FileSystemAclExtensions クラスの静的メソッドです。

FileSystemAclExtensions は、.NET Framework では標準サポートされていません。
NuGet Gallery | System.IO.FileSystem.AccessControl を .NET Framework に導入すれば利用可能となります。

directoryInfo.SetAccessControl も同様です。

.NET 限定、もしくは、NuGet Gallery | System.IO.FileSystem.AccessControl を .NET Framework に導入するならば、FileSystemAclExtensions を明示的に利用したほうが万人向けのコードかもしれません。

<省略>
// 現在のアクセス権取得 - FileSystemAclExtensions 利用可
var dirInfo = new DirectoryInfo(folder);
var security = FileSystemAclExtensions.GetAccessControl(dirInfo);

<省略>
// アクセス権限付与 - FileSystemAclExtensions 利用可
security.AddAccessRule(newRule);
FileSystemAclExtensions.SetAccessControl(dirInfo, security);

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

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

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?