locked
How to deploy LOB app with legacy DLLs that depend on specific SxS MSVCRT?

    Question

  • I have a 3rd party dll linked against MSVCRT90.dll and friends (MFC90u.dll)

    Running dependency walker on the dll reveals that it can find the SxS Dlls for one MSVCRT90.DLL

    How do I interpret this result and how do I deploy my 3rd party DLL with my LOB (Its not published in the store)?

    I tried to include the MSVC*.dlls and MFC90.dll (with manifests) in my packages root folder. I then load the dll using LoadPackagedLibrary. That works on some machines, but on some it displays an error message that the Visual Studio Runtime has been initialized incorrectly.
    • Edited by pkursawe Friday, June 13, 2014 10:18 PM
    Friday, June 13, 2014 10:11 PM

Answers

  • So, after looking into the msvcrt source code I found my solution. To code that leads to the anoying "C Runtime Error R6034" message and abort of the runtime loading is in crtlib.c _check_manifest

    Starting with VS2005 MSFT tried (and failed) to solve the "DLL hell" by enforcing the C-Runtime to be only loaded indirectly though the Win32 Loader depending on the applications process manifest declarations. They wanted to prevent developers to LoadLibrary("mscvr80.dll"). The routine checks various conditions under which it permits the runtime to be loaded. As of the comment at the beginning of the function:

    Notice that this is not a security feature: it's an helper which will try (as much as possible) to discourage the practice of not using a manifest to load the crt dll.

    However in Modern Apps, especially ones that are hosted in wwahost.exe, you have no influence of the manifest of the process nor its activation context (which I think is the culprit here). Both conditions checked by the _check_manifest function. So whatever I tried my 3rd party DLL could not load the msvcr80.dll (in the apps deployment root folder) properly.

    Now the hack: Luckily for me, MSFT had to short-circuit its own check routine in case a "Profile Guided Optimization" is performed by comment in the routine: 

    // If pogo-instrumented mscoree is loaded, it has
    // a dependency on pgort80.dll. However, the manifest
    // in pgort80.dll is ignored.

    and it then returns TRUE from the check routine.

    So all I had to do now was to create 2 dummy DLLs with no code, nor entry point (clocking in at 2560 bytes) named "mscoree.dll" and "pgort80.dll", load them into my apps process by using LoadPackagedLibrary and msvcr80.dll finally successfully loaded as a dependency of my 3rd party DLL.

    I think my hack is worthy to be mentioned in "The Old New Thing" one day, but since MSFT takes care of backward-compatibility I can safely assume that this solution will run stable until MSFT comes to senses and supports such scenarios out of the box for LOB apps in the future.

    Thanks everyone who tried to help to solve this issue!

     
    • Marked as answer by pkursawe Wednesday, November 12, 2014 9:15 AM
    • Edited by pkursawe Wednesday, November 12, 2014 1:53 PM
    Wednesday, November 12, 2014 9:15 AM

All replies

  • You need to use libraries which are valid for Windows Store apps.

    To use legacy libraries in a side-loaded app check out brokered Windows Runtime Components.

    Saturday, June 14, 2014 5:28 AM
    Owner
  • nah, I had this setup working just well. No brokered Runtime Components needed. Why make things so complicated.

    I just deployed the legacy DLLs with my app, loaded them via LoadPackagedLibrary and they just worked, despite them using a lot of "restricted" API calls. Of course for file system operations I need to feed them special paths they have access too. No problem so far.

    It all just works, because Windows does not do runtime checks of called API. So the legacy DLLs are even able to open sound input streams using the Winmm library. Of course I have to give them permission via the app first, so that level the APIs are protected.

    Now on some customer devices I am getting a "C Runtime Error R6034" http://msdn.microsoft.com/en-us/library/ms235560(v=vs.90).aspx and on all my machines (none of them have VS installed, its plain win8.1 Pro) all just works fine. Any idea what could cause this?

    Monday, June 16, 2014 11:09 AM
  • You're in an unsupported deployment. I can't explain why this works or doesn't work, but my guess would be that somebody else installed the files.
    Monday, June 16, 2014 3:16 PM
    Owner
  • My guess would be that on the machines where it works, somehow the 3rd party DLL is able to find the requisite 90 CRT DLLs from somewhere else on the system (like a centrally installed location).

    Is it not possible for you to get the sources of the 3rd party DLL and rebuild it using the new VS?

    Thursday, July 17, 2014 3:59 PM
  • I have somelegacy DLLs in want to use in my Store App. They need older versions of the VS runtime as seen in this ProcessMonitor screen (MSVCR80 and MSVCR90)

    The docs mention something about the search path that can be altered via the manifest:

    1. The package dependency graph of the process. This is the application's package plus any dependencies specified as<PackageDependency> in the <Dependencies> section of the application's package manifest. Dependencies are searched in the order they appear in the manifest.

    How is this done exactly?

    Copying the correct DLLs from my machines SxS folder to the apps bin root does indeed allow to load the legacy Dlls on some PCs but it crashes on some machines with an "Internal Runtime Error". I wonder why that is? Those DLLs should be able to exist in memory side by side just fine. I compiled a quick normal VS Win32 project and its using the SxS from the Windows folders and everything runs just fine.

    Any ideas?

    Wednesday, November 5, 2014 9:33 PM
  • MSFT knows that this situation is unacceptable for LOB apps that are not deployed via the store? With Windows 10 more directed to Business customers does MSFT plan to revise its strategy and help us to convert legacy apps over to Modern Apps?

    This situation with the runtime dlls restrictions makes it nearly impossible right now. We have systems where this setup works just fine, others pop up that weird R6034 error.

    Thursday, November 6, 2014 1:23 PM
  • The WinRT does not support the usage of older versions of the C++ Runtime DLLs. I guess in some cases it works due to specific device drivers being present or something like that. Overall however it is not supported and likely won't be.

    The Microsoft solution for the issue of legacy DLLs in LOB Apps are Brokered Windows Runtime Components that still live in the Win32 world as Rob already said. If you want WinRT only you will have to recompile those DLLs against a current version of the VC Runtime DLLs.

    Of course you could also go the route of simply building a regular Win32 App and perhaps styling it's UI to be Touch Friendly (basically the way Adobe went with Photoshop).

    I obviously don't know yet what Win 10 will bring on the API front but I'm rather certain that not all Win32 calls will become available to WinRT Apps.

    Thursday, November 6, 2014 2:00 PM
  • Oliver, I am certainly not asking for more WinRT Win32 calls. I am asking to support the scenario where you just can't recompile old code with the new runtime DLLs. On the desktop loading apps that uses different versions of the VS runtime DLLs is perfectly supported. Why was this crippled in WinRT apps. It makes no sense. Especially in a controlled LOB deployment scenario.
    Thursday, November 6, 2014 3:19 PM
  • Also I cannot use Brokered Runtime Components, since I am in the C++ field.
    Thursday, November 6, 2014 3:44 PM
  • I tried to create a proxy using the VSIX for Brokered components MSFT provides.

    I referenced my WinRT component in the proxy project and compiled it:

    proxy\winrt_proxy\debug\winrt.h(1590): error C2143: syntax error : missing ')' before '*' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1590): error C2081: '__x_Windows_CFoundation_CIAsyncAction' : name in formal parameter list illegal (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1590): error C2143: syntax error : missing ';' before '*' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1590): error C2059: syntax error : '*' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1590): error C2059: syntax error : ')' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1602): error C2143: syntax error : missing ')' before '*' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1602): error C2081: '__x_Windows_CStorage_CStreams_CIBuffer' : name in formal parameter list illegal (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1602): error C2143: syntax error : missing '{' before '*' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1602): error C2059: syntax error : ')' (Debug\winrt_p.c)
    proxy\winrt_proxy\debug\winrt.h(1645): error C2059: syntax error : '}' (Debug\winrt_p.c)

    I guess those are unsupported types then in Brokered components? How would one expose async operations to the proxy then?

    Thursday, November 6, 2014 4:02 PM
  • Now there seems to be a difference how VS deploys apps and when I am installing the app via the packaged .PS file. Anyone know what's the difference?
    Monday, November 10, 2014 11:38 AM
  • It seems that apps deployed from inside Visual Studio behave differently to the ones I install on the device itself using the packages PowerShell script.

    What exactly is the difference? Does VS register 3rd party dlls differently?

    Monday, November 10, 2014 2:10 PM
  • What exactly do you mean that it behaves differently, and why does it matter if it does?

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Monday, November 10, 2014 7:04 PM
    Moderator
  • It matters because I am still struggling deploying 3rd party DLLs in an LOB scenario. I tried the Brokered Component approach and it does only work if I deploy the package via VS. If I install the same package via PS script on the target machine it fails to properly load my 3rd party DLLs that is depended on an older MSVCR80.DLL.

    And don't mention again that this scenario is not supported. I get it, that MSFT makes it especially hard to convert old desktop applications to the new platform, for whatever reason. Fact is it works when deployed via VS. So I wonder what does VS different than the installer script.

    Monday, November 10, 2014 7:10 PM
  • While VS can update an already deployed package in no-time (it seems to use a bin-diff algo to transfer only changed blocks from the package), the .ps1 script always reinstalls the app which takes much longer.
    Monday, November 10, 2014 11:49 PM
  • So, after looking into the msvcrt source code I found my solution. To code that leads to the anoying "C Runtime Error R6034" message and abort of the runtime loading is in crtlib.c _check_manifest

    Starting with VS2005 MSFT tried (and failed) to solve the "DLL hell" by enforcing the C-Runtime to be only loaded indirectly though the Win32 Loader depending on the applications process manifest declarations. They wanted to prevent developers to LoadLibrary("mscvr80.dll"). The routine checks various conditions under which it permits the runtime to be loaded. As of the comment at the beginning of the function:

    Notice that this is not a security feature: it's an helper which will try (as much as possible) to discourage the practice of not using a manifest to load the crt dll.

    However in Modern Apps, especially ones that are hosted in wwahost.exe, you have no influence of the manifest of the process nor its activation context (which I think is the culprit here). Both conditions checked by the _check_manifest function. So whatever I tried my 3rd party DLL could not load the msvcr80.dll (in the apps deployment root folder) properly.

    Now the hack: Luckily for me, MSFT had to short-circuit its own check routine in case a "Profile Guided Optimization" is performed by comment in the routine: 

    // If pogo-instrumented mscoree is loaded, it has
    // a dependency on pgort80.dll. However, the manifest
    // in pgort80.dll is ignored.

    and it then returns TRUE from the check routine.

    So all I had to do now was to create 2 dummy DLLs with no code, nor entry point (clocking in at 2560 bytes) named "mscoree.dll" and "pgort80.dll", load them into my apps process by using LoadPackagedLibrary and msvcr80.dll finally successfully loaded as a dependency of my 3rd party DLL.

    I think my hack is worthy to be mentioned in "The Old New Thing" one day, but since MSFT takes care of backward-compatibility I can safely assume that this solution will run stable until MSFT comes to senses and supports such scenarios out of the box for LOB apps in the future.

    Thanks everyone who tried to help to solve this issue!

     
    • Marked as answer by pkursawe Wednesday, November 12, 2014 9:15 AM
    • Edited by pkursawe Wednesday, November 12, 2014 1:53 PM
    Wednesday, November 12, 2014 9:15 AM
  • I think you've asked about this same scenario a number of times with answers that you're not satisfied with. If that's the case, it might be better if you open a support case and let us dig into this.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Wednesday, November 12, 2014 1:18 PM
    Moderator
  • Solved it myself. See https://social.msdn.microsoft.com/Forums/windowsapps/en-US/524dca19-6e3f-4fd1-ab8c-1d87a6551399/how-to-deploy-lob-app-with-legacy-dlls-that-depend-on-specific-sxs-msvcrt?forum=winappswithnativecode

    Still it would be nice VS would not deploy differently to manual installing a package. Overall, the whole deployment of LOB apps is still a mess. I hope MSFT fixes this with Windows 10.

    Wednesday, November 12, 2014 2:02 PM