Share via


AppDomain.AppendPrivatePath is obsolete

In .Net framework 2.0, AppDomain.AppendPrivatePath is marked as obsolete.

The deprecation is explained in Gotdotnet.com's break change web site

https://www.gotdotnet.com/team/changeinfo/Backwards1.1to2.0/default.aspx#00000102

<quote>

Title Cache load failures in order to ensure that different app domains do not have different dependency loading success/failure characteristics in domain neutral sharing scenarios.
Area System.Reflection
Affected APIs Deprecating Appdomain.AppendPrivatePath and Appdomain.ClearPrivatePath
Affected Scenarios This change would break code that is dependent on changing the private path of the app-domain after the first assembly has been loaded. This is actually less common than one would think. ASP.Net though that they relied on this and later learned that they did not.
Description In V1 & Version 1.1, some pathways through the loader recorded a failure to load an assembly and would fail subsequent attempts to load that same assembly into the same AppDomain. However, most pathways through the loader would not cache this binding failure. This lack of caching enables certain scenarios, which some customers are doubtless taking advantage of. This includes a known xaml / JScript Avalon scenario which will break if we start consistently caching our binding failures. That particular scenario (VSV2.0 120644) executes code that contains an AssemblyRef to an assembly that doesn’t exist. Any load failures are trapped. Later, the missing assembly is generated via JScript and subsequent load attempts are expected to succeed. In V2.0, we would like our new default behavior to break these scenarios. Naturally we would support an opt-in mechanism to force the loader back to the V1 & Version 1.1 behavior via a config file. We would break these scenarios by making the following changes: - Cache all binding failures per assembly per AppDomain. Subsequent attempts would unconditionally continue to fail. Of course, transient errors like OutOfMemoryException are not considered binding failures and are subject to retry. - Deprecate AppDomain.AppendPrivatePath and ClearPrivatePath. These APIs allow the application to dynamically change where we look for assemblies to satisfy binding requests. These APIs are subject to race conditions and cannot be reliably used, as I will explain.
Workaround There is no workaround

</quote>

If you have read my blog about Domain Neutral Assemblies and Caching Binding Failures, you will see that we are toward more on a deterministic binding behavior where we can make sane sharing decision without fearing that our assumption will be broken. Deprecating AppDomain.AppendPrivatePath is a step toward that goal.

The deprecation actually causes quite some confusion. People asks if there is a replacement.

There is no replacement in .Net framework 2.0. There will be no future replacement, as far as I can see.

The only reason I see why AppDomain.AppendPrivatePath can be any useful, is that your application will download some random bits, put them in a sub folder under your application, then use AppDomain.AppendPrivatePath to make them available to the application.

The approach has at least two problems.

First, it makes assembly binding undeterministic. Depending on the assembly binding happens before the download or after, you may see a failure sometimes, or a success the other times. This is exactly the reason why we deprecate AppDomain.AppendPrivatePath in the first place --- WE WANT A DETERMINISTIC BINDING BEHAVIOR.

Second, on a typical Windows machine, applications are installed to C:\Program Files, which by default, only administrators can update. If you start download random bits into the application's sub directory, it practically means your application can only run under administrator account. This is exactly the reason why Windows is so vulnerable, because EVERY APPLICATION REQUIRES ADMINISTRATOR ACCOUNT TO RUN. If you are doing this, please stop, and use your creativity to find alternatives.

Of course, I can't really know all the cases how people use AppDomain.AppendPrivatePath. If you are using it, post your reason here. We can discuss the alternatives.

In any case, if you subscribe AssemblyResolve event, you can probably have your problem solved easily.

Comments

  • Anonymous
    February 23, 2005
    Great blog. This information is priceless. I was wondering if you could comment on the following, however. We're wanting to place assemblies in a specific location outside of our ASP.NET application and I understand altering the path won't help. However, when I place them in a web-accessible location, I can't seem to add a <runtime> directive to machine.config to indicate the location of the dependent assembly. Your article here: http://blogs.msdn.com/junfeng/archive/2004/11/16/258081.aspx details XML that doesn't seem to work as shown. Repeated here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/gngrfCodeBase.asp this also seems not to work.

    Any advice on how you actually download or use an assembly from a location outside the ASP.NET app?
  • Anonymous
    February 23, 2005
    Please read my article closely.

    <quote>
    1. For the runtime to use the <codeBase> setting in a machine configuration file or publisher policy file, the file must also redirect the assembly version (to a different assembly version, added by me).


    What this says is, when the <codeBase> hint is in publisher policy or in machine config, if there is no assembly version redirection, or assembly redirection does not result in a different assembly version, the codeBase hint will not be honored.

    </quote>
  • Anonymous
    February 24, 2005
    I agree with the desire to achieve deterministics binding but I disagree with deprecating the use of AppendPrivatePath.

    I believe that forcing apps to use the AssemblyResolve event will lead to LESS deterministic binding. There will be more differences in how assemblies get resolved, not less. It would only make it more predictable for assemblies that are in the Load context - all others will be resolved differently for each application. If each app has to deal with it themselves, and if they get it wrong (and the liklihood of that will increase with the number of devs all dealing, perhaps incorrectly, with binding issues), the end user's frustration with .NET will increase.

    There are other problems with deprecating this API. There are numerous valid use cases for an application to dynamically add assemblies into subdirectories below its appbase; this can occur anytime an app wants to load a new plugin that is located in its own folder. For reasons I've gone into in other threads it is not always feasible to load plugins in the LoadFrom context - conflicts can arise because some assemblies can get loaded twice, once in each context.

  • Anonymous
    February 24, 2005
    The versioning stuff is quite a gotcha. It forces you to write an app to depend on a different version of an assembly if you want to use an external location for the "real" version, and its not apparent in your other discussions, like this:

    <quote>There are other solutions if you don’t want to install the assembly to GAC. You can put the assembly in a well known location. You then add a codebase hint for the assembly in machine.config. When you service the assembly, you upload the updated assembly in a new well known location and modify the codebase hint in machine.config.

    If you don’t want to modify machine.config, you still have options. You can add the codebase hint to the config file for all the applications that want to use the assembly. When you service the assembly, you update all the application config files to point the assembly to the new location. The advantage of this option is that the change only affects the applications you modified, instead of all the applications in the machine, as the first and the second option do. </quote>

    The fact that the assembly that is mentioned in the codebase hint MUST be a different version than what the application is looking for makes this a less than ideal solution if you are looking to just place assemblies in a common external location.
  • Anonymous
    February 24, 2005
    The comment has been removed
  • Anonymous
    February 24, 2005
    The comment has been removed
  • Anonymous
    February 25, 2005
    David,

    Your discussion goes way beyond the scope of this article.

    I have an article about binding context, but I did not have time to finish yet. We should probably have a full discussion there.

    But it is sufficient to say that the direction is to use another appdomain for the add-in activation. Hopefully we will have all the problem sorted out in the next version. .Net framework 2.0 is too close to finish. There is really not much we can do now.
  • Anonymous
    February 25, 2005
    By the way David,

    I can't reach you on your email. Drop me an email if you did update your email.

    Thanks,
    Junfeng
  • Anonymous
    February 25, 2005
    The comment has been removed
  • Anonymous
    March 18, 2005
    By the way David,
  • Anonymous
    May 29, 2009
    PingBack from http://paidsurveyshub.info/story.php?title=junfeng-zhang-s-windows-programming-notes-appdomain-appendprivatepath