2012-12-10 16 views
1

我正在使用下面的代碼來更改文件的所有者。此代碼在用C#4.0版編寫的Windows服務中運行。它運行在運行Windows Server 2008 R2 Standard,Service Pack 1的本地服務器上。設置文件所有者拋出InvalidOperation異常

我需要將通過FTP接收的文件的所有者更改爲域帳戶。我可以使用資源管理器手動登錄並執行此操作,但是當我嘗試通過代碼運行此代碼時,我得到一個InvalidOperation異常。我可以將所有者更改爲本地系統帳戶,但不是網絡帳戶。任何幫助,將不勝感激。

我正在處理一些奇怪的處理EDI文件的Microsoft Dynamics AX代碼。該過程要求文件的所有者是有效的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) 

UPDATE

如果我改變下我試圖改變所有者帳戶運行服務的帳戶,我得到不同的例外。

意外的異常:System.UnauthorizedAccessException:嘗試 執行未經授權的操作。在 System.Security.AccessControl.Win32.SetSecurityInfo(的ResourceType型, 字符串名稱,SafeHandle的手柄,SecurityInfos securityInformation, 的SecurityIdentifier老闆,集團的SecurityIdentifier,GenericAcl SACL, GenericAcl DACL)

+0

需要更多信息。你爲什麼不復制文件並刪除原件。這將創建一個具有正確權限的新文件夾。否則,如果您希望使用您的代碼,則需要有關上傳文件的更多信息。完整的例外也是有幫助的。 –

+0

我已經添加了這個異常,並且詳細描述了我正在做的事情,或者至少我爲什麼要這樣做。 –

+0

將您剛纔發佈的評論置入您的問題中。 –

回答

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