0

By the property name (Specific Version), I would think that if an assembly complied, then later a newer DLL is dropped in, then if resolved to that DLL it would still load and work even though it has a different version than the original DLL that was referenced. I am using VS 2022. This has worked in the past, so I am not sure if something has changed.

Part of my assumption was based on this SO thread. The original thread is over 8 years old and the most recent comment which might be my issue said open a new topic. :-) How exactly does the "Specific Version" property of an assembly reference work in Visual Studio? The screenshot is for context, to make sure the property I am talking about.

Let me try to anticipate some of the questions. This may be in the more info than you care. This exe is running on over 900 devices. I have used Xcopy app management for a long time. All of the apps are in a few directories. I have a resolve function for DLL to keep from fighting the GAC, cache, etc. Basically, it is a handler for the " AppDomain.CurrentDomain.AssemblyResolve". I will include the code snippet, basically it just calls itself recursively through certain directories till the DLL is found. This works for the most part. They can not find the DLL error that happens even before the 'Sub Main()' starts. I guess since the app is in the same directory as the DLL, it assumes the DLL is not right because of the DLL version. Just guessing. Of course, if I remove all the DLL references and then re-add them works. The reason why I was hoping is that the set "Specific Version" would work, I was hoping to avoid recompiling all the apps that reference the DLL(s).

Show the property I was asking about.

This code is what sets up the handler.

        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ResolveAssembly

This is what is executed.

        Public Function ResolveAssembly(ByVal sender As Object, ByVal args As ResolveEventArgs, Optional ByVal pPath As String = Nothing) As Reflection.Assembly
        'BuildLogOutput("ResolveAssembly - " & args.Name)
        Dim resourceName As String = New Reflection.AssemblyName(args.Name).Name & ".dll"
        If resourceName.Contains("&") Then Return Nothing
        If resourceName.ToLower.Contains(".resources.") Then Return Nothing
        Dim AssemblyPath As String = ""
        pPath = DLLSearchPath(pPath)
        Dim returnedassembly As Reflection.Assembly = Nothing
        If pPath.Length > 0 Then
            AssemblyPath = Path.Combine(pPath, resourceName)
            If IO.File.Exists(AssemblyPath) Then
                returnedassembly = Reflection.Assembly.LoadFrom(AssemblyPath)
            Else
                returnedassembly = ResolveAssembly(sender, args, pPath)
            End If
        Else
            Throw New IO.FileNotFoundException("ResolveAssembly - Could not load Assembly: " & resourceName, AssemblyPath)
        End If
        If returnedassembly Is Nothing Then
            Throw New Exception("ResolveAssembly - Unexpected failure to load: " & AssemblyPath)
        End If
        Return returnedassembly
    End Function

        Public Function DLLSearchPath(Optional ByVal LastPath As String = "") As String
        Dim PathList() As String = Environment.GetEnvironmentVariable("Path").Split(";"c)
        If LastPath = "" Then
            Return AppPath
        ElseIf LastPath = AppPath Then
            Return SystemPath
        ElseIf LastPath = SystemPath Then
            Return "c:\user\braums\com"
        ElseIf LastPath = "c:\user\braums\com" Then
            If PathList.Length > 0 Then
                Return PathList(0)
            Else
                Return ""
            End If
        Else
            For xLoop As Integer = 0 To PathList.Count - 1
                If LastPath = PathList(xLoop) Then
                    If xLoop + 1 <= PathList.Count - 1 Then
                        If PathList(xLoop + 1).ToLower = SystemPath.ToLower OrElse
                        PathList(xLoop + 1).ToLower = "c:\user\braums\com" OrElse
                        PathList(xLoop + 1).ToLower = AppPath.ToLower Then
                            LastPath = PathList(xLoop + 1)
                            Continue For
                        End If
                        Return PathList(xLoop + 1)
                    End If
                End If
            Next
        End If
        Return ""
    End Function
Paul
  • 101
  • 2
  • 10
  • 1
    If you think the Specific Version property is not behaving as you expected, you can go to the [Visual Studio Developer Community](https://developercommunity.visualstudio.com/home) for feedback. – Jiachen Li-MSFT May 19 '23 at 09:32
  • @JiachenLi-MSFT Thanks for the idea. Here is the link to my report. https://developercommunity.visualstudio.com/t/VS-2022-Referenced-dll-Specific-Version/10369449 I am open to any suggestions to make it more clear. I still would like to understand it, for now, I just going to have to update and start looking and compiling. :-) – Paul May 19 '23 at 12:50
  • My understanding and expectation is that `SpecificVersion` means it matches on the version number *exactly*. I think this is a good way for it to behave. A newer version is not necessarily compatible. Arguably, following semver, a non-major version bump should be allowed, but under no circumstances would I want a reference to 5.0.1 to successfully bind to a file versioned 6.x. – Craig May 19 '23 at 14:27
  • @Craig if set to true, then I agree, so if set to false then I would expect it not to force the version check. The DLL is a purchase library and I am in control of the calling assembly, so I know it would be ok. If you are going to force the version check why give it as an option? – Paul May 22 '23 at 12:51
  • @Paul if it's set to false, in my experience, there is no version check whatsoever on the library that is directly referenced. The library itself may have specific version dependencies, and you may get exceptions if you reference something that isn't in the version of the library that is present. – Craig May 22 '23 at 13:47

1 Answers1

0

They were able to finally able to help me connect the dots in the developer community for VS.

Again, here is the link. https://developercommunity.visualstudio.com/t/VS-2022-Referenced-dll-Specific-Version/10369449#T-ND10386781

I thought I would try and summarize it here for anyone stumbling across this thread. That way they don't have to chase links around.

First, if I had really understood the thread ... How exactly does the "Specific Version" property of an assembly reference work in Visual Studio? It had the answer. What was confusing me, in my wrong assumption that setting the "Specific Version" (SV) to false, would release the compiler from checking the version, which does work as I did expect and would also keep the runtime from checking the version. When I read it has to be set at compile time to take effect was a no-brainer. It does release the compiler from enforcing the check, but whatever version was compiled is what is used at runtime no matter what the SV is set to. In hindsight, I feel embarrassed, or maybe it was just wishful thinking not wanting to recompile with newer dll's from the vendor. What even got me off on this tangent, is I'm pretty sure I have loaded newer dlls without recompiling. Either I am not remembering correctly or it changed in some VisualStudio version.

For those who want to see the detail: Here are the steps I did to connect the dots. :-)

I have my dll’s referenced to the path ‘\ProductionLibs\ProductionLibs\EO. WebObjects’ Then I have two other paths

\ProductionLibs\ProductionLibs\EO. WebObjects_V1 \ProductionLibs\ProductionLibs\EO. WebObjects_V2 Now I can move either V1 or V2 into the actual reference path. The dll’s are all named the same. So I have “Specific Version” (SV) set to false on all references. Testing with V1 I move V1 into the reference dir and compile it without errors. When I try and execute the exe with the V2 dll’s I get the missing dll error.

Testing with V2 Move the V2 into the reference dir and compile, it still compiles without error. This time the exe executes with the V2 dll’s. As expected I might add.

Testing by moving V1 into the reference dir and setting the SV to true. Move the V2 into the reference dir and the compile fails. As I set each reference SP to false, the version changes to V2 Now it will compile. Move V1 back into the reference dir, the reference stays V2, and it compiles. close solution and reopen, now the references show V1. move V2 back into reference dir, references still show V1 and it compiles close solution and reopened, now references show V2.

Paul
  • 101
  • 2
  • 10