How do I make a Visual Studio 2010 solution read-only?
How do I make a 开发者_运维技巧Visual Studio 2010 solution read-only?
You have to set the solution (and all other files that you want to protect) to read-only on the operating system level. So for windows select the files, then right click, select properties and then check the read-only check box. The read-only annotation shows up when you are reloading the project. To make the solution/project writeable just uncheck the read-only checkbox.
Note: When setting the solution to read-only, you cannot add any new projects to it, however, the projects remain writeable.
In your comment you said you want to lock your source code. You can "read-only" lock your code with this console program. You can also unlock and tersely query what is locked. It is handy for Visual Studio. It can lock everything because it is recursive and then you would just unlock the single solution you are working on.
namespace SourceLocker1
{
// lock source code by setting read only for all files that match source file extensions
class Program
{
internal const bool VerboseMode = false;
internal const int ShowImmediateLevelDefault = 3;
internal static List<string> FileNameExtensions = new List<string> { ".c", ".cpp", ".cs", ".xaml", ".java", ".py" };
internal enum Mode { SetReadOnly = 0, UnSetReadOnly, Show };
static void Main(string[] args)
{
if ((args.Length != 1) && (args.Length != 2))
Program.PrintUsage();
else if (args.Length == 1)
Program.RecursiveTraverse(Mode.SetReadOnly, args[0]); // program.exe path
else if ((args.Length == 2) && (args[0] == "u"))
Program.RecursiveTraverse(Mode.UnSetReadOnly, args[1]); // program.exe u path
else if ((args.Length == 2) && (args[0] == "s"))
Program.RecursiveTraverse(Mode.Show, args[1]); // program.exe s path
else if ((args.Length == 2) && (args[0] == "si"))
Program.ImmediateModeShowFirstNotReadOnly(Program.ShowImmediateLevelDefault, args[1]); // program.exe si path
else if ((args.Length == 2) && (args[0] == "si1"))
Program.ImmediateModeShowFirstNotReadOnly(1, args[1]); // program.exe si1 path
else if ((args.Length == 2) && (args[0] == "si2"))
Program.ImmediateModeShowFirstNotReadOnly(2, args[1]); // program.exe si2 path
else if ((args.Length == 2) && (args[0] == "si3"))
Program.ImmediateModeShowFirstNotReadOnly(3, args[1]); // program.exe si3 path
else
Program.PrintUsage();
}
static void RecursiveTraverse(Mode mode, string path)
{
IEnumerable<string> filePaths;
if (Directory.Exists(path))
{
filePaths = Directory.EnumerateFiles(path);
// recurse here
foreach (string directoryPath in Directory.EnumerateDirectories(path))
Program.RecursiveTraverse(mode, directoryPath);
}
else
{
if (File.Exists(path))
{
// Array is IEnumerable<T> Read the manual carefully
filePaths = new string[1] { path };
}
else
{
filePaths = new string[0]; // empty array
Console.WriteLine("Not found: {0}", path);
}
}
Program.ProcessFilePaths(mode, filePaths);
}
// immediate mode searches in the immediate levels
// and limits the output to one file per level
// level 1: files in the folder path
// level 2: files in the sub folder paths
// level 3: files in the sub sub folder paths
static void ImmediateModeShowFirstNotReadOnly(int showImmediateLevel, string folderPath)
{
if (Directory.Exists(folderPath))
{
if (showImmediateLevel >= 1)
{
Program.ShowFirstNotReadOnly(Directory.GetFiles(folderPath)); // first level
if (showImmediateLevel > 1)
{
foreach (string subFolderPath in Directory.EnumerateDirectories(folderPath))
{
if (showImmediateLevel >= 2)
{
Program.ShowFirstNotReadOnly(Directory.GetFiles(subFolderPath)); // second level
if (showImmediateLevel > 2)
{
foreach (string subSubFolderPath in Directory.EnumerateDirectories(subFolderPath))
{
if (showImmediateLevel >= 3)
Program.ShowFirstNotReadOnly(Directory.GetFiles(subSubFolderPath)); // third level
}
}
}
}
}
}
}
else
{
Console.WriteLine("No such folder: {0}", folderPath);
}
}
static void PrintUsage()
{
Console.WriteLine("Examples:");
Console.WriteLine(" sourcelocker1 FileName.cs");
Console.WriteLine(" sourcelocker1 FolderName");
Console.WriteLine(" sourcelocker1 u FileName.cs");
Console.WriteLine(" sourcelocker1 u FolderName");
Console.WriteLine(" sourcelocker1 s FileName.cs");
Console.WriteLine(" sourcelocker1 s FolderName");
Console.WriteLine(" Also");
Console.WriteLine(" sourcelocker1 si FolderName");
Console.WriteLine(" sourcelocker1 si1 FolderName");
Console.WriteLine(" sourcelocker1 si2 FolderName");
Console.WriteLine(" sourcelocker1 si3 FolderName");
Console.WriteLine("Usage:");
Console.WriteLine(" This program makes files read-only or not-read-only.");
Console.WriteLine(" This program is recursive or immediate depending upon the mode.");
Console.WriteLine(" By default this program is recursive.");
Console.WriteLine(@" ""u"" means unlock");
Console.WriteLine(@" ""s"" means show unlocked matching files");
Console.WriteLine(@" ""si"" means show unlocked matching files in the ""si3"" immediate mode");
Console.WriteLine(" Immediate mode is an n-level search, abbreviated to one file per folder.");
Console.WriteLine(" Immediate mode can be useful in a Projects folder where");
Console.WriteLine(@" the structure is like Projects\Project1\Source and Projects\Project2\Source");
Console.WriteLine(@" in which case if the path argument is ""Projects"" .cs files may be found at:");
Console.WriteLine(@" Projects\*.cs");
Console.WriteLine(@" Projects\Project1\*.cs");
Console.WriteLine(@" Projects\Project1\Source\*.cs");
Console.WriteLine(@" Projects\Project2\*.cs");
Console.WriteLine(@" Projects\Project2\Source\*.cs");
Console.WriteLine("Supported extension types:");
Console.Write(" ");
IEnumerator e = Program.FileNameExtensions.GetEnumerator();
e.Reset();
while (e.MoveNext())
Console.Write("{0} ", e.Current);
Console.WriteLine();
}
static void ProcessFilePaths(Mode mode, IEnumerable<string> filePaths)
{
foreach (string filePath in filePaths)
{
foreach (string extension in Program.FileNameExtensions)
{
if (filePath.EndsWith(extension, StringComparison.CurrentCultureIgnoreCase))
{
if (mode == Mode.SetReadOnly)
Program.SetFileReadOnly(filePath);
else if (mode == Mode.UnSetReadOnly)
Program.UnSetFileReadOnly(filePath);
else if (mode == Mode.Show)
Program.ShowReadOnlyAttribute(filePath);
else
Debug.Assert(false);
}
}
}
}
static void SetFileReadOnly(string filePath)
{
// FileAttributes is a [FlagsAttribute] modified enum in powers of 2,
// and as such, it can take bitwise operations
VerboseConsole.WriteLine(filePath + " set read only");
File.SetAttributes(filePath, File.GetAttributes(filePath) | FileAttributes.ReadOnly);
}
static void UnSetFileReadOnly(string filePath)
{
// FileAttributes is a [FlagsAttribute] modified enum in powers of 2,
// and as such, it can take bitwise operations
VerboseConsole.WriteLine(filePath + " unset read only");
File.SetAttributes(filePath, File.GetAttributes(filePath) & (~FileAttributes.ReadOnly));
}
static void ShowReadOnlyAttribute(string filePath)
{
bool bit = (File.GetAttributes(filePath) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
if (bit)
VerboseConsole.WriteLine(filePath + " is read only");
else
Console.WriteLine(filePath + " is NOT read only");
}
// shows the first file path that is not read only
// returns silently if there are none
static void ShowFirstNotReadOnly(IEnumerable<string> filePaths)
{
foreach (string filePath in filePaths)
foreach (string extension in Program.FileNameExtensions)
if (filePath.EndsWith(extension, StringComparison.CurrentCultureIgnoreCase) &&
(Program.IsReadOnly(filePath) == false))
{
Console.WriteLine(filePath + " is NOT read only");
return;
}
}
static bool IsReadOnly(string filePath)
{
return (File.GetAttributes(filePath) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
}
}
internal static class VerboseConsole
{
internal static void Write(string arg)
{
if (Program.VerboseMode) Console.Write(arg);
}
internal static void Write(string arg, object[] args)
{
if (Program.VerboseMode) Console.Write(arg, args);
}
internal static void WriteLine(string arg)
{
if (Program.VerboseMode) Console.WriteLine(arg);
}
internal static void WriteLine(string arg, object[] args)
{
if (Program.VerboseMode) Console.WriteLine(arg, args);
}
}
}
The suggested batch file with a terse name is lock.bat
and can serve to invoke the above program.
@REM Commands prefaced with @ have echo suppressed.
@REM
@REM The program sourcelocker1.exe supports only 1 or 2 arguments but we pass 3 just
@REM to verify that usage information is printed in this case of misuse.
@REM
@sourcelocker1.exe %1 %2 %3
精彩评论