Tech

22 Articles

Loading Specific Versions of .NET Assemblies From the GAC Based on the Assembly Information in a .NET DLL – Visual Basic Example Code

By default the latest version of an assembly is loaded from the GAC (Global Assembly Cache) when the assembly is instantiated. While working on a side project the need arose to load older versions of the assembly without hard coding the assembly versions. The answer, load the existing assembly library from the assembly DLL and interrogate it to find the assembly information. Then ask the GAC to provide a handle to the specific object. The result allows multiple versions of the same assembly to be loaded loaded at the same time.

The Visual Basic .NET example code below loads SampleAppV1\DotNetLibrary.DLL and AnotherSampleAppV2\DotNetLibrary.DLL which are different versions of the same assembly.

'Load assembly using reflection from the file specified so we can get information about it
Dim DLLAssemblyInfo As System.Reflection.Assembly
DLLAssemblyInfo = System.Reflection.Assembly.LoadFrom("\\\\appserver.company.int\\SampleAppV1\\DotNetLibrary.DLL")

'Now load the assembly from the GAC using the information in the file. 
Dim GACDLL As System.Reflection.Assembly
GACDLL = System.Reflection.Assembly.Load(AssemblyInfo.FullName, DLLAssemblyInfo.Evidence)
'Load the second version of the same assembly from the newer application
Dim DLLAssemblyInfoV2 As System.Reflection.Assembly
DLLAssemblyInfoV2 = System.Reflection.Assembly.LoadFrom("\\\\appserver.company.int\\AnotherSampleAppV2\\DotNetLibrary.DLL")
'Again, use the DLL information from the assembly file to load the assembly from the GAC
Dim GACDLLv2 As System.Reflection.Assembly
GACDLLv2 = System.Reflection.Assembly.Load(AssemblyInfoV2.FullName, DLLAssemblyInfoV2.Evidence)
'At this point in the code we have references to both assemblies loaded from the GAC. The next step is to instantiate an object from each of the references.
'Get an MyAssembly.Library from the old version and run the version method
Dim GACDLLType As Type = GACDLL.GetType("MyAssembly.Library")
Dim MyLibV1 As Object = Activator.CreateInstance(GACDLLType)
Dim v1 As String
v1 = MyLibV1.Version
'Finally, do the same and get the new MyAssembly.Library
Dim GACDLLTypeV2 As Type = GACDLLV2.GetType("MyAssembly.Library")
Dim MyLibV2 As Object = Activator.CreateInstance(GACDLLTypeV2)
Dim v2 As String
v2 = MyLibV2.Version

The variables v1 and v2 were both retrieved from the MyAssembly.Library.Version() method but the variables will not contain the same value because different versions of the assembly were loaded from the GAC during the System.Reflection.Assembly.Load() call.

Why not just load the assembly from each of the DLL files instead of the GAC? Security restrictions prevented untrusted assemblies from being loaded over the network. A possible work around would be to trust the network location or sign the assemblies and trust the signer but that remains for another posting.

Excel 2007 Insert Column Slowed by Google Desktop

On a spring afternoon a call came in from a very exasperated client. “Why is my excel coming to a crashing halt? Is 120,000+ rows too many in a spreadsheet? How come it keeps locking up!” He spoke with the unmistakable tone that indicated his computer was about to take flight from his second story window.

The sheet was only 17MB in size with about 120,000 rows, a few pivot tables, and no complex formulas. Every time he would insert a new empty column on the main sheet Excel would come to a screeching halt. After about 10 minutes the operation would complete. Turning off automatic calculations and starting excel with the /safe switch resulted in no change of behavior.

After some creative Google searches I came across a post about Google Desktop slowing down excel. With nothing to to lose Google Desktop was un-installed and miraculously the insert column took 1 second instead of 1o minutes!

Further examination revealed another blog posting that further explained the underlying problem.

Ironic, isn’t it? Searching Google revealed Google Desktop to be the culprit of the slow down.

How to Launch a WSH VBScript as Administrator in Windows 7 and Vista

The example below launches a VB script as administrator on Windows 7 and Vista regardless if the context menu contains the “Run as administrator” option. Registry tweaks exist to add the run as administrator option to the context menu for .vbs files but this creates complications if the script is distributed to other people.

When the script below is executed it checks to see if it was passed a command line argument named “elevated”. If it is not found the script recursively calls itself passing the elevated command line argument and requests to be run as administrator. The user is prompted to confirm the action and the restricted script exits leaving the escalated administrator script running. When the user grants permission the elevated argument is found and the script changes back from the %System32% working directory to the script where the script is located.

If WScript.Arguments.Named.Exists(“elevated”) = False Then
‘Launch the script again as administrator
CreateObject(“Shell.Application”).ShellExecute “wscript.exe”, “””” & WScript.ScriptFullName & “”” /elevated”, “”, “runas”, 1
WScript.Quit
Else
‘Change the working directory from the system32 folder back to the script’s folder.
Set oShell = CreateObject(“WScript.Shell”)
oShell.CurrentDirectory = CreateObject(“Scripting.FileSystemObject”).GetParentFolderName(WScript.ScriptFullName)
MsgBox “Now running with elevated permissions”
End If
If WScript.Arguments.Named.Exists("elevated") = False Then
	'Launch the script again as administrator
	CreateObject("Shell.Application").ShellExecute "wscript.exe", """" & WScript.ScriptFullName & """ /elevated", "", "runas", 1
	WScript.Quit
Else
	'Change the working directory from the system32 folder back to the script's folder.
	Set oShell = CreateObject("WScript.Shell")
	oShell.CurrentDirectory = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName)
	MsgBox "Now running with elevated permissions"
End If

IIS 7 AppCmd Example – Changing Default ISAPI Settings

The default ISAPI settings in IIS 7 and later reference %windir% in the path. Changing these settings with a script using AppCmd requires special handling of the % character because it is a reserved character in the AppCmd utility. The % character is and operator to indicate the start of a Unicode character value.

To set values with extended characters using the IIS 7 AppCmd utility you must specify the Unicode value.

For example, to change the value of an ISAPI restriction from true to false on a setting with a relative path issue the command:

appcmd set config /section:system.webServer/security/isapiCgiRestriction /[path=’%u0025windir%u0025\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll”‘].allowed:false

The sequence %u0025 is the Unicode value of the % character.

r%u0025\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll”‘].allowed:true

CounterPath Corporation EyeBeam License Maintenance Link

For those of you who use the eyeBeam VoIP phone client and can’t find the license account maintenance page on the couterpath.com website here it is:

https://secure.counterpath.com/Store/CounterPath/Members/Account/ListLicenses.aspx

The page will allow you to login and re-assign or revoke licenses. This is especially useful if you happen to sift between a home desktop PC and laptop.

I’ve been happily using eyeBeam for almost a year with my BroadVoice SIP accounts until CounterPath changed the license mechanism. It is almost impossible to find the license maintenance link on the main CounterPath page. The client doesn’t link to the maintenance site either. Argh!

I am not affiliated with CounterPath other than I use eyeBeam.