1

以下のコードを使用して、ファイルの所有者を変更しています。このコードは、C#バージョン4.0で記述されたWindowsサービスで実行されます。ローカルサーバーで実行されており、Windows Server 2008 R2 Standard、ServicePack1を実行しています。

FTP経由で受信したファイルの所有者をドメインアカウントに変更する必要があります。ボックスにログインしてエクスプローラーを使用して手動で実行できますが、コードを介してこれを実行しようとすると、InvalidOperation例外が発生します。所有者をローカルシステムアカウントに変更できますが、ネットワークアカウントに変更することはできません。これに関する助けをいただければ幸いです。

私はEDIファイルを処理するいくつかの奇妙なMicrosoftDynamicsAXコードを使用しています。このプロセスでは、ファイルの所有者が有効なDAXユーザー(この場合はドメインユーザー)である必要があります。FTP経由でEDIデータを送信するベンダーがあります。DAXアプリケーションは10分ごとにFTPディレクトリをチェックし、ファイルを処理します。所有者が無効であるため、プロセスは現在失敗しています。そこで、ファイルが到着したときに所有者を変更するサービスを作成しました。ただし、以下のコードは、コード例の下にある例外を除いて失敗します。

var ediFileOwner = new NTAccount("MyDomain", _ediEndpointUserAccount);

var fileSecurity = File.GetAccessControl(fileName);

var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

fileSecurity.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.FullControl, AccessControlType.Allow));
fileSecurity.AddAccessRule(new FileSystemAccessRule(ediFileOwner, FileSystemRights.TakeOwnership, AccessControlType.Allow));


fileSecurity.SetOwner(ediFileOwner); //Change our owner from to our desired User

File.SetAccessControl(fileName, fileSecurity);

完全な例外は次のとおりです。

System.InvalidOperationException: The security identifier is not allowed to be the owner of this object.
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle handle, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections)
at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
at System.IO.File.SetAccessControl(String path, FileSecurity fileSecurity)

アップデート

サービスを実行しているアカウントを、所有者に変更しようとしているアカウントに変更すると、別の例外が発生します。

予期しない例外:System.UnauthorizedAccessException:許可されていない操作を実行しようとしました。System.Security.AccessControl.Win32.SetSecurityInfo(ResourceTypeタイプ、文字列名、SafeHandleハンドル、SecurityInfos securityInformation、SecurityIdentifier所有者、SecurityIdentifierグループ、GenericAcl sacl、GenericAcl dacl)

4

1 に答える 1

2

ここで見つけたコードを使用することになりました。http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User

私はすべてを成し遂げるためにいくつかのフープを飛び越えなければなりませんでした、しかしそれはうまくいきました。発生したエラーを回避するために、ユーザーを切り替えるだけでなく、見つけた偽装のものを使用する必要がありました。

using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;

// ...        

//Copy the file. This allows our service account to take ownership of the copied file
var tempFileName = Path.Combine(Path.GetDirectoryName(file.FileName), "TEMP_" + file.FileNameOnly);
File.Copy(file.FileName, tempFileName);


var windowID = WindowsIdentity.GetCurrent();

var currUserName = windowID.User.Translate(typeof(NTAccount)).Value;
var splitChar = new[] { '\\' };

//var name = currUserName.Split(splitChar)[1];
//var domain = currUserName.Split(splitChar)[0];

var ediFileOwner = new NTAccount("TricorBraun", _radleyEDIEndpointUserAccount);

//We have to give Access to the service account to delete the original file
var fileSecurity = File.GetAccessControl(file.FileName);
var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
fileSecurity.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.FullControl, AccessControlType.Allow));
File.SetAccessControl(file.FileName, fileSecurity);
File.Delete(file.FileName);



//We rename our file to get our original file name back
File.Move(tempFileName, file.FileName);


//The following give our desired user permissions to take Ownership of the file.
//We have to do this while running under the service account.
fileSecurity = File.GetAccessControl(file.FileName);
var aosSID =  (SecurityIdentifier) ediFileOwner.Translate(typeof(SecurityIdentifier));
fileSecurity.AddAccessRule(new FileSystemAccessRule(aosSID, FileSystemRights.FullControl, AccessControlType.Allow));
File.SetAccessControl(file.FileName, fileSecurity);

//Now we user the Impersonator (http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User)
//This allows us to manage the file as the Account we wish to change ownership to.
//It makes itself the owner.
using (new Impersonator(_radleyEDIEndpointUserAccount, "MyDomain", "password")) {
    _logger.Debug(string.Format("Attempting changing owner to Tricorbraun\\{0}", _radleyEDIEndpointUserAccount));
    fileSecurity = File.GetAccessControl(file.FileName);
    fileSecurity.SetOwner(ediFileOwner); //Change our owner from LocalAdmin to our chosen DAX User
    _logger.Debug(string.Format("Setting owner to Tricorbraun - {0}", _radleyEDIEndpointUserAccount));
    File.SetAccessControl(file.FileName, fileSecurity);
}
于 2012-12-10T20:55:44.480 に答える