DevMaster.net Forums
[[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]]

Go Back   DevMaster.net Forums > Site Discussions > Code & Snapshot Discussion
User Name
Password
Register FAQ Members List Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Search this Thread Display Modes
Old 09-26-2009, 08:00 AM   #1
Wernaeh
 
Posts: n/a
Default

Hello everyone :)

In the last months, I have been busy in a less-than-optimally organized C++ project.

This project involved work on a larger codebase that had absolutely no version control system available. All files were lying around in a semi-sorted directory structure on some intranet server. This, of course, made daily synching to this structure quite tedious. In particular, Visual Studio 2003 refuses to import recursive directories, and aborts importing if any files are already present within the solution.

Thus, I wrote the following macro.

It essentially discards all folders and files in selected projects, and rebuilds these from the solution directories.

During this process, new solution folders are created for each on-disk sub directory, so the source files remain nicely sorted in the IDE.

The macro has been tested in Visual Studio 2003, but should hopefully work in other VS versions with slight adaptions.

Note that the
Microsoft.VisualStudio.VCProject
and
Microsoft.VisualStudio.VCProjectEngine
references need to be added to the Visual Studio macro project for the macro to work.

Perhaps one or another might find it helpful, it's free for any use.

If anybody is interested in more integrated Visual Studio code, I also have a working COM-based C++ version of the macro available.

Cheers,
- Wernaeh



Code:
'========================================================================== ' Project generator main module. ' ' Copyright Wernaeh, Juli 2009 ' Free for any use. ' ' Contact: wernaeh@gmail.com '========================================================================== Option Explicit On Option Strict Off Imports EnvDTE Imports System.Diagnostics Imports Microsoft.VisualStudio.VCProject Imports Microsoft.VisualStudio.VCProjectEngine Public Module ProjectGen '========================================================================== ' Main project generation entry point '========================================================================== Sub regenerateMain() '====================================================================== ' Temporaries '====================================================================== ' Temporary loop variables Dim i As Integer Dim j As Integer ' Array with file extensions to be added Dim exts(8) As String exts(0) = ".c" exts(1) = ".cpp" exts(2) = ".h" exts(3) = ".def" exts(4) = ".ico" exts(5) = ".rc" exts(6) = ".flex" exts(7) = ".bat" '====================================================================== ' Determine project selection '====================================================================== ' Retrieve an array with selected projects Dim selectedprojects() As Project Dim selectedprojectcount As Integer selectedprojectcount = 0 For i = 1 To DTE.SelectedItems.Count If TypeOf DTE.SelectedItems.Item(i).Project Is Project Then selectedprojectcount += 1 Redim Preserve selectedprojects(selectedprojectcount - 1) selectedprojects(selectedprojectcount - 1) = _ DTE.SelectedItems.Item(i).Project End If Next ' Notify the user if no projects have been selected If selectedprojectcount = 0 Then MsgBox("Please select some projects for processing with the" & _ vbNewLine & _ "project generator within the solution view.", _ MsgBoxStyle.OKOnly, _ "Please select projects!") Return End If '====================================================================== ' Handle open documents '====================================================================== ' Prompt the user whether to save all open documents, if there ' are any. If DTE.Documents.Count > 0 Then Dim usersaveall As MsgBoxResult usersaveall = _ MsgBox("The project generator will close any open files." & _ vbNewLine & _ "Should these be saved now?", _ MsgBoxStyle.YesNoCancel, _ "Save open files now?") If usersaveall = MsgBoxResult.Cancel Return End If If usersaveall = MsgBoxResult.Yes DTE.Documents.SaveAll() End If DTE.Documents.CloseAll(vsSaveChanges.vsSaveChangesNo) End If '====================================================================== ' Regenerate projects '====================================================================== ' Now, regenerate each project For i = 0 To selectedprojectcount - 1 Dim project As Project project = selectedprojects(i) '================================================================== ' Regeneration prompt '================================================================== ' First, prompt whether regeneration is desired at all ' for a single project. Dim userregenerate As MsgBoxResult userregenerate = _ MsgBox("Should the project:" & vbNewLine & _ " " & selectedprojects(i).Name & vbNewLine & _ "be regenerated?" & vbNewLine & vbNewLine & _ "All file links and folders within the project will be removed," & _ vbNewLine & _ "and regenerated from the on-disk project structure.", _ MsgBoxStyle.YesNoCancel, _ "Really regenerate project: " & _ selectedprojects(i).Name & "?") If userregenerate = MsgBoxResult.Cancel Return End If If userregenerate = MsgBoxResult.No Goto NextProject End If '================================================================== ' Delete old project items '================================================================== ' Here, we just need to delete root project items. ' Since we do not know how indices change when deleting ' items, we do a copy to a save array first. Dim items() As ProjectItem Dim itemcount As Integer itemcount = project.ProjectItems.Count Redim items(itemcount - 1) For j = 1 To project.ProjectItems.Count items(j - 1) = project.ProjectItems.Item(j) Next For j = 0 To itemcount - 1 items(j).Remove() Next '================================================================== ' Regenerate project items from disk '================================================================== ' First, retrieve the project folder Dim projectfolder As String projectfolder = _ Left(project.FullName, InStrRev(project.FullName, "") - 1) ' Then, starting with the project folder, ' add all files into our project. ' Note there is a bug here, we can't use the common DTE interfaces ' for managing project folders for VC projects. ' Thus, we need to go for the C++ specific project type instead. Dim projectvc As VCProject projectvc = project.Object addItemsInFolder(projectfolder, "", projectvc, nothing, exts, 0) NextProject: Next '================================================================== ' Recursively close all treeview items '================================================================== Dim solutionexplorer As UIHierarchy solutionexplorer = _ DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Object For i = 1 To solutionexplorer.UIHierarchyItems.Count closeTreeViewHelper _ (solutionexplorer.UIHierarchyItems.Item(i), solutionexplorer, _ selectedprojects, selectedprojectcount, 0) Next End Sub '========================================================================== ' Directory management helper '========================================================================== Sub addItemsInFolder(basefolder As String, recursefolder As String, _ projectvc As VCProject, _ filtervc As VCFilter, exts() As String, _ depth As Integer) ' Put together base directory for searching, ' this needs to be the absolute directory within the ' project base directory. Dim searchfolder As String If recursefolder <> "" Then searchfolder = basefolder & "" & recursefolder Else searchfolder = basefolder End If ' First, handle files within the folder. Dim filename As String filename = Dir(searchfolder & "*") Do While (filename <> "") ' Expand file to relative path within project If recursefolder <> "" Then filename = recursefolder & "" & filename End If ' For each found file, ' check if it matches the provided extensions filter. Dim i As Integer For i = 0 To UBound(exts) If Right(filename, Len(exts(i))) = exts(i) Then ' File matches, so either add it to the filter ' or the project itself Dim file As VCFile If filtervc Is Nothing Then file = projectvc.AddFile(filename) Else file = filtervc.AddFile(filename) End If Goto filefinished End If Next filefinished: filename = Dir() Loop ' Load all folder directories into some array - ' otherwise recursion won't do, since Dir() does ' not have a search handle. Dim dirnames() As String Dim dirnamecount As Integer dirnamecount = 0 Dim dirname As String dirname = Dir(searchfolder & "*", vbDirectory) Do While (dirname <> "") If (GetAttr(searchfolder & "" & dirname) And vbDirectory) = _ vbDirectory Then dirnamecount += 1 Redim Preserve dirnames(dirnamecount - 1) dirnames(dirnamecount - 1) = dirname End If dirname = Dir() Loop ' Finally, create items for each folder, and ' recurse into subfolders. Dim j As Integer For j = 0 To dirnamecount - 1 Dim newfilter As VCFilter If filtervc Is Nothing Then newfilter = projectvc.AddFilter(dirnames(j)) Else newfilter = filtervc.AddFilter(dirnames(j)) End If Dim newrecurse As String If recursefolder <> "" Then newrecurse = recursefolder & "" & dirnames(j) Else newrecurse = dirnames(j) End If addItemsInFolder(basefolder, newrecurse, _ projectvc, newfilter, exts, depth + 1) Next End Sub '========================================================================== ' Tree view closing helper '========================================================================== Sub closeTreeViewHelper(hierarchyitem As UIHierarchyItem, _ solutionexplorer As UIHierarchy, _ selectedprojects() As Project, _ selectedprojectcount As Integer, _ depth As Integer) ' Helper call for closing all but the lowest hierarchy items. ' This is a little bit more complicated than one would assume: ' First, we need to check if the given item is a folder. ' This is done by checking its number of children - empty folders ' are ignored. ' Then, the folder is first expanded, so we may close children ' folders - otherwise closing children doesn't work. ' Then, the folder is closed again. ' Folder closing is performed by selecting the folder and ' then simulating a mouse click event. ' Test if we are a valid folder - i.e. we have children. ' For leaf entries (files), we just abort here. If hierarchyitem.UIHierarchyItems.Count = 0 Then Return End If ' On level 1 (projects level), we should ignore all projects ' that currently are not selected. ' This keeps the update from messing with unrelated projects. If depth = 1 Then Dim j As Integer For j = 0 To selectedprojectcount - 1 If selectedprojects(j) Is hierarchyitem.Object Then Goto projectselected End If Next ' Project not selected, so abort Return projectselected: End If ' We are a folder, so see if we are expanded, ' if we aren't do the expansion now. If Not hierarchyitem.UIHierarchyItems.Expanded Then hierarchyitem.Select(vsUISelectionType.vsUISelectionTypeSelect) solutionexplorer.DoDefaultAction() End If ' Recurse on all children items Dim i As Integer For i = 1 To hierarchyitem.UIHierarchyItems.Count closeTreeViewHelper _ (hierarchyitem.UIHierarchyItems.Item(i), solutionexplorer, _ selectedprojects, selectedprojectcount, depth + 1) Next ' Finally, unexpand our object again, ' but only if it is not on depth = 1, so root project folders and ' files remain visible. ' (Depth = 0 -> Solution, Depth = 1 -> Projects) If depth > 1 Then hierarchyitem.Select(vsUISelectionType.vsUISelectionTypeSelect) solutionexplorer.DoDefaultAction() End If End Sub End Module
  Reply With Quote
Old 09-28-2009, 01:38 AM   #2
Nick
Senior Member
 
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
Default Re: VS Project Synch macro

I don't get it. Shouldn't you instead just be using version control? TortoiseSVN and TortoiseGit are pretty awesome.
Nick is offline   Reply With Quote
Old 09-28-2009, 02:22 AM   #3
rouncer
Senior Member
 
rouncer's Avatar
 
Join Date: Mar 2006
Location: perth
Posts: 887
Default Re: VS Project Synch macro

wow, havent looked at basic in a while.
___________________________________________
Do you say-> "C plus plus" or "C increment."
rouncer is offline   Reply With Quote
Old 09-30-2009, 12:07 AM   #4
Wernaeh
Senior Member
 
Wernaeh's Avatar
 
Join Date: Aug 2005
Posts: 332
Default Re: VS Project Synch macro

Quote:
I don't get it. Shouldn't you instead just be using version control? TortoiseSVN and TortoiseGit are pretty awesome

Ya, it wasn't my decision not to use any version control - sadly, sometimes the people who decide are not those that should do so...

That's why I came up with the macro above - the only alternative was that I'd create my own local SVN repository, synch that to the coworkers network project folders on the one side, and to VS on the other.

Hope that makes it a little more clear

Cheers,
- Wernaeh
___________________________________________
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)
Wernaeh is offline   Reply With Quote
Old 09-30-2009, 03:47 AM   #5
Nick
Senior Member
 
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
Default Re: VS Project Synch macro

Ok, thanks for clarifying that. Still, it leaves a bad taste in my mouth to suggest a neat solution to a problem that actually really asks for a totally different solution: a hammer to slam on the heads of the people who decided not to use source control.

I seriously suggest to try and convince every possible coworker of using SVN, and create some momentum to demand server space for it. There's no excuse for not using version control.
Nick is offline   Reply With Quote
Old 09-30-2009, 02:36 PM   #6
Wernaeh
Senior Member
 
Wernaeh's Avatar
 
Join Date: Aug 2005
Posts: 332
Default Re: VS Project Synch macro

... great... now I want a hammer

Cheers,
- Wernaeh
___________________________________________
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)
Wernaeh is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Forum Jump


All times are GMT -7. The time now is 08:37 AM.


Powered by vBulletin
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.