It is time again for something completly off-topic.

In februari I read this msdn article regarding startup time of .Net applications. One of the problems is that every DLL you create in VS will have the same baseaddress causing the LoadImage api to relocate you're dll in memory and run a 'fixup' routine to change the memory address to match for the new location. You can read this blog from Raymond Chen for some background.

Well that is fixed then, just add a baseaddress for each dll. On that small demo project that will work but for your multi-layer, multi assemblies projects this will be a cumbersome task. Reading through all the available information there is some extra info to take into account. First of all baseAdress start on 64K boundaries and should map into empty process memory space. Determing what empty process space is cannot be calculated during compile time. Only after all dlls are loaded in the process you can run listdlls to get a hint if rebasing was needed. Running listdlls -r [pid] will also show you that some dlls are loaded in your process which depend on the software configuration of the pc. For example the virusscanner software loads a dll in the process on my machine. This makes the problem worse. Not only is it not possible to calculate a rebase free memory space for compile time but also not for all runtime configurations.

Given this I decided to just provide a macro that sets the baseaddress for all your dll projects in your solution. I know this is far from a 100% solution but at least it should fix the rebases on our development box. The macro does not yet take into account definitely blocked addresses but on the next rainy weekend I might improve this macro.

Remember that the BaseAdress setting is bound to the build configuration. You have to run the macro at least for your Debug and Relase config.

In the attachment you find the zip file with the VS Macro.

Imports System
Imports System.IO
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics

Public Module BaseAddress

Sub SetBaseAddress()
Const DllKind As String = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
Const ClassLibrary As String = "2"
Const RebaseTop As Long = &H7F000000
Const DefaultFileLength As Long = &H1000
Dim project As Project

Dim startBase As Long = RebaseTop

If DTE.ActiveSolutionProjects.Length = 0 Then
Exit Sub
End If

For Each project In DTE.Solution.Projects

' only dlls require a base adress
If (project.Kind = DllKind) Then

If (project.Properties.Item("OutputType").Value = ClassLibrary) Then

' this is the initial poor mans memory size calc
' we just taken the filesize of the dll
' so compile your solution before running this macro
Dim CompleteOutputFile As String
CompleteOutputFile = project.Properties.Item("FullPath").Value + _
project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value + _
project.Properties.Item("OutputFileName").Value
Dim opfileLength As Long = DefaultFileLength
If (File.Exists(CompleteOutputFile)) Then
Dim fi As FileInfo = New FileInfo(CompleteOutputFile)
opfileLength = fi.Length
End If
' base adress on 64k boundaries
startBase = startBase - opfileLength
startBase = startBase >> 16 << 16 ' rotate right 16 times and and left 16 times
Debug.Print(String.Format("name:{0} address:{1:x}", project.Name, startBase))
' store the calculated baseadress in the project BaseAddress
' remember this is a Compile config setting. So rerun this if you compile for Release
project.ConfigurationManager.ActiveConfiguration.Properties.Item("BaseAddress").let_Value(startBase)
End If
End If
Next
End Sub
End Module