How Can I Change a Read-only File to a Read-write File?

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I change a read-only file to a read-write file?

— WR

SpacerHey, Scripting Guy! AnswerScript Center

Hey, WR. We don’t mean to shock you, but how can you change a read-only file to a read-write file? Why, by using a script, of course!


We know: you never saw that coming, did you?


As a matter of fact, you can use this script, which changes the file C:\Scripts\Test.vbs from a read-only file to a read-write file:

Const ReadOnly = 1

Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objFile = objFSO.GetFile(“C:\Scripts\Test.vbs”)

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


You’re right: maybe we should explain what’s going on here. We begin by setting the value of the constant ReadOnly to 1 (more on this monetarily). We then create an instance of the FileSystemObject, and use the GetFile method to bind to the file C:\Scripts\Test.vbs. So far, so good.


This is where it starts to get weird, or at least a little unusual. The Read-only attribute is stored as part of a “bitmask” along with other file attributes such as Hidden (value of 2, which indicates whether the file is a hidden file) and System (value of 4, which indicates whether the file is a system file). In a bitmask (loosely defined as a collection of attributes stored as a single value) individual attributes can be likened to switches, switches that can be either on or off. If the switch with value of 1 is on, then the file is read-only; if the switch with the value of 1 is off, then the file is read-write.


That just leaves one question: how the heck do you determine whether one of these switches is on or off? A complete explanation of that is well beyond the scope of this column, but the simple answer is that you use the bitwise AND operator. Notice the following odd-looking line in the script:

If objFile.Attributes AND ReadOnly Then

Believe it or not, this line is checking to see if the ReadOnly attribute (with a value of 1) is on. What if we wanted to see if the file was a hidden file? Well, in that case (and assuming we set the value of a constant named Hidden to 2), we’d use this line of code:

If objFile.Attributes AND Hidden Then

Basically the AND operator can be read like this: “If we’re looking at the Attributes of the file and of the ReadOnly switch is on, then this is a read-only file and this If statement is True. If the ReadOnly switch is off, then this If statement is False.” Experienced scripters might cringe a bit at that explanation, but that gives you an idea of what’s going on here.


So why are we checking to see if the file is read-only? Well, momentarily, we’re going to use the XOR operator to “flip” the switch; that’s what this line of code is for:

objFile.Attributes = objFile.Attributes XOR ReadOnly

In this example, XOR simply toggles the file from one state to the other. If the file is read-only, XOR switches it to read-write; if it’s read-write, XOR switches it to read-only. That’s why we first check to see if the file is already read-only. If it is, we want to flip the switch and make it read-write. If it’s already read-write, though, we obviously don’t want to flip the switch; after all, that would make the file read-only. (Remember, we’re just toggling from one state to the other.)


You’re right: this bitwise stuff is confusing, so we owe you a treat. Therefore, here’s a script which binds to the folder C:\Scripts and turns all the read-only files in that folder into read-write files. We won’t explain the details behind how the script gets back a list of all the files in a folder; we’ll save that for tomorrow’s column. (A sneaky way of making you come back tomorrow!) For now, though, here’s your treat:

Const ReadOnly = 1

Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objFolder = objFSO.GetFolder(“C:\Scripts”)
Set colFiles = objFolder.Files

For Each objFile in colFiles
If objFile.Attributes AND ReadOnly Then
objFile.Attributes = objFile.Attributes XOR ReadOnly
End If
Next


See you tomorrow, huh?