質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Q&A

解決済

3回答

4343閲覧

internal sealed class にアクセスできない

mercurian-teto

総合スコア75

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

0グッド

0クリップ

投稿2019/07/26 09:53

編集2019/07/27 07:11

#実現したいこと
ファイルの所有者を変更して、アクセス権を変更しようと思っています。
現在のユーザーアカウントのファイルの所有権をAdministratorsに変更し、ファイルのアクセス権を変更することができました。

しかし、ファイルの所有者がTrustedInstallerの場合はうまくいきませんでしたので
visualstudioは管理者権限で起動しています。
ネットで検索してみると、
ファイルの所有者がTrusted Installerの場合はPrivelegeのクラスを用意しなければならないらしいので、以下のように実装しました。(ファイルの所有者を変更するところまで記載しています。)

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Security.AccessControl; using System.Security.Principal; using System.Text; using System.Threading.Tasks; using System.Windows; public class ModifyPermission { public static bool DenyFileAccess(string filepath) { FileSecurity fs; fs = File.GetAccessControl(filepath); var ntAccount = new NTAccount("BUILTIN", "Administrators"); fs.SetOwner(ntAccount); Privilege p; bool ownerChanged = false; try { p = new Privilege(Privilege.TakeOwnership); p.Enable(); fs.SetOwner(new System.Security.Principal.NTAccount( Environment.UserDomainName, Environment.UserName)); ownerChanged = true; } catch (PrivilegeNotHeldException e) { // privilege not held // TODO: show an error message, write logs, etc. } finally { p.Revert(); } if (!ownerChanged) return false; try { File.SetAccessControl(filepath, fs); } catch (InvalidOperationException ex) { //Debug.WriteLine("You cannot assign ownership to that user." + // "Either you don't have TakeOwnership permissions, or it is not your user account." //); //throw; return false; } catch(System.UnauthorizedAccessException e3) { MessageBox.Show("error"); } //以下省略 } }

すると、
Privelegeはアクセスできない保護レベルですといわれましたとエラーがはかれました。

Privelegeの定義へ移動すると
internal sealed class privilegeとなっていました。
今回の自作クラスは継承をしていないので、internalに問題があるかと思い、
AssemblyInfo.csに

[assembly: InternalsVisibleTo("System.Security.AccessControl")]

を追加しました。しかしエラーが出たままです。
上の属性の文字列の部分に該当の名前空間を入れたはずなのですが、エラーが出たままでした。
どこをどのように修正すれば、エラーが払えるでしょうか。
回答お願いします。

##環境
windows10 pro 1803
visualstudio 2017

##追記2
System.Reflectionを使用して実装しました。
例外を投げずに処理ができたのですが、
ファイルのアクセス権および所有者は変更されませんでした。
下記のサイトを参考にしました。
https://stackoverflow.com/questions/5528888/how-to-enable-the-secreateglobalprivilege-in-net-without-resorting-to-p-invoke?lq=1

public static bool DenyFileAccess(string filepath) { FileSecurity fs; fs = File.GetAccessControl(filepath); Type privilegeType = Type.GetType("System.Security.AccessControl.Privilege"); object privilege; bool ownerChanged = false; try { privilege = Activator.CreateInstance(privilegeType, "SeTakeOwnershipPrivilege"); // => privilege.Enable(); privilegeType.GetMethod("Enable").Invoke(privilege, null); var ntAccount = new NTAccount("BUILTIN", "Administrators"); fs.SetOwner(ntAccount); File.SetAccessControl(filepath, fs); privilegeType.GetMethod("Revert").Invoke(privilege, null); ownerChanged = true; } catch { MessageBox.Show("error"); } if (!ownerChanged) return false; try { File.SetAccessControl(filepath, fs); } catch (InvalidOperationException ex) { MessageBox.Show("error"); return false; } catch (System.UnauthorizedAccessException e3) { MessageBox.Show("error"); } try { Debug.WriteLine("Adding access control entry for " + filepath); //管理者権限で起動していても、デスクトップユーザーのアカウント名が返されます。nuget->Cassia ITerminalServicesManager manager = new TerminalServicesManager(); ITerminalServicesSession session = manager.CurrentSession; string username = session.UserName; // Add the access control entry to the file. string principal = string.Format(@"{0}\{1}", System.Environment.MachineName, username); AddFileSecurity(filepath, principal, FileSystemRights.ReadAndExecute, AccessControlType.Deny); AddFileSecurity(filepath, principal, FileSystemRights.Read, AccessControlType.Deny); //Console.WriteLine("Removing access control entry from " // + filepath); //// Remove the access control entry from the file. //RemoveFileSecurity(filepath, @"BUILTIN\Administrators", // FileSystemRights.ReadData, AccessControlType.Allow); Console.WriteLine("Done."); } catch (System.UnauthorizedAccessException e3) { MessageBox.Show("error"); } catch (Exception e2) { Console.WriteLine(e2); return false; }

##追記3
方法2

static class Program { [STAThread] static void Main() { string filepath = @"C:\WINDOWS\system32\cmd.exe"; FileSecurity fs; fs = File.GetAccessControl(filepath); var takeOwnerShip = new Privirage(PrivirageNames.SeTakeOwnershipPrivilege); takeOwnerShip.Enable(); ProcessStartInfo psi = new ProcessStartInfo("whoami.exe", "/priv") { UseShellExecute = false }; using (Process pprocess = Process.Start(psi)) { pprocess.WaitForExit(); } var ntAccount = new NTAccount("BUILTIN", "Administrators"); fs.SetOwner(ntAccount); File.SetAccessControl(filepath, fs); takeOwnerShip.Revert(); psi = new ProcessStartInfo("whoami.exe", "/priv") { UseShellExecute = false }; using (Process pprocess = Process.Start(psi)) { pprocess.WaitForExit(); } Console.ReadKey(); } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

internal なクラスは他のアセンブリからアクセスできません。

stack overflow で触れられている Privilege クラスは MSDN マガジンに掲載された記事に付属していたサンプルのようです。

InternalsVisibleTo は単体テストで使用する属性ですので、指定したからといって他のアセンブリの非公開部分にアクセスできるわけではありません。

System.Reflection を使って非公開部分にアクセスすることはできますが、せっかく Microsoft がソースコードを公開してくれているのですから、勉強がてら実装してみてはいかがでしょうか。

「privilege.cs」
https://referencesource.microsoft.com/#mscorlib/system/security/accesscontrol/privilege.cs

TakeOwnership 特権を有効にしたいだけなら、System.Security.AccessControl.ObjectSecurity クラスをを継承して Persist メソッドをオーバーライドすればなんとかなりそうではあります。

https://referencesource.microsoft.com/#mscorlib/system/security/accesscontrol/objectsecurity.cs,344

あと、MSDN フォーラムでやりとりしながら作っていただいたサンプルソース(VB)があります。
私が「回答の候補に設定」したソースはきちんと動きますが、何点か修正しておいたほうが良い部分があってスレッドの中で指摘しています。
ご参考になれば幸いです。

SeBackupPrivilegeについて

投稿2019/07/26 12:17

編集2019/07/26 12:23
KOZ6.0

総合スコア2622

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mercurian-teto

2019/07/26 15:59

回答ありがとうございます。 追記2のようにSystem.Reflectionを使用して実装してみましたが、ファイルのアクセス権と アクセス許可の内容が変更されていませんでした。
KOZ6.0

2019/07/27 00:13 編集

書き込んでいただいたソースを実行してみましたが、ちゃんと呼び出しはできているのに特権が有効になっていないですね。 特権が有効になっているかどうかは、プロセスの中から新しいプロセスを起動して "whoami.exe /priv" を実行するとわかります。 var psi = new ProcessStartInfo("whoami.exe", "/priv"); psi.UseShellExecute = false; using (var p = Process.Start(psi)) { p.WaitForExit(); } 呼び出すために必要な手順があるのかもしれませんね。 ちなみに MSDN のスレッドのソースを実行したら、TakeOwnership 特権が有効になったのが確認できました。
KOZ6.0

2019/07/27 02:46 編集

これ以上やりとりするのであれば、はタイトル(?)とは別の話題になってしまうので新しい質問を上げていただいたほうがよさそうです。 といいつつサンプルを作ってみたのでよろしければ。 http://kozhouse.homeip.net/dotnet/etc/21/
mercurian-teto

2019/07/27 07:16 編集

サンプルありがとうございます。 サンプルを用いてcmd.exeの所有者をadministartorに変更しようところ見ましたが(追記2)、TakeOwnerShipは有効になっていても所有者は変更されていませんでした。 kozさんの指摘通り、タイトルが別の話題になってしまい、又,当初のinternal classにアクセスすると言うことは実現できたので、違うレスにて質問しようと思います。回答ありがとうございました。
KOZ6.0

2019/07/27 14:54

FileSecurity.SetOwner だとうまくいかないですね。 SetNamedSecurityInfo API を使うとうまくいきます。 サンプルを更新しておきました。
KOZ6.0

2019/07/27 15:42

>FileSecurity.SetOwner だとうまくいかないですね。 と思ったら SetAccessControl が自分のコードには抜けていて、追加したらちゃんと変更できました。 mercurian-teto さんのとこで動かないのは SysWow64 のほうを更新しているのかも。
guest

0

これじゃないですか?

ProcessPrivileges

投稿2019/07/26 12:11

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/07/26 16:15 編集

internal なクラスをリフレクションで無理やり使うなんてことをやっていいわけがない。使わないでくれという意味でわざわざ internal にしてるのに。
Zuishin

2019/07/27 07:22

低評価の人は理由をどうぞ。
guest

0

Privelegeはアクセスできない保護レベルですといわれましたとエラー

まず、エラーメッセージはそのまま、書いた方が回答がつき易いです。

internal sealed class privilegeとなっていました。

privilegeは何処で定義されているクラスでしょうか? Systemにあるクラスでしょうか? もしそうならば、外部(一般アプリ)からの利用が許されていない、と考えられます。

投稿2019/07/26 12:06

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mercurian-teto

2019/07/26 15:52

回答ありがとうございます。 Privilegeは System.Security.AccessControl名前空間にある internal sealed class Privilegeでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問