Click here to Skip to main content
15,889,595 members
Articles / Programming Languages / C#

A Small Tool to Remove SCC Information of a VS2003.NET Project File

Rate me:
Please Sign up or sign in to vote.
4.73/5 (25 votes)
15 Jul 20043 min read 190.4K   1.3K   60   41
This tool removes the information saved in the project and solution files of VS2003.NET which are relative to source code control.

Sample Image - RemoveSCCInfo.jpg

Introduction

With the yet to be released SourceSafe 2005, we decided to switch back to a SourceSafe database for some of our projects instead of a CVS repository. And saying that it has been quite a pain is not even beginning to come close to reality. Source-code integration in VS.NET is not a nightmare, but you have to change your project files and delete a few other files to get rid of it. Failing to do so may get you in real trouble when rebinding to another SCC provider.

This "article" (OK, it may not be a great one, but that's my first one for Code Project) summarizes what I have found while building this tool, either by myself or on blogs and newsgroups.

Using the Code

I decided to write this small tool to help get rid of everything that is related to source-code control. It's quite straightforward to use: just enter the path to your project or solution file and click Continue, and it should work.

For now, there are (quite) a few limitations:

  • It does not handle Web Projects (I'll do it as soon as I can).
  • Only .csproj and .vbproj and deployment project (.vdproj) files are supported, and having any other type of project will block you from using this tool.
  • It doesn't change the Read-Only status of files that are not .sln, .csproj or .vbproj.

Points of Interest

Visual Studio keeps its SCC information in quite a few places. And if you want to get clean, you'll have to get rid of all of them.

The Solution File (.sln)

The solution file contains a section that is dedicated to SCC. If you open the .sln file in a text editor, you'll have something that looks like:

Microsoft Visual Studio Solution File, Format Version 8.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyProject", 
    "Projects\MyProject.csproj", "{B1A1C06F-EB84-4215-975E-6B0B57496BAC}" 
        ProjectSection(ProjectDependencies) = postProject 
        EndProjectSection
EndProject 
        ... other projects in your solution ...
Global
    GlobalSection(SourceCodeControl) = preSolution
        SccNumberOfProjects = 1
        SccProjectName0 = Perforce\u0020Project
        SccLocalPath0 = .
        SccProvider0 = MSSCCI:Perforce\u0020SCM
        CanCheckoutShared = true
        SolutionUniqueID = {0F9ACC79-634F-44DB-9C57-C4B0C461AA7B}
        SccProjectUniqueName1 = Projects\\MyProject.csproj
        SccLocalPath1 = MyProject
    EndGlobalSection
        ... other global sections ...        
EndGlobal

Just delete the GlobalSection(SourceCodeControl) ... EndGlobalSection and save the file.

The Solution User Options File (.suo)

I didn't find any real good solution besides deleting the file. But don't worry, VS.NET will create it back when you open the sln file.

The Projects File (C# .csproj and VB.NET .vbproj)

Those files are XML based, so it won't really be hard to clean them. All you have to do is remove the following attributes on the main project node (which is named CSharp or VisualBasic):

  • SccProjectName
  • SccLocalPath
  • SccProvider
  • SccAuxPath

The Setup Projects Files (.vdproj)

They are quite similar to the .csproj and .vbproj except on one point: they are not XML based. You'll have to remove the following lines:

"SccProjectName" = "XXXXXXXXXXXXXXXXXX"
"SccLocalPath" = "8:..\\.."
"SccAuxPath" = "8:"
"SccProvider" = "XXXXXXXXXXXXXXXXXX"

All the Other Stuff

Visual Studio creates a few files for managing the source code integration, so you'll have to delete those files:

  • In the same folder as the .sln file, you should find a solutionName.vssscc.
  • With the projects file, you'll have a projectFileName.projectExtension.vspscc.
  • You will also find some vssver.scc and mssccprj.scc in the project directory.

If you use MS SourceSafe as your source "database", you'll also find a vssver.scc file in each folder: delete them all if you want, but I didn't have any issues for not having done so.

History

  • v 0.9.3.0: Support for localhost-based ASP.NET projects
  • v 0.9.2.0: VDPROJ support, French chars in project and solution support
  • v 0.9.0.0: First release, quite a few things to be done

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Web Developer
France France
I'm french, do I need to say more ?

Comments and Discussions

 
QuestionDoes this work with VS2005? Pin
Keith Mallen21-Apr-08 9:19
Keith Mallen21-Apr-08 9:19 
GeneralUse UnBind instead! Pin
alinconstantin21-Jul-07 7:44
alinconstantin21-Jul-07 7:44 
GeneralCool and fast Pin
Vastug7-Aug-06 2:24
Vastug7-Aug-06 2:24 
QuestionIs this the same as Unbind? Pin
Giles8-May-06 22:38
Giles8-May-06 22:38 
GeneralThanks Pin
j0ey2-May-06 4:35
j0ey2-May-06 4:35 
QuestionHas anyone had this working with VS2005.NET Projects? Pin
Peter Connors27-Apr-06 6:31
Peter Connors27-Apr-06 6:31 
GeneralSource Code Pin
anger66623-Feb-06 2:08
anger66623-Feb-06 2:08 
GeneralRe: Source Code Pin
mcarbenay23-Feb-06 2:36
mcarbenay23-Feb-06 2:36 
GeneralRe: Source Code Pin
anger66623-Feb-06 2:44
anger66623-Feb-06 2:44 
GeneralThanks: Question on VSS & the IDE Pin
Len Miller1-Feb-06 3:30
Len Miller1-Feb-06 3:30 
QuestionC++ projects? Pin
Anna-Jayne Metcalfe10-Jan-06 4:01
Anna-Jayne Metcalfe10-Jan-06 4:01 
AnswerRe: C++ projects? Pin
mcarbenay10-Jan-06 4:52
mcarbenay10-Jan-06 4:52 
GeneralRe: C++ projects? Pin
Anna-Jayne Metcalfe10-Jan-06 8:47
Anna-Jayne Metcalfe10-Jan-06 8:47 
GeneralThanks! Pin
-Dy20-Sep-05 23:37
-Dy20-Sep-05 23:37 
GeneralThanks a lot Pin
Gaben29-Jun-05 10:37
Gaben29-Jun-05 10:37 
GeneralHelp Translating the regular expression for use in VB.net Pin
Chubby Arse12-May-05 22:16
Chubby Arse12-May-05 22:16 
GeneralRe: Help Translating the regular expression for use in VB.net Pin
mcarbenay12-May-05 23:43
mcarbenay12-May-05 23:43 
GeneralRe: Help Translating the regular expression for use in VB.net Pin
Chubby Arse16-May-05 5:18
Chubby Arse16-May-05 5:18 
GeneralRe: Help Translating the regular expression for use in VB.net Pin
mcarbenay16-May-05 10:05
mcarbenay16-May-05 10:05 
GeneralVery cool Pin
msureshkr14-Feb-05 8:46
msureshkr14-Feb-05 8:46 
GeneralCool Pin
rico6519-Dec-04 23:59
rico6519-Dec-04 23:59 
GeneralBackup leave directory when "don't backup" is torn on Pin
Mike Chaliy7-Oct-04 20:33
Mike Chaliy7-Oct-04 20:33 
GeneralRe: Backup leave directory when "don't backup" is torn on Pin
mcarbenay7-Oct-04 21:54
mcarbenay7-Oct-04 21:54 
GeneralRe: Backup leave directory when "don't backup" is torn on Pin
Greg Norris24-Nov-05 11:39
Greg Norris24-Nov-05 11:39 
GeneralI don't know... Pin
mracka22-Jul-04 19:49
mracka22-Jul-04 19:49 
I wrote this. Just copy text to a *.js file. Put the file to the same dir, where *.sln is. No need for exe...

<code>
/// Global ------------------------------------------------------

var deleteByForce = true;
var consoleOnly = true;
var defaultTimeOut = 1;
var showDetails = false;

var WSShell;
var fso;
var currentFolder;
var deletedFiles = 0;
var modifiedFiles = 0;
var ForReading = 1, ForWriting = 2, ForAppending = 8;
var CharSetDefault = -2, CharSetUnicode = -1, CharSetAscii = 0;
var AttrNormal = 0, AttrReadOnly = 1, AttrHidden = 2, AttrSystem = 4,
AttrVolume = 8, AttrDirectory = 16, AttrArchive = 32, AttrAlias = 1024,
AttrCompressed = 2048;


Init();
Main();
//Test();


/// Main ------------------------------------------------------

function Main() {

var text;

// say hello
text = "Remove from SourceSafe has started.";
Out(text,true);
COut("Working folder: \r\n"+ currentFolder);


// delete files
// *.suo, *.eto, *.vssscc, *.vspscc, vssver.scc, mssccprj.scc
DeleteFiles("[.]*([.]suo$|[.]eto$|[.]vssscc$|[.]vspscc$|vssver[.]scc$|mssccprj[.]scc$)");

// modify files
// *.etp, *.sln, *.csproj
ModifyFiles("[.]*([.]etp$|[.]sln$|[.]csproj$)");

// say goodbye
text = "Remove from SourceSafe has finished. \r\n\r\n"
+ "Deleted files: \t" + deletedFiles + "\r\n"
+ "Modified files: \t" + modifiedFiles + "\r\n";
Out(text,false);
}

function Init() {

// detect command line
try {
WScript.StdOut.WriteLine(" ");
} catch (e) {
consoleOnly = false;
}

// initialize
WSShell = new ActiveXObject("WScript.Shell");
fso = new ActiveXObject("Scripting.FileSystemObject");
currentFolder = GetCurrentFolder();
}

/// Files ------------------------------------------------------

// getcurrent folder
function GetCurrentFolder() {

return fso.GetFolder(fso.GetFile(WScript.ScriptFullName).ParentFolder);
}


// delete files by mask
function DeleteFiles(mask) {
var files = FindFiles(mask);
var i;

Out("Deleting files", true);

for (i=0; i<files.length; i++) {
try {
fso.DeleteFile(files[i], deleteByForce);
deletedFiles ++;
} catch (e) {
WScript.echo(e.Message);
}
}

if (deletedFiles == 0) {
COut("No files were deleted.");
}
}


// find files
function FindFiles(mask) {
return GetFiles(currentFolder, mask);
}

// determine, if filename matches given mask
function MatchesMask(file, mask) {
return new RegExp(mask).test(file);
}

// get files in current folder & subfolders
function GetFiles(folder, mask) {
var result = new Array();
// do files in current folder
var files = new Enumerator(folder.Files);
for (; !files.atEnd(); files.moveNext()) {
if (MatchesMask(files.item(), mask)) {
result.push("" + files.item());
}
}
// do subfolders in current folder
var folders = new Enumerator(folder.SubFolders);
for (; !folders.atEnd(); folders.moveNext()) {
result = result.concat(GetFiles(folders.item(), mask));
}
return result;
}

/// Output ------------------------------------------------------

// output
function Out(text, useTimeOut) {
if (useTimeOut) {
useTimeOut = defaultTimeOut;
} else {
useTimeOut = -1;
}

if (consoleOnly) {
WScript.StdOut.WriteLine(text);
} else {
WSShell.Popup(text, useTimeOut, "Remove from SourceSafe");
}
}

// output
function COut(text, useTimeOut) {
if (useTimeOut) {
useTimeOut = defaultTimeOut;
} else {
useTimeOut = -1;
}

if (consoleOnly) {
WScript.StdOut.WriteLine(text);
}
}


/// Modify ------------------------------------------------------

// modify all files matching given mask
function ModifyFiles(mask) {

var files = FindFiles(mask);
var i;

Out("Modifying files", true);

for (i=0; i<files.length; i++) {
// WScript.echo(files[i]);
// try {
ModifyFile(fso.GetFile(files[i]));
modifiedFiles ++;
// } catch (e) {
// WScript.echo(e.description);
// }
}

if (modifiedFiles == 0) {
COut("No files were modified.");
}
}


function ModifyFile(file) {

switch (fso.GetExtensionName(file.Path).toLowerCase()) {
case "etp":
ModifyFileETP(file);
break;
case "sln":
ModifyFileSLN(file);
break;
case "csproj":
ModifyFileCSPROJ(file);
break;
}
}

function ReadFile(file) {
var stream = file.OpenAsTextStream(ForReading, CharSetDefault);
text = stream.ReadAll();
stream.Close();
return text;
}

function WriteFile(file, text) {
var ro = ((file.Attributes & AttrReadOnly) != 0);
if (ro) file.Attributes -= AttrReadOnly;
var stream = file.OpenAsTextStream(ForWriting, CharSetDefault);
stream.Write(text);
stream.Close();
if (ro) file.Attributes += AttrReadOnly;
}


// remove element <SourceControlSettings>...</SourceControlSettings>
function ModifyFileETP(file) {

var text;
var re1 = new RegExp('(\\s*<SourceControlSettings(\\s[^>]*)?>[.\\s\\S\\r\\n]*<\\/SourceControlSettings>)','m');

text = ReadFile(file);
text = text.replace(re1, "");
WriteFile(file, text);

}

// remove section GlobalSection(SourceCodeControl) = preSolution ... EndGlobalSection
function ModifyFileSLN(file) {

var text;
var re1 = new RegExp('(\\s*GlobalSection\\(SourceCodeControl\\))[.\\r\\n\\s\\S]*?EndGlobalSection','m');

text = ReadFile(file);
text = text.replace(re1, "");
WriteFile(file, text);

}

// remove lines with SccProjectName, SccLocalPath, SccAuxPath, SccProvider
function ModifyFileCSPROJ(file) {

var text;
var re1 = new RegExp('(^\\s*SccProjectName = .*$)', 'm');
var re2 = new RegExp('(^\\s*SccLocalPath = .*$)', 'm');
var re3 = new RegExp('(^\\s*SccAuxPath = .*$)', 'm');
var re4 = new RegExp('(^\\s*SccProvider = .*$)', 'm');

text = ReadFile(file);
text = text.replace(re1, "");
text = text.replace(re2, "");
text = text.replace(re3, "");
text = text.replace(re4, "");
WriteFile(file, text);

}

</code>

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.