Search code examples
vb.netpinvokeclrshimcreateprocessasuser

vb.net CLR/SHIM error: This application could not be started. --> Unable to find a version of the runtime to use


Getting an unexpected, "This application cannot be started" popup error that is suggesting SHIM_NOVERSION_FOUND error in .NET CLR. Here's what's going on...

I have two vb.net applications:

1- MyApp.exe -- Windows Forms App
2- Launcher.exe -- Windows Service

Both are .NET framework 4.5 applications, and Launcher.exe is embedded inside MyApp.exe. Both are configured for AnyCPU, and neither use an app.config file. The reason being that the delivery tool can only deliver a single file, so I can't include any extras. The executable must be self-contained, and you can't embed an app.config file.

The execution runs in the following layers:

Layer 1: Delivery tool

  • Native C++ application
  • Elevated, running as Local System Account

Layer 2: MyApp.exe

  • .NET 4.5 application
  • Elevated, running as Local System Account
  • It runs fine, and installs Launcher.exe as a new Windows Service.

Layer 3: Launcher.exe

  • .NET 4.5 Windows Service
  • Elevated, running as Local System Account
  • Uses Windows API calls to enable the following privileges: SE_INCREASE_QUOTA_NAME, SE_ASSIGNPRIMARYTOKEN_NAME, SE_TCB_NAME
  • In summary, it uses elevated privileges to search for Explorer.exe processes, open them, duplicate the user's security token, and call the CreateProcessAsUser() API, using the user's token, in order to launch a second copy of MyApp.exe, running on the user's desktop.

Layer 4: MyApp.exe

  • .NET 4.5 application
  • Fails to launch with popup error --> This application could not be started.
  • It's A COPY of MyApp.exe, same as layer 2.

I've enabled .NET CLR debugging to compare the loading of MyApp.exe at layers 2 and 4:

Layer 2:
6172,1589.119,Parsing config file: C:...\MyApp.exe.config
6172,1589.119,Config File (Open). Result:80070002
6172,1589.119,UseLegacyV2RuntimeActivationPolicy is set to 0
6172,1589.119,LegacyFunctionCall: GetFileVersion. Filename: C:...\MyApp.exe
6172,1589.119,LegacyFunctionCall: GetFileVersion. Filename: C:...\MyApp.exe
6172,1589.119,C:...\MyApp.exe was built with version: v4.0.30319
6172,1589.166,Decided on runtime: v4.0.30319

Layer 4:
6552,1594.704,Parsing config file: C:\windows\TEMP\MyApp.exe.config
6552,1594.704,Config File (Open). Result:80070002
6552,1594.704,UseLegacyV2RuntimeActivationPolicy is set to 0
6552,1594.704,LegacyFunctionCall: GetFileVersion. Filename: C:\windows\TEMP\MyApp.exe


6552,1594.704,ERROR: Unable to find a version of the runtime to use.
6552,1594.704,SEM_FAILCRITICALERRORS is set to 5
6552,1688.055,FunctionCall: RealDllMain. Reason: 0
6552,1688.055,FunctionCall: OnShimDllMainCalled. Reason: 0

Random facts:

  • This doesn't happen on all computers targeted.
  • Disabling the antivirus doesn't resolve on affected systems.
  • On some computers, the error only happens once, and subsequent executions do not reproduce the popup error.

Looking for any help in understanding or debugging WHY .NET CLR is unable to determine the runtime version to use, when that very same application has already launched successfully!


Solution

  • I had the same issue with a Windows service running as LocalSystem and a WPF application that I was trying to run using CreateProcessAsUser by duplicating the user token pertaining to the active session (WTSQueryUserToken). When running the .exe manually it worked, but when the service was trying to create the process I kept receiving "This application could not be started". I also got the same CLR logs as you with "ERROR: Unable to find a version of the runtime to use.".

    These are the things I've done:

    • Set OnlyUseLatestCLR registry value to 1
    • Use UNC paths for mapped drives (I am running inside a Windows VM and for some reason the system could not find the path for the config file after loading the app)

    Check firstly if the path you are passing to CreateProcessAsUser is correct.