File Attribute Changer





5.00/5 (10 votes)
An Attribute changer which can change attributes of files and folders
Introduction
Recently, I came across an application called "BulkFileModifier
" from nirsoft which is able to change attributes of files and folders. I wanted to know how it works so I developed one of my own. Also, this is an update to my previous release, which modified attributes of files only. Now the program can modify attributes of folders also. I added the option to scan directories recursively, i.e., now you can modify the attributes of all the files and folders inside the directory at once! I also added the option to drag and drop files directly on the program.
Using the Code
To create this program, I added System.IO namespace
. The namespace contains classes to read information from files and folders.
The Main
form uses datagridview
which will contain the file path. GroupBox
control contains radiobuttons
to change option of changing attributes of files and folders within.checkbox
and DateTimePicker
to change file attributes.
public partial class FileAttributeChanger : Form
{
//Initializing new instance of DataTable
DataTable dt = new DataTable();
DataRow dr;
string filename = "";
public FileAttributeChanger()
{
InitializeComponent();
//Adding a new column name to datagridview of type string
//that will show files or folder names , its type and full path
dt.Columns.Add(new DataColumn("Name", typeof(string)));
dt.Columns.Add(new DataColumn("Type", typeof(string)));
dt.Columns.Add(new DataColumn("Path", typeof(string)));
}
...
Adding Files to the Form
To add files to datagrid
view, you can select one or more than one file. Note that all the files added to datagridview
will have the same attributes after you change its attribute. If you want to remove any file from the view, then just click the row and press the "Delete" button on your keyboard. To remove all files from datagridview
, click the "Clearlist" button.
//AddFiles To DatagridView
private void btn_AddFiles_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true; //Allow multiselection of files
ofd.ShowDialog();
//If many files are selected, then all of them will be added to datagridview
foreach (string file in ofd.FileNames)
{
dr = dt.NewRow();
FileInfo fi = new FileInfo(file);
dr[0] = fi.Name;
dr[1] = "File";
dr[2] = file;//Filename will be shown in the first column of all rows
dt.Rows.Add(dr);
dgv_filescollection.DataSource = dt;
dgv_filescollection.Focus();
}
}
...
Adding Folders to datagridview
Adding folders to the form is similar to adding files. The difference is that you cannot add multiple folders at the same time.
//AddFiles To DatagridView
private void btn_addfolder_Click(object sender, EventArgs e)
{
//show folder browser dialog
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.ShowNewFolderButton = false;
fbd.ShowDialog();
//if folder browser dialog box path is not empty
if (fbd.SelectedPath != "")
{
if (Directory.Exists(fbd.SelectedPath))
{
DirectoryInfo di = new DirectoryInfo(fbd.SelectedPath);
dr = dt.NewRow();
dr[0] = di.Name;
dr[1] = "Directory";
dr[2] = di.FullName;
dt.Rows.Add(dr);
dgv_filescollection.DataSource = dt;
dgv_filescollection.Focus();//set focus to datagridview
//so that you can remove files/folders just by pressing "delete"
}
}
}
...
Get Current File Attributes
When files are added to datagridview
, the dgv_filescollection_RowEnter
event below will get the current file or folder name. The current name (i.e., full path of file is passed as a parameter to a user function checkattributes
. The File.GetAttributes
method will retrieve all the attributes of the file and will be passed as a string
. The Contains(Attribute name)
will check whether the file has Archive
, Readonly
properties or not. If any attribute is present, then the checkbox corresponding to it will be checked. Also with change in selected filename in datagridview
, the checkbox
es will be unchecked. This is necessary otherwise it will show attributes of the previous file or folder also. To see all the attributes of the file at once, add a message box inside the checkattribs
function and type MessageBox.Show(Fileattributes);
//if current row changes then the file name will be changed
private void dgv_filescollection_RowEnter
(object sender, DataGridViewCellEventArgs e)
{
//filename is actually the fullpath of file or folder which is obtained by
//checking its currentrow and value of the 3rd cell in the current row.
//The File name will be used to retrieve its attributes
filename = dgv_filescollection.Rows[e.RowIndex].Cells[2].Value.ToString();
string gettype =
dgv_filescollection.Rows[e.RowIndex].Cells[1].Value.ToString();
clearCheckBox(); //checkboxes are unchecked everytime row is changed
checkattribs(filename,gettype); //file or folder path and its type
//is passed on to check its attributes
}
//clear the checkboxes so that current file or folder will
//not show attributes of previous one
private void clearCheckBox()
{
//since the groupbox contains only checkboxes,
//hence their checked status can be removed
foreach (CheckBox cbx in gbx_attributes.Controls)
{
if (cbx.Checked == true)
{
cbx.Checked = false;
}
}
chk_ChangeCreatedDate.Checked = false;
chk_ChangeModifiedDate.Checked = false;
chk_ChangeAccessedDate.Checked = false;
}
private void checkattribs(string currentfile,string type)
{
try
{
String attributes = "";
if (type == "File")
{
//Get Dates of file
//Show File creation,modified,lastaccess date in datetimepicker
dtp_creationdate.Value = File.GetCreationTime(currentfile);
dtp_modifieddate.Value = File.GetLastWriteTime(currentfile);
dtp_accesseddate.Value = File.GetLastAccessTime(currentfile);
attributes = File.GetAttributes(currentfile).ToString();
}
else if (type == "Directory")
{
DirectoryInfo di = new DirectoryInfo(currentfile);
dtp_creationdate.Value = di.CreationTime;
dtp_modifieddate.Value = di.LastWriteTime;
dtp_accesseddate.Value = di.LastAccessTime;
attributes = di.Attributes.ToString();
}
//The File.GetAttributes method retrieves all the attributes of file
if (attributes.Contains("Archive") == true)
{
chk_archive.CheckState = CheckState.Checked;
}
if (attributes.Contains("Compressed"))
{
chk_compressed.Checked = true;
}
.....
....
//Get Dates of file
//Show File creation,modified,lastaccess date in datetimepicker
dtp_creationdate.Value = File.GetCreationTime(currentfile);
dtp_modifieddate.Value = File.GetLastWriteTime(currentfile);
dtp_accesseddate.Value = File.GetLastAccessTime(currentfile);
}
...
Dragging and Dropping Files and Folders
To drag and drop files and folders, we need to make use of the dragevents
handler. The form has a DragEnter
event handler. To allow dropping files onto form, we need to set AllowDrop
property to true
. On dragging over file to form, it will show cursor drageffects of copy operation(i.e., mouse pointer with + symbol). To add files and folders that have been dragged over, we use dragdrop
event of the form. If one or many files are selected, then all the files will be stored in a string
array after they have been dropped. The foreach
loop will retrieve all the file and folder names that had been dragged over and then it will be added to datagridview
. More Information about dragdrop can be found at this link.
private void FileAttributeChanger_DragOver(object sender, DragEventArgs e)
{
//on dragging a file or folder over form, show drageffects of copy operation
e.Effect = DragDropEffects.Copy;
this.AllowDrop = true;
}
private void FileAttributeChanger_DragDrop(object sender, DragEventArgs e)
{
//get all filenames and store them in string array
string[] FileList = (string[])e.Data.GetData(DataFormats.FileDrop, false);
foreach (string file in FileList)
{
//Add Directories to datagridview
if (File.GetAttributes(file).ToString().Contains("Directory"))
{
DirectoryInfo di = new DirectoryInfo(file);
dr = dt.NewRow(); //create a new datarow
dr[0] = di.Name; //get the name of directory
dr[1] = "Directory"; //Type , in this case Directory
dr[2] = di.FullName; //get full path to that directory
dt.Rows.Add(dr);
}
//This will add each file to datagridview
else
{
dr = dt.NewRow();
FileInfo fi = new FileInfo(file);
dr[0] = fi.Name; //Get file name
dr[1] = "File"; //store its type, will be used
//to distinguish between directory and files
dr[2] = file; //full path of the file
dt.Rows.Add(dr);
}
}
dgv_filescollection.DataSource = dt;
dgv_filescollection.Focus();
}
Finally...
Once the files whose attributes are to be changed are added to the Datagridview
, check or uncheck the current attributes of the file. (Note: All the files added to the datagridview
will have the same attributes once the ChangeAttributes
button is pressed). If the file is checked to be set as ReadOnly
or System
, then before doing so, attribute of file will be set to normal
(one that has no attributes set). If you don't want to change the current attribute, leave it checked. To change the attribute of folders, one is presented with the option of changing either the attribute of current folder only or all the folders and files within the folder. If the option of applying changes to folder, subfolders and files is selected, then the folder is scanned recursively. This is made by making use of searchoption enum
. The searchoption
allows searching files or folders in topdirectory
or alldirectories
. Here, since we have checked all subdirectories, it will scan recursively and get information about files and folders using directoryinfo
or fileinfo
class. If only the attributes for the directory are to be set, then click "Apply Changes to Folder only" radiobutton .
private void btn_ChangeAttribs_Click(object sender, EventArgs e)
{
string type ="";
foreach (DataGridViewRow dgvr in dgv_filescollection.Rows)
{
try
{
//Get Current file name in the datagridview
filename = dgvr.Cells[2].Value.ToString();
type = dgvr.Cells[1].Value.ToString();
//Set File Attributes To normal so that new attributes can be set
//This is required because file attributes cannot be
//changed if it is read-only
File.SetAttributes(filename, FileAttributes.Normal);
if (type == "File")
{
//change file dates if date time picker for
//creation date is enabled
if (dtp_creationdate.Enabled)
File.SetCreationTime(filename, dtp_creationdate.Value);
//change modified time if date time picker for
//modified time is enabled
if (dtp_modifieddate.Enabled)
File.SetLastWriteTime(filename, dtp_modifieddate.Value);
//change last accessed date if datetime picker for
//last accessed date is enabled
if (dtp_accesseddate.Enabled)
File.SetLastAccessTime(filename, dtp_accesseddate.Value);
ChangeFileAttributes(filename);//pass filename as parameter
//to change its attributes
}
//if Changes to all is enabled and type is directory then all the
//files and folders in the directory will have the same attributes
else if (rbtn_changestoall.Checked == true && type == "Directory")
{
//create an instance of DirectoryInfo to
//get information about the directory
DirectoryInfo di = new DirectoryInfo(filename);
//get all the files in the directory with
//searchoption by searching all subdirectories within
foreach (FileInfo files in di.GetFiles
("*.*", SearchOption.AllDirectories))
{
File.SetAttributes(files.FullName, FileAttributes.Normal);
//change file dates if date time picker for
//creation date is enabled
if (dtp_creationdate.Enabled)
File.SetCreationTime
(files.FullName, dtp_creationdate.Value);
if (dtp_modifieddate.Enabled)
File.SetLastWriteTime
(files.FullName, dtp_modifieddate.Value);
if (dtp_accesseddate.Enabled)
File.SetLastAccessTime(files.FullName,
dtp_accesseddate.Value);
//pass the full path of file as a parameter
//to change its attributes
ChangeFileAttributes(files.FullName);
}
//get all the directories in the current directory
//by searching all directories within
foreach (DirectoryInfo dinfo in di.GetDirectories
("*.*", SearchOption.AllDirectories))
{
File.SetAttributes(dinfo.FullName, FileAttributes.Normal);
//change creation date of directory if creation date
//is to be changed
if (dtp_creationdate.Enabled)
Directory.SetCreationTime
(dinfo.FullName, dtp_creationdate.Value);
if (dtp_modifieddate.Enabled)
Directory.SetLastWriteTime
(dinfo.FullName, dtp_modifieddate.Value);
if (dtp_accesseddate.Enabled)
Directory.SetLastAccessTime
(dinfo.FullName, dtp_accesseddate.Value);
ChangeFileAttributes(dinfo.FullName);
}
//change attribute of the directory
//which was added to datagridview also
if (dtp_creationdate.Enabled)
Directory.SetCreationTime(di.FullName, dtp_creationdate.Value);
//similarly change modified date and lastwritetime of directory
....
...
}
//if only the attributes of the directory in the datagridview
//is to be changed
//and NOT its subdirectories and files
else if (rbtn_folderonly.Checked == true && type == "Directory")
{
if (dtp_creationdate.Enabled)
Directory.SetCreationTime(filename, dtp_creationdate.Value);
if (dtp_modifieddate.Enabled)
Directory.SetLastWriteTime(filename, dtp_modifieddate.Value);
....
private void ChangeFileAttributes(string fname)
{
//File class is also able to change attributes of Directory ;)
//if Archive is checked, then its attribute will be set to archive
if (chk_archive.Checked == true &&
File.GetAttributes(fname).ToString().Contains("Archive") == false)
File.SetAttributes(fname, File.GetAttributes(fname) |
FileAttributes.Archive); // Archive attribute will be added to
//its existing attributes
//if unchecked, then Archive attribute will be removed
//To remove attribute a tilde(~) is appended before the FileAttributes enum
else if (chk_archive.Checked == false &&
File.GetAttributes(fname).ToString().Contains("Archive"))
File.SetAttributes(fname, File.GetAttributes(fname) &
~FileAttributes.Archive);
//set or unset attribute of file or folder to be hidden
if (chk_hidden.Checked == true &&
File.GetAttributes(fname).ToString().Contains("Hidden") == false)
File.SetAttributes(fname,
File.GetAttributes(fname) | FileAttributes.Hidden);
else if (chk_hidden.Checked == false &&
File.GetAttributes(fname).ToString().Contains("Hidden"))
File.SetAttributes(fname, File.GetAttributes(fname) &
~FileAttributes.Hidden);
//similar code to change system and readonly attributes
...
}
After changing attributes, reload the same files and check their current properties:
Conclusion
In my initial release, I had released the project with very minimal features. Thanks to the recommendations of CodeProject users, I have now made it a full fledged project which now changes folder attributes, and allows dragdrop files and folders. Please let me know if you like my project so that I may plan for another release.
History
- 20th July, 2011
- Initial release
- Added option to add folders
- Added option to scan folders recursively
- Added
DragDrop
feature - Updated source and article and added demo project