C#中如何承担文件的所有权

8

我正在尝试通过C#接管文件并删除它。

该文件是iexplorer.exe,默认所有者为TrustedInstaller。

使用FileSecurity.SetOwner方法似乎可以设置指定的所有权,但实际上并不更改最初的所有者,并且不会引发任何异常。

显然,下一次尝试删除该文件会引发异常。

那么应该更改代码以接管该文件并删除它?

var fileS = File.GetAccessControl(@"C:\Program Files (x86)\Internet Explorer\iexplore.exe");
fileS.SetOwner(new System.Security.Principal.NTAccount(Environment.UserDomainName, Environment.UserName));
File.Delete(@"C:\Program Files (x86)\Internet Explorer\iexplore.exe");

2
这里的UAC是怎么回事?你是否正在以提升的权限运行? - Hans Passant
是的,这并不起作用。您需要设置权限,然后删除给定的文件。解决方案在这里:http://msdn.microsoft.com/en-us/magazine/cc164701.aspx?code=true&level=root%2cPrivilege11 - alternative
4个回答

6

您必须显式启用 SeTakeOwnershipPrivilege

需要在未被授予自主访问权限的情况下拥有对象所有权。此特权仅允许将所有者值设置为持有者可以合法分配为对象所有者的值。用户权限:获取文件或其他对象的所有权。

我建议您阅读 Mark Novak 写的优秀文章: 可靠、安全和高效地操作特权的托管代码

并/或查看他的示例

更新

示例用法:

var fileS = File.GetAccessControl(@"C:\Program Files (x86)\Internet Explorer\iexplore.exe");

Privilege p;
bool ownerChanged = false;
try
{
    p = new Privilege(Privilege.TakeOwnership);
    p.Enable();

    fileS.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)
    File.Delete(@"C:\Program Files (x86)\Internet Explorer\iexplore.exe");

谢谢,Nikolay。有人的工作代码仍然非常受欢迎。 - alternative
@alternative我的答案包含了马克实现的“Privilege”类的链接以及示例代码。我不认为我应该在这里复制粘贴大约1k行的代码。虽然我已经更新了我的答案,提供了一个使用示例。 - Nick Hill
1
文章链接已经失效,但您仍然可以通过滚动到此页面底部并单击2005年3月份来获取CHM格式的文章。保存后右键单击它,在属性中需要取消“阻止”,否则会出现空白。此外,源代码链接在CHM中以.exe文件的形式提供,看起来需要安装才能使用。 - TripleAntigen

4
        string filepath = @"C:\Program Files (x86)\Internet Explorer\iexplore.exe";

        //Get Currently Applied Access Control
        FileSecurity fileS = File.GetAccessControl(filepath);

        //Update it, Grant Current User Full Control
        SecurityIdentifier cu = WindowsIdentity.GetCurrent().User;
        fileS.SetOwner(cu);
        fileS.SetAccessRule(new FileSystemAccessRule(cu, FileSystemRights.FullControl, AccessControlType.Allow));

        //Update the Access Control on the File
        File.SetAccessControl(filepath, fileS);

        //Delete the file
        File.Delete(filepath);

添加以下导入:
        using System.IO;
        using System.Security.AccessControl;
        using System.Security.Principal;

以管理员权限运行代码。


我已经尝试了所有其他获取文件所有权的建议——包括这个页面上的建议,它们期望我使用第三方类,以及来自其他网站的建议,但只有你的建议对我起作用了!谢谢!(我省略了 file.delete 部分,因为我只想出于其他原因拥有所有权。) - Joe Gayetty

1

使用Windows 8.1中的Privilege类来提供支持,例如: 可靠、安全和高效地在托管代码中操作特权

    private bool TryDeleteFile(string fileName)
    {
        string filePath = Path.GetFullPath(fileName);
        var fi = new FileInfo(filePath);

        bool ownerChanged = false;
        bool accessChanged = false;
        bool isDelete = false;

        FileSecurity fs = fi.GetAccessControl();
        Privilege p = new Privilege(Privilege.TakeOwnership);

        try
        {
            p.Enable();
            fs.SetOwner(WindowsIdentity.GetCurrent().User);
            File.SetAccessControl(filePath, fs); //Update the Access Control on the File
            ownerChanged = true;
        }
        catch (PrivilegeNotHeldException ex) { }
        finally { p.Revert(); }

        try
        {
            fs.SetAccessRule(new FileSystemAccessRule(WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, AccessControlType.Allow));
            File.SetAccessControl(filePath, fs);
            accessChanged = true;
        }
        catch (UnauthorizedAccessException  ex) { }

        if (ownerChanged && accessChanged)
        {
            try
            {
                fi.Delete();
                isDelete = true;
            }
            catch (Exception ex) {  }
        }

        return isDelete;
    }

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接