The System.IO.FileAttributes class gives us access to file/directory attributes. In this article, we’ll see how to use this class to first read the current attributes and then change them.
The System.IO.FileAttributes class
The class has numerous members that can be accessed. These members, which are really file or directory properties, fall under the Mscorlib Assembly (in Mscorlib.dll), and should be the same for Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, and the Windows .NET Server family.
| Member Name | Description |
| Archive | The file’s archive status. Applications use this attribute to mark files for backup or removal. |
| Compressed | The file is compressed. |
| Device | Reserved for future use. |
| Directory | The file is a directory. |
| Encrypted | The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is the default for newly created files and directories. |
| Hidden | The file is hidden, and thus is not included in an ordinary directory listing. |
| Normal | The file is normal and has no other attributes set. This attribute is valid only if used alone. |
| NotContentIndexed | The file will not be indexed by the operating system’s content indexing service. |
| Offline | The file is offline. The data of the file is not immediately available. |
| ReadOnly | The file is read-only. |
| ReparsePoint | The file contains a reparse point, which is a block of user-defined data associated with a file or a directory. |
| SparseFile | The file is a sparse file. Sparse files are typically large files whose data are mostly zeros. |
| System | The file is a system file. The file is part of the operating system or is used exclusively by the operating system. |
| Temporary | The file is temporary. File systems attempt to keep all of the data in memory for quicker access rather than flushing the data back to mass storage. A temporary file should be deleted by the application as soon as it is no longer needed. |
This enumeration allows a bitwise combination of its member values. Bit fields are generally used for lists of elements that might occur in combination. Therefore, bit fields are designed to be combined with a bitwise OR operation to generate unnamed values. Each member in this class carries a bitwise value with it.
The web form: editAttribs.aspx
Our aspx page will accept a directory or a file through the URL (by HTTP GET). I leave this up to you to perform, as it should be pretty easy to do. Make sure it is a virtual path though, otherwise you will have to modify my code. If it’s a file, preceed the path by an F, otherwise if it’s a directory, preceed the path by a D.
![]()
In the example above, we will display the attributes for a file, located at /images/xefteri.gif. If we wanted to see the attributes of the parent directory of this file (i.e. images), then the URL which we would have had to pass would be http://localhost/editAttribs.aspx?location=D/images.
The final template will look like this:

The HTML code that produces this is pretty much straight forward. All the attributes, images and checkboxes in the template are declared as a Web Controls, so that we can programatically set them. The StatusMessage label control will output any exceptions on updating the attributes. Our code-behind source code is simply editAttribs.aspx.vb and the class which we will inherit from is called EditAttribs.
<%@ Page Language="vb" src="editAttribs.aspx.vb" inherits="EditAttribs" %>
<html>
<head>
<title>Xefteri - Edit Attributes</title>
<style type="text/css">
#tblContents {
font-family: Verdana;
font-size: 70%;
}
</style>
</head>
<body bgcolor="#ffffff">
<form method="post" ID="setAttribs" runat="server">
<asp:Label runat="server" ID="StatusMessage" Visible="False" />
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td bgcolor="#696969">
<table cellspacing="0" cellpadding="4" border="0" bgcolor="#ffffff" id="tblContents">
<tr>
<td valign="top" align="right"><asp:Image runat="server" ID="imgType" /></td>
<td> </td>
</tr>
<tr>
<td valign="top" align="right"><b>Name:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblName" /></td>
</tr>
<tr>
<td colspan="2"><hr size="1" width="100%" noshade></td>
</tr>
<tr>
<td valign="top" align="right"><b>Virtual Location:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblLocation" /></td>
</tr>
<tr>
<td valign="top" align="right"><b>Physical Location:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblAbsLocation" /></td>
</tr>
<tr>
<td valign="top" align="right"><b>Size:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblSize" /></td>
</tr>
<tr>
<td colspan="2"><hr size="1" width="100%" noshade></td>
</tr>
<tr>
<td valign="top" align="right"><b>Created:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblCreated" /></td>
</tr>
<tr>
<td valign="top" align="right"><b>Last Modified:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblModified" /></td>
</tr>
<tr>
<td valign="top" align="right"><b>Last Accessed:</b></td>
<td valign="top"><asp:Label runat="server" ID="lblLastAccessed" /></td>
</tr>
<tr>
<td colspan="2"><hr size="1" width="100%" noshade></td>
</tr>
<tr>
<td valign="top"><asp:CheckBox runat="server" ID="cbxReadOnly" Text="Read-Only" /></td>
<td valign="top"><asp:CheckBox runat="server" ID="cbxHidden" Text="Hidden" /></td>
</tr>
<tr>
<td colspan="2" valign="top"><asp:CheckBox runat="server" ID="cbxArchive" Text="Ready For Archiving" /></td>
</tr>
<tr>
<td colspan="2" valign="top"><asp:CheckBox runat="server" ID="cbxIndexing" Text="For fast searching, allow Indexing Service to index this" /></td>
</tr>
<tr>
<td colspan="2"><hr size="1" width="100%" noshade></td>
</tr>
<tr>
<td colspan="2" valign="top"><asp:Image runat="server" ID="imgCompressed" />Compressed contents to save disk space</td>
</tr>
<tr>
<td colspan="2" valign="top"><asp:Image runat="server" ID="imgEncrypted" /> Encrypted contents to secure data</td>
</tr>
<tr>
<td colspan="2"> </td>
</tr>
<tr>
<td colspan="2" align="center" valign="top"><asp:Button runat="server" ID="btnSetAttribs" Text="Update Attributes" onClick="UpdateAttribs_Click" /></td>
</tr>
<tr>
<td colspan="2"> </td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>
The code-behind: editAttribs.aspx.vb
Let’s take a look, piece by piece, at the code needed to get this done.
Option Explicit on Option Strict on Imports System Imports System.IO Imports Microsoft.VisualBasic Public Class EditAttribs Inherits System.Web.UI.Page 'declare variables used throughout the class Dim Private strLocation As String Dim Private strAbsLocation As String Dim Private originalLocation As String Dim Private isFile As Boolean Dim Private intTotalFolders As Integer Dim Private intTotalFiles As Integer Dim Private imgYes As String = "yes.gif" Dim Private imgNo As String = "no.gif" 'declare the various Web Controls Protected lblLocation As System.Web.UI.WebControls.Label Protected lblAbsLocation As System.Web.UI.WebControls.Label Protected imgType As System.Web.UI.WebControls.Image Protected lblName As System.Web.UI.WebControls.Label Protected lblSize As System.Web.UI.WebControls.Label Protected lblCreated As System.Web.UI.WebControls.Label Protected lblModified As System.Web.UI.WebControls.Label Protected lblLastAccessed As System.Web.UI.WebControls.Label Protected cbxReadOnly As System.Web.UI.WebControls.CheckBox Protected cbxHidden As System.Web.UI.WebControls.CheckBox Protected cbxIndexing As System.Web.UI.WebControls.CheckBox Protected cbxArchive As System.Web.UI.WebControls.CheckBox Protected imgCompressed As System.Web.UI.WebControls.Image Protected imgEncrypted As System.Web.UI.WebControls.Image Protected StatusMessage As System.Web.UI.WebControls.Label ...
Our custom class is called EditAttribs, and it inherits from the System.Web.UI.Page parent class. The first thing we do is dimension our global variables, and then declare our Web Controls which are used in the default.aspx page.
...
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim objFile As FileInfo
Dim objFolder As DirectoryInfo
'read the location variable passed in the URL
strLocation = Request.Params("location")
originalLocation = strLocation
If strLocation = "" Then
strLocation = "/"
End If
isFile = strLocation.StartsWith("F")
strLocation = Mid(strLocation, 2, Len(strLocation))
strAbsLocation = Server.MapPath(strLocation)
lblLocation.Text = strLocation
lblAbsLocation.Text = strAbsLocation
'if we are viewing a file
If isFile Then
imgType.ImageUrl = "file.gif"
imgType.AlternateText = "Type: File"
objFile = New FileInfo(strAbsLocation)
lblName.Text = objFile.Name
lblSize.Text = FormatSize(objFile.Length)
lblCreated.Text = FormatDate(objFile.CreationTime)
lblModified.Text = FormatDate(objFile.LastWriteTime)
lblLastAccessed.Text = FormatDate(objFile.LastWriteTime)
If ((CDbl(objFile.Attributes And FileAttributes.ReadOnly)) = FileAttributes.ReadOnly) Then
cbxReadOnly.Checked = True
End If
If ((CDbl(objFile.Attributes And FileAttributes.Hidden)) = FileAttributes.Hidden) Then
cbxHidden.Checked = True
End If
If ((CDbl(objFile.Attributes And FileAttributes.NotContentIndexed)) = _
FileAttributes.NotContentIndexed) Then
cbxIndexing.Checked = False
Else
cbxIndexing.Checked = True
End If
If ((CDbl(objFile.Attributes And FileAttributes.Archive)) = FileAttributes.Archive) Then
cbxArchive.Checked = True
End If
If ((CDbl(objFile.Attributes And FileAttributes.Compressed)) = FileAttributes.Compressed) Then
imgCompressed.ImageUrl = imgYes
imgCompressed.AlternateText = "Compressed"
Else
imgCompressed.ImageUrl = imgNo
imgCompressed.AlternateText = "Not Compressed"
End If
If ((CDbl(objFile.Attributes And FileAttributes.Encrypted)) = FileAttributes.Encrypted) Then
imgEncrypted.ImageUrl = imgYes
imgEncrypted.AlternateText = "Encrypted"
Else
imgEncrypted.ImageUrl = imgNo
imgEncrypted.AlternateText = "Not Encrypted"
End If
'if we are viewing a directory
Else
imgType.ImageUrl = "directory.gif"
imgType.AlternateText = "Type: Folder"
objFolder = New DirectoryInfo(strAbsLocation)
lblName.Text = objFolder.Name
'run recursive method to calculate directory size
'and include total number of subdirectories and files
lblSize.Text = FormatSize(GetDirectorySize(objFolder.FullName)) " (" + intTotalFolders.ToString() + " folders, " + intTotalFiles.Tostring() + " files)"
lblCreated.Text = FormatDate(objFolder.CreationTime)
lblModified.Text = FormatDate(objFolder.LastWriteTime)
lblLastAccessed.text = FormatDate(objFolder.LastWriteTime)
If ((CDbl(objFolder.Attributes And FileAttributes.ReadOnly)) = FileAttributes.ReadOnly) Then
cbxReadOnly.Checked = True
End If
If ((CDbl(objFolder.Attributes And FileAttributes.Hidden)) = FileAttributes.Hidden) Then
cbxHidden.Checked = True
End If
If ((CDbl(objFolder.Attributes And FileAttributes.NotContentIndexed)) = _
FileAttributes.NotContentIndexed) Then
cbxIndexing.Checked = False
Else
cbxIndexing.Checked = True
End If
If ((CDbl(objFolder.Attributes And FileAttributes.Archive)) = FileAttributes.Archive) Then
cbxArchive.Checked = True
End If
If ((CDbl(objFolder.Attributes And FileAttributes.Compressed)) = FileAttributes.Compressed) Then
imgCompressed.ImageUrl = imgYes
imgCompressed.AlternateText = "Compressed"
Else
imgCompressed.ImageUrl = imgNo
imgCompressed.AlternateText = "Not Compressed"
End If
If ((CDbl(objFolder.Attributes And FileAttributes.Encrypted)) = FileAttributes.Encrypted) Then
imgEncrypted.ImageUrl = imgYes
imgEncrypted.AlternateText = "Encrypted"
Else
imgEncrypted.ImageUrl = imgNo
imgEncrypted.AlternateText = "Not Encrypted"
End If
End If
End Sub
...
The Page_Load() method performs most of the actions. It first reads the location variable passed through the URL, to determine if we are looking at a file or a directory, and what its path is. We use the System.IO.FileInfo class to access the attributes if we are looking at a file, and the System.IO.DirectoryInfo class if it’s a directory. The Web Controls’ output is the same in both cases, except for the lblSize, which includes the number of subdirectories and files in parenthesis when we are looking at a directory. This closely resembles the Windows OS behavior when viewing a directory’s properties.
To determine if an attribute is set, we must convert the bit sum of the attribute into a Double value and compare it with the corresponding FileAttribute value. Let’s say for example, that we are trying to establish if the attribute Compressed has been set for a directory. We must convert the value of System.IO.DirectoryInfo.Attributes and System.IO.FileAttributes.Compressed into a Double value, and compare it with System.IO.FileAttributes.Compressed. If they are equal, then the attribute has been set.
...
Protected Sub UpdateAttribs_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim fileAttribs As FileAttributes = FileAttributes.Normal
If Request.Form("cbxReadOnly") = "on" Then
fileAttribs = fileAttribs Or FileAttributes.ReadOnly
End If
If Request.Form("cbxHidden") = "on" Then
fileAttribs = fileAttribs Or FileAttributes.Hidden
End If
If Request.Form("cbxArchive") = "on" Then
fileAttribs = fileAttribs Or FileAttributes.Archive
End If
If Request.Form("cbxIndexing") <> "on" Then
fileAttribs = fileAttribs Or FileAttributes.NotContentIndexed
End If
Try
File.SetAttributes(strAbsLocation, fileAttribs)
Server.Transfer("editAttribs.aspx?location=" + originalLocation)
Catch exc As Exception
StatusMessage.Text = exc.Message
StatusMessage.Visible = True
End Try
End Sub
...
The UpdateAttribs_Click() method gets called when we click on the button “Update Attributes” in our aspx page. It checks every checkbox control to see if it was checked or not, and sets the file/directory attributes accordingly. To add the attribute ReadOnly for example, we simply create an instance of the FileAttributes class for the file or directory, and add the attribute to the Normal state using OR. This works the same way for both files and directories.
...
Private Function FormatDate(ByVal datDate as Date) As String
Return String.Format("{0:dddd, MMMM dd yyyy - hh:mm tt}", datDate)
End Function
Private Function FormatSize(ByVal dblFileSize As Double) As String
If dblFileSize < 1024 Then
Return String.Format("{0:N0} B", dblFileSize)
ElseIf dblFileSize < 1024 * 1024 Then
Return String.Format("{0:N2} KB", dblFileSize/1024)
ElseIf dblFileSize < 1024 * 1024 * 1024 Then
Return String.Format("{0:N2} MB", dblFileSize/(1024*1024))
End If
End Function
Private Function GetDirectorySize(ByVal path As String) As Long
Dim lngDirSize As Long = 0
Dim objDirInfo As DirectoryInfo = New DirectoryInfo(path)
Dim arrChildFiles As Array = objDirInfo.GetFiles()
Dim arrSubFolders As Array = objDirInfo.GetDirectories()
Dim objChildFile As FileInfo
Dim objChildFolder As DirectoryInfo
'for each file found under the directory
'increment by 1 the number of files found
'and add its size to the total size
For Each objChildFile in arrChildFiles
intTotalFiles = intTotalFiles + 1
lngDirSize += objChildFile.Length
Next
'for each subfolder found
'increment by 1 the number of sub-directories found
'and call this function recursively
For Each objChildFolder in arrSubFolders
intTotalFolders = intTotalFolders + 1
lngDirSize += GetDirectorySize(objChildFolder.FullName)
Next
Return lngDirSize
End Function
End Class
These last 3 functions perform some general tasks for us. The FormatDate() and FormatSize() give us a custom output for dates and sizes respectively. The GetDirectorySize() returns the total size of a directory – something that is not provided by the current release of the .NET framework. If you wish, you can take a look at a previous article, which goes into more detail on how to accomplish this. The GetDirectorySize() function also calculates the total number of sub-directories and files found under the directory that we are viewing.
Editing other document properties
There are other properties that are available in a file. These include, among others, the Title, Subject, Author, Category, Keywords & Comments. Microsoft makes available a DLL that can read and change these properties. Since this is outside the scope of this article, you can read more about how to do this from Microsoft or from others who have done this.
We have seen how to view and edit file and directory attributes by using the System.IO.FileAttributes class. We are not limited to these attributes though. We can expand on this if we want to, and also edit the CreationTime, LastAccessTime and LastWriteTime. These last 3 attributes are supported under both the System.IO.FileInfo and System.IO.DirectoryInfo classes, and and they can be set and retrieved.