How to change file permissions with WMI?

2019-07-03 22:02发布

I'm want to do the equivalent of what is described here from a script. Basically, I want to take ownership of the file, and set the permissions to OWNER/Full Control.

It seems to me that using WMI from a vbs script is the most portable way. That is, I'd like to avoid xcacls, icacls and other tools that either require a download, or are supported only on some versions of windows.

After googling around, I found this code for taking ownership:

'connect to WMI namespace on local machine 
Set objServices = 
GetObject("winmgmts:{impersonationLevel=impersonate}") 
'get a reference to data file 
strFile = Wscript.Arguments(0) 
Set objFile = objServices.Get("CIM_DataFile.Name='" & strFile & "'") 
If  objFile.TakeOwnership = 0 Then 
    Wscript.Echo "File ownership successfully changed" 
Else 
    Wscript.Echo "File ownership transfer operation" 
End If 

The pieces I'm still missing is setting the permissions, and having it work on relative paths.

2条回答
淡お忘
2楼-- · 2019-07-03 22:07

Since you're already using TakeOwnership in the CIM_DataFile class, I'd assume you could just use ChangeSecurityPermissions to change the permissions, which is in the same class.

And you might be able to use GetAbsolutePathName to convert your relative paths to absolute paths before you use them.

查看更多
劳资没心,怎么记你
3楼-- · 2019-07-03 22:07

Taking the hints from ho1's answer, I googled around some more, and eventually came up with this:

This script finds the current user SID, then takes ownership and changes the permissions on the file given in argv[0] to Full Control only to current user.

Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}") 

Function GetCurrentUserSID
    ' Get user name '
    Set colComputer = objWMI.ExecQuery("Select * from Win32_ComputerSystem")

    ' Looping over one item '
    For Each objComputer in colComputer
      currentUserName = objComputer.UserName
    Next

    Set AccountSIDs = GetObject("Winmgmts:").InstancesOf("Win32_AccountSID") 
    For Each AccountSID In AccountSIDs
        AccountKey = AccountSID.Element 
        Set objAccount = GetObject("Winmgmts:"+AccountKey) 
        strName = objAccount.Domain & "\" & objAccount.Name
        If strName = currentUserName Then ' that's it 
            SIDKey = AccountSID.Setting
            Set SID = GetObject("Winmgmts:" + SIDKey)
            GetCurrentUserSID = SID.BinaryRepresentation
            Exit For 
        End If   
    Next 
End Function

Function LimitPermissions(path, SID)
    Set objFile = objWMI.Get("CIM_DataFile.Name='" & path & "'") 

    Set Trustee = GetObject("Winmgmts:Win32_Trustee").SpawnInstance_ 
    Trustee.SID = SID

    Set ACE = getObject("Winmgmts:Win32_Ace").Spawninstance_ 
    ACE.AccessMask = 2032127 ' Full Control
    ACE.AceFlags = 3 
    ACE.AceType = 0
    ACE.Trustee = Trustee 

    Set objSecDescriptor = GetObject("Winmgmts:Win32_SecurityDescriptor").SpawnInstance_ 
    objSecDescriptor.DACL = Array(ACE) 

    objFile.ChangeSecurityPermissions objSecDescriptor, 4 
End Function

Function TakeOwnership(path)
    Set objFile = objWMI.Get("CIM_DataFile.Name='" & path & "'") 
    TakeOwnership = objFile.TakeOwnership
End Function

' Main '

strFilename = Wscript.Arguments(0) 
Set fso = CreateObject("Scripting.FileSystemObject")
path = fso.GetAbsolutePathName(strFilename)

SID = GetCurrentUserSID

TakeOwnership path
LimitPermissions path, SID
查看更多
登录 后发表回答