(You can choose or or both)

Tuesday, October 30, 2007

Teddies in pyjamas ... code (UPDATED)


(L'autre jour, tout d'un coup, Kalia a eu l'idée de mettre tous ces nounours en pyjama...).

Tech blog aujourd'hui.

(UPDATE 2008-09-05: Il y a une meilleure version, je mettrais ici bientôt)
Visual Studio Macros to update file to Project references and vice versa
Si vous avez une solution avec 5 projets, chacun qui référence un dll externe, puis vous voulez ajouter le projet de la référence dans la solution, vous êtes obligé de mettre à jour à la main. Pire, si vous enlevez un projet, les références sont perdues - dommage !

Ces deux macros peuvent être utilisés pour automatiser la mise à jour des deux actions. Il faut les invoquer depuis 'EnvironmentEvents' pour les Solution events ProjectAdded et ProjectRemoved.

(The other day, Kalia suddenly decided she was going to put pyjamas on all her teddies...).

Sorry, programmer's blog today.

(UPDATE 2008-09-05: I have a better version which I will post here shortly)
Automatically update visual studio references from file to projet and vice versa.
If you work with solutions with lots of projects and external dependencies, you often want to swap in or out projects depending on trade offs between load time and debugging. If you have 5 projects in your solution which all reference the same dll, when you add the project in to the solution, you have to update (delete&add) each reference manually. Even worse when you remove the project - all the references are deleted, you don't even know where to add them!

These two macros are designed to automatically detect and update all references in projects (including the included project), when adding and removing projects to a solution. They have to be wired in to the Visual Studio events Solution_ProjectAdded and Solution_ProjectRemoved.

Private Sub SolutionEvents_ProjectAdded(ByVal Project As EnvDTE.Project) Handles SolutionEvents.ProjectAdded
Call HandleAddProject(Project)
End Sub

Private Sub SolutionEvents_ProjectRemoved(ByVal Project As EnvDTE.Project) Handles SolutionEvents.ProjectRemoved
Call HandleRemoveProject(Project)
End Sub

'Called on add project - cycle through other projects, replace references if found
Sub HandleAddProject(ByVal Project As EnvDTE.Project)
Dim proj As EnvDTE.Project
Dim vsproject As VSLangProj.VSProject
Dim refItem As VSLangProj.Reference

Call WriteToOutputWindow("---- Handle file references on adding " & Project.Name & " ----")

For Each proj In DTE.Solution.Projects
'Check for this project in new project's references
vsproject = Project.Object
For Each refItem In vsproject.References
If refItem.Name = proj.Name Then
refItem.Remove()
refItem = vsproject.References.AddProject(proj)
refItem.CopyLocal = False
Call WriteToOutputWindow("Changed file reference to project reference for " & refItem.Name & " in project " & Project.Name)
End If
Next

'check for new project in the project references
If Not proj.Object Is Nothing And Not proj Is Project Then
vsproject = proj.Object
For Each refItem In vsproject.References
If refItem.Name = Project.Name Then
refItem.Remove() ' remove file reference
refItem = vsproject.References.AddProject(Project) ' add project reference
refItem.CopyLocal = False
Call WriteToOutputWindow("Changed file reference to project reference for " & Project.Name & " in project " & proj.Name)
Exit For ' go to next project
End If
Next
End If
Next
End Sub

'Called on remove project - attempt to replace project reference with file reference, using project reference paths
Sub HandleRemoveProject(ByVal Project As EnvDTE.Project)
Dim proj As EnvDTE.Project
Dim vsproject As VSLangProj.VSProject
Dim refItem As VSLangProj.Reference
Dim arrRefPath() As String
Dim i As Integer
Dim fileRefPath As String

Call WriteToOutputWindow("---- Handle project references before removing " & Project.Name & " ----")

'Check all references for project we are removing - remove any project references
vsproject = Project.Object
For Each refItem In vsproject.References
If Not refItem.SourceProject Is Nothing Then
Call ChangeProjRefToFileRef(refItem, vsproject)
End If
Next

'Check all other projects in solution
For Each proj In DTE.Solution.Projects
If Not proj.Object Is Nothing And Not proj Is Project Then
vsproject = proj.Object

'Check all the refences in the project
For Each refItem In vsproject.References
' If references the project we are removing
If refItem.Name = Project.Name Then
Call ChangeProjRefToFileRef(refItem, vsproject)
Exit For ' goto next project
End If
Next ' reference
End If
Next 'project
End Sub

'For given project, check all references. If broken project references found, attempt to transform to file references
' This method is not currently used, but could be wired up to a context menu, if I could work out how...

Sub RepairBrokenProjRef(ByVal Project As EnvDTE.Project)
Dim vsproject As VSLangProj.VSProject
Dim refItem As VSLangProj.Reference
Dim arrRefPath() As String
Dim i As Integer
Dim fileRefPath As String
Dim refName As String


vsproject = Project.Object
For Each refItem In vsproject.References
' If path is empty, this reference is broken, we can try to find it in reference path
If refItem.Path = "" Then
Call ChangeProjRefToFileRef(refItem, vsproject)
End If
Next ' reference
End Sub

' Remove reference to ReferencedProjectName from references,
' Attempt to locate corresponding dll in referencePath of ReferencingProject
' If found, add to references
Sub ChangeProjRefToFileRef(ByRef refItem As VSLangProj.Reference, ByRef ReferencingProject As VSLangProj.VSProject)
Dim ReferencedProjectName As String
Dim arrRefPath() As String
Dim i As Integer
Dim fileRefPath As String

' Get project name form reference (just for readability)
ReferencedProjectName = refItem.Name

' On Error Resume Next
'Split reference path (can be multiple, or potentially also empty)
arrRefPath = Microsoft.VisualBasic.Strings.Split(ReferencingProject.Project.Properties.Item("ReferencePath").Value, ";")

For i = 0 To UBound(arrRefPath)
fileRefPath = arrRefPath(i) & ReferencedProjectName & ".dll"
If System.IO.File.Exists(fileRefPath) Then
Call refItem.Remove() 'only remove it if we can find a replacement.
Call ReferencingProject.References.Add(fileRefPath)
Call WriteToOutputWindow("Changed project reference to file reference for " & ReferencedProjectName & " in project " & ReferencingProject.Project.Name)
Exit For ' reference path worked, exit
End If
Next

End Sub

Public Sub WriteToOutputWindow(ByVal Msg As String)
Dim owPane As OutputWindowPane

Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
Dim ow As OutputWindow = win.Object
Try
owPane = ow.OutputWindowPanes.Item("General")
owPane.Activate()
owPane.OutputString(Msg & vbCrLf)
Catch
End Try
End Sub

No comments yet :