Hey, Scripting Guy! Question

Hey, Scripting Guy! Is it possible to use a script to change the read-only attribute of a file?

-- ZO

SpacerHey, Scripting Guy! AnswerScript Center

Hey, ZO. Of course, you can do this; the FileSystemObject can do anything!

Well, OK, it can’t do either of those things. And, no, it can’t do that, either. But it can change a read-only file to a writeable file, and with just a few lines of code.

Here’s a script that binds to the file C:\Scripts\Computers.txt, checks to see if the file is read-only and, if it is, makes it writeable:

Const READ_ONLY = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\Scripts\Computers.txt")

If objFile.Attributes AND READ_ONLY Then
    objFile.Attributes = objFile.Attributes XOR READ_ONLY
End If

Pretty easy, huh? The only tricky part comes with this line of code, when we check to see if the file is read-only:

If objFile.Attributes AND READ_ONLY Then

The way we determine whether or not a file is read-only is by checking the appropriate switch in the Attributes bitmask. If this switch (which has the value of 1; that’s why we created a constant named READ_ONLY and assigned it the value 1) is enabled, then the file is read-only. If the switch is not enabled then the file is writeable.

This line of code is a bit confusing (welcome to the world of Boolean logic!) but it can be read like this: if the read-only switch within the Attributes bitmask is enabled, then run the next line of code. The syntax is kind of clumsy-looking, but it’s just something we have to live with.

And before you ask, what if you wanted to turn a writeable file into a read-only file? Well, in that case, we’d want to determine if the read-only switch is not set. Thus we’d use this line of code instead:

If Not objFile.Attributes AND READ_ONLY Then

If it turns out that we have a read-only file, the script then uses the Boolean operator XOR to “flip” the read-only switch. This line of code executes only if the read-only switch is enabled; consequently, it’s going to turn this switch off, thus making the file writeable. The XOR operator just flips things from on to off and vice-versa. That’s why we check to see if the read-only switch is enabled before we call XOR. Suppose we didn’t check and suppose the file was writeable. In that case, XOR would flip the switch, and make our writeable file read-only.

Yes, it’s confusing. For a very brief primer on bitmask properties and Boolean logic, you might take a look at this portion of the Microsoft Windows 2000 Scripting Guide.

Of course, instead of simply changing one read-only file to a writeable file, a more common task is to go through a folder and make all the read-only files writeable. Can a script do that? You bet it can. Here’s a script that uses WMI to retrieve a list of all the read-only files found in the folder C:\Scripts (by checking for files where the Writeable property is FALSE). The script then takes each of those files, passes the file name to the FileSystemObject, and proceeds to make the file writeable. We won’t explain how all the WMI code works today; if you’re interested in that, you might take a look at this Hey, Scripting Guy! column.

Oh, right; here’s the script:

Const READ_ONLY = 1

strComputer = "."
Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colFiles = objWMIService. _
    ExecQuery("Select * from CIM_DataFile where Path = '\\Scripts\\' " & _
        "AND Drive = 'C:' AND Writeable = FALSE")

For Each objFile in colFiles
    Set objReadOnlyFile = objFSO.GetFile(objFile.Name)
    objReadOnlyFile.Attributes = objReadOnlyFile.Attributes XOR READ_ONLY
Next