HOWTO: determine BITS version installed?

Topics: Updater Application Block
Aug 21, 2004 at 11:57 AM
originally posted by: eugeniop

The update published in our GotDotNet Workspace for Updater Application Block fixed the BITS based downloader included in the block. It doesn't include any intelligence to determine which the installed version of BITS is and act accodringly. A smarter downloader could determine at runtime which the installed version is in a particular desktop and then decide whether or not to use the new APIs available. Here are some code snippets that may help doing this:



using System;
using System.Runtime.InteropServices;

namespace Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders
{
public class BITSVersionHelper
{

//2.0
ComImport, Guid("6d18ad12-bde3-4393-b311-099c346e6df9")
internal sealed class BITS2_0
{
}
//1.5
ComImport, Guid("f087771f-d74f-4c1a-bb8a-e16aca9124ea")
internal sealed class BITS1_5
{
}
//1.0
ComImport, Guid("4991d34b-80a1-4291-83b6-3328366b9097")
internal sealed class BITS1_0
{
}

private static bool BITS10Installed;
private static bool BITS15Installed;
private static bool BITS20Installed;

public static bool IsVersion10Installed
{
get { return BITS10Installed; }
}

public static bool IsVersion15Installed
{
get { return BITS15Installed; }
}

public static bool IsVersion20Installed
{
get { return BITS20Installed; }
}

static BITSVersionHelper()
{
try
{
BITS10 bits10 = new BITS1_0();
BITS10Installed = true;
}
catch
{
BITS10Installed = false;
}

try
{
BITS15 bits15 = new BITS1_5();
BITS15Installed = true;
}
catch
{
BITS15Installed = false;
}
try
{
BITS20 bits20 = new BITS2_0();
BITS20Installed = true;
}
catch
{
BITS20Installed = false;
}
}

private BITSVersionHelper()
{}
}
}

You can the call this helper class like:


if( BITSVersionHelper.IsVersion20Installed )
{
// Do stuff with BITS 2.0
}

Sep 2, 2004 at 11:33 AM
originally posted by: pccoxDMR

OK, Eugenio...what am I missing?

I took your example and added it to my assembly (granted, I converted to VB.NET first). I added a call in the CreateCopyJob() method of the BITSDownloader class to BITSVersionHelper.IsVersion20Installed.

When my updater runs, the process hangs up, and I get the following error in my Updater log:

-----------
BITSDownloader.CreateCopyJob :
The BITS downloader experienced an unexpected error. It may have been asked to check job status for a job ID that no longer exists,
or a job that was canceled. The jobID was '88131e96-de8d-4f3a-ba4a-ad250ba6470d', the job name was 'Updater job.', and the description was 'Updater: Download the Server XML File.'.
ERROR: The type initializer for "Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSVersionHelper" threw an exception.
STACK: at Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSVersionHelper.get_IsVersion20Installed()
at Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSDownloader.CreateCopyJob(IBackgroundCopyManager& copyManager, IBackgroundCopyJob& copyJob, Guid& jobID, String jobNameKey, String jobDescriptionKey)
ERROR: Could not load type BITS1_0 from assembly Microsoft.ApplicationBlocks.ApplicationUpdater, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b923d8046cecdb27.
STACK: at Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSVersionHelper..cctor()
-----------

Any ideas as to why this is happening? Should the Try..Catch blocks in the Class Constructor handle the error if the v1.0 GUID isn't available? I've added TraceWrite statements to those Try..Catch blocks for additional feedback, but there are no entries in my log from those, so I don't know that it's even getting there.

Any thoughts, great wizard?

Paul C.
Sep 2, 2004 at 2:33 PM
originally posted by: eugeniop

After posting the C# version of this I tried a VB.NET version too with the intention to publish it aswell. However, I faced the same problem as you do. The try/catch doens't seem to capture the exception when the typeloading fails.

I haven't spent much time since then, but I will. I couldn't figure out why it fails as my code is an exact copy of the C# version (which worked just fine). I couldn't even debug it. (as in your example, the code seems never to be executed)

But, at the same time, I'm not an expert VB.NET programmer.

I'll do some internal research. In the meantime, if you find anything please send us a message.

Thanks!
Eugeniop
Sep 3, 2004 at 8:20 AM
originally posted by: pccoxDMR

Well, I don't know.....

I tried a number of different things, including using the Type.GetTypeFromCLSID method, but that didn't work, either. I even tried compiling the BITSVersionHelper class into a separate C# assembly and referencing from my VB UAB assembly, but that still didn't work (strangely, it wouldn't create any of the three types, even though I know BITS 2.0 is on my machine).

Anyway, as a workaround, I ended up adding a Try...Catch block around the call to VerifyAndSetBackgroundCopyJobCredentials as follows:

-----------
' Set credentials on the job
Try
VerifyAndSetBackgroundCopyJobCredentials(copyJob)
Catch bcwe As BitsWrapper.BitsCredentialWrapperException
ApplicationUpdateManager.TraceWrite(bcwe, "BITSDownloader.CreateCopyJob")
End Try
-----------

This doesn't detect the version number, but it does work on our machines that still have the older BITS version installed (don't ask me why they haven't updated) to trap only the special Exception type, yet continue with the download, while still authenticating on machines with BITS 2.0.

It's not pretty and I would like rather use something like your solution, but at least it works for now....

grrrr......computers......

Paul C.
Sep 3, 2004 at 8:52 AM
originally posted by: eugeniop

Here's a VB version of the detection code that works (Thanks to my colleage Jonathan Wanagel). The reason the one to one translation doesn't work is that VB tries to proactively instantiate the referenced types, instead of doing it lazily as C# does.

Imports System.Runtime.InteropServices

Public Class BITSVersionHelper
'2.0
<ComImport(), Guid("6d18ad12-bde3-4393-b311-099c346e6df9")> _
Friend NotInheritable Class BITS2_0
End Class

'1.5
<ComImport(), Guid("f087771f-d74f-4c1a-bb8a-e16aca9124ea")> _
Friend NotInheritable Class BITS1_5
End Class

'1.0
<ComImport(), Guid("4991d34b-80a1-4291-83b6-3328366b9097")> _
Friend NotInheritable Class BITS1_0
End Class

Private Shared BITS10Installed As Boolean
Private Shared BITS15Installed As Boolean
Private Shared BITS20Installed As Boolean

Public Shared ReadOnly Property IsVersion10Installed() As Boolean
Get
Return BITS10Installed
End Get
End Property

Public Shared ReadOnly Property IsVersion15Installed() As Boolean
Get
Return BITS15Installed
End Get
End Property

Public Shared ReadOnly Property IsVersion20Installed() As Boolean
Get
Return BITS20Installed
End Get
End Property

Private Shared Sub TestBITS10()
Dim bits As BITS10 = New BITS10
End Sub

Private Shared Sub TestBITS15()
Dim bits As BITS15 = New BITS15
End Sub

Private Shared Sub TestBITS20()
Dim bits As BITS20 = New BITS20
End Sub

Shared Sub New()
Try
TestBITS10()
BITS10Installed = True
Catch
BITS10Installed = False
End Try

Try
TestBITS15()
BITS15Installed = True
Catch
BITS15Installed = False
End Try

Try
TestBITS20()
BITS20Installed = True
Catch
BITS20Installed = False
End Try
End Sub

Private Sub New()
End Sub

End Class
Sep 7, 2004 at 12:08 AM
originally posted by: viet2k

Hi,

I'm tying to run the vb version of this code, and it returns false on all version of BITS. Please can you advise?


Best Regards,


Viet
Sep 7, 2004 at 3:15 PM
originally posted by: eugeniop

can you describe your environment? xp? w2k? which service pack?

thanks
Sep 10, 2004 at 12:37 AM
originally posted by: viet2k

Hi,

I running Win2k SP3.


Thanks