none
PlugIn in Windows Service ...ShadowCopyFiles...hum..my understanding is.. RRS feed

  • Question

  • Hello,

    I have my Windows Service. I am trying to create a plug-in so that my plugin dll can be loaded and run in the service.

    Here is what I did.

    AppDomain pDomain;

    override OnStart(..) {

    AppDomainSetup sInfo = new AppDomainSetup();
    sInfo.ApplicationName = "MyApp";
    sInfo.ApplicationBase = "C:\MyPlugin";
    sInfo.ShadowCopyFiles = "true";
    sInfo.ConfigurationFile = "Blah..MyConfigPaht...";
    sInfo.PrivateBinPath = "bin";

    pDomain = AppDomain.CreateDomain("MyAppPlugin",
                                null, sInfo);

    }

    ..MyFunction..() {

         // This function will be called several times by my business logic.

         // Load my plugin dll from the pDomain

          MyPluginLoader mypl  =       pDomain.CreateInstanceFromAndUnwrap..........;

         // Call my plug-in interface

          mypl.Run();

           ....

    }

    override void OnStop() {

       AppDomain.Unload(pDomain );

    }

    My plugin DLL located at C:\MyPlugin\bin\BlahBlah.dll

    Well..The code works fine... As you look at the my code, I enabled the shadow copy. So I thought that I can simply replace my plug-in dll to update without stopping the service. However, it doesn't work the way I expected. After I copied the updated plugin dll,I have to stop and start the service in order to see updated one. As you see, I explicitly turned on the Shadow feature..So I thought that without restarting the service, my updated dll can be used right away, but it seems not...

    Well,  obviously, instead of doing this, I can create, load, and unload in one function(MyFunction)..but this is not really shadow copying feature. According to MSDN, "Shadow copying enables assemblies that are used in an application domain to be updated without unloading the application domain"..So I believe my updated plug-in dll should be picked up by the service, since I explicitly turned on the Shadow...

    Is my understanding incorrect?

    Any idea?

    Thanks,


    • Edited by T J Friday, June 3, 2016 3:27 PM
    Friday, June 3, 2016 3:24 PM

Answers

  • That's not exactly how it works.

    Read that article carefully once again and you should be able to see that it works because "assemblies from the application path are copied to another location and loaded from that location. The copy is locked, but the original assembly file is unlocked and can be updated."

    This implies the running instance still see and use the old copy, which is logical because otherwise your application will runs with all sorts of funny scenarios, like classes that got serialized in Session cannot be deserialized back because the container is different, etc.

    In your case you'll still have to restart the service to see the code in new files, just that you need not stop the service during your copying time, therefore the overall downtime is reduced.

    Monday, June 6, 2016 2:37 AM
    Answerer
  • In the case of ASP.NET, since any file change inside the "~\bin" folder or web.config file, with or without shadow copy enabled, will trigger AppDomain reload. The situation "feels" a bit different but in fact the same.

    And btw, since ASP.NET compiles the MSIL binaries to native and load from <.NET framework folder>\Temporary ASP.NET Files, you can say shadow copy is default enabled from day one since the days of .NET v1.0.


    Wednesday, June 8, 2016 1:55 AM
    Answerer

All replies

  • That's not exactly how it works.

    Read that article carefully once again and you should be able to see that it works because "assemblies from the application path are copied to another location and loaded from that location. The copy is locked, but the original assembly file is unlocked and can be updated."

    This implies the running instance still see and use the old copy, which is logical because otherwise your application will runs with all sorts of funny scenarios, like classes that got serialized in Session cannot be deserialized back because the container is different, etc.

    In your case you'll still have to restart the service to see the code in new files, just that you need not stop the service during your copying time, therefore the overall downtime is reduced.

    Monday, June 6, 2016 2:37 AM
    Answerer
  • Hi T J,

    I agree with cheong. You could add file watching to the DLL folder. If the folder is changed, you could restart your appdomain.

    System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher("dll path");
    watcher.Changed += watcher_Changed;
    void watcher_Changed(object sender, System.IO.FileSystemEventArgs e)
    {
        //restart appdomain
    }
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, June 6, 2016 5:22 AM
    Moderator
  • Yes, right. I might be able to use FileSystemWatcher to restart my app domain. But....

    Let's suppose that you have 10 dlls in a directory being watched by FileSystemWatcher.

    Say you updated two of them ...so FileSystemWatcher got notified two times(may be more depending on that associated IO operation I guess,anyway)... so the app domain is going to restart two times..(but in this case, I only need to restart once)

    I don't think there is a really good way to tell WHEN the app domain needs to be restarted. What I meant is that say I updated 3 dlls in the directory..then only thing I want is that I need to restart the app domain only once after 3 dlls are changed completely(which basically means those after 3 files are copied and replaced)..

    Another question, do you know by any chance how ASP.NET internally shadow copy works? I believe that they use pretty much same technique..

    So say you have 20 dlls in bin directory of ASP.NET. Let's say there are 15 updated dlls, so you copied and replaced 15 dlls in the bin directory. In this case, ASP.NET internally restarts the app domain 15 times, or somehow only once(if it does, then how)?

    My last question is how expensive operation it is to unload the app domain and creation.

    Thanks,





    • Edited by T J Monday, June 6, 2016 7:20 PM
    Monday, June 6, 2016 7:11 PM
  • For your problem, usually you'll want to keep the start time (I mean the exact time, not duration) of you application as it runs, and skips restart if the time of event is less than, say 3 minutes, from the start time. Increase the timespan as you need if you have more DLLs or would be working on slower connection.

    The question on "how expensive" cannot be known because it really depends on how many "static" code your application need to load. (In .NET v4.5+, the runtime will only load and initialize classes as you use them, except those static classes / classes used in static variables which is always initialized on load. You can have 100 DLLs but none of them except 3 will be needed on initial application start, then the AppDomain restart cost will be very low. If you only have 3 DLLs but one of time is doing heavy-handed initialization on load, say the grid component DLL of certain company start with D, your application's restart time can cost a few minutes)




    Tuesday, June 7, 2016 1:53 AM
    Answerer
  • Hi T J,

    >>"My last question is how expensive operation it is to unload the app domain and creation."

    You could add file watching to app.config file instead of all the DLL folder. If you want to restart app domain after updating the DLLs, you could change some contents of the app.config file. For example, add a serialnumber section in appsettings. Then increase the value by 1 after updating the DLLs.

    <appSettings>
      <add key="serialnumber" value="1"/>
    </appSettings>
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, June 7, 2016 5:52 AM
    Moderator
  • For your problem, usually you'll want to keep the start time (I mean the exact time, not duration) of you application as it runs, and skips restart if the time of event is less than, say 3 minutes, from the start time. Increase the timespan as you need if you have more DLLs or would be working on slower connection.


            -> It may or may NOT work. BTW, so is this possibly also how ASP.NET shadow copy works internally? I don't think so though.

    • Edited by T J Tuesday, June 7, 2016 12:18 PM
    Tuesday, June 7, 2016 11:33 AM
  • In the case of ASP.NET, since any file change inside the "~\bin" folder or web.config file, with or without shadow copy enabled, will trigger AppDomain reload. The situation "feels" a bit different but in fact the same.

    And btw, since ASP.NET compiles the MSIL binaries to native and load from <.NET framework folder>\Temporary ASP.NET Files, you can say shadow copy is default enabled from day one since the days of .NET v1.0.


    Wednesday, June 8, 2016 1:55 AM
    Answerer
  • Is that somehow particularly that piece of code that does the AppDomain reload in the ASP.NET...I can peek the code somehow by a sort of tool such as Reflector?

    Please let me know if you know somehow.

    Thanks,

    Wednesday, June 8, 2016 11:39 AM
  • This is done by the ASP.NET worker process.

    The runtime registers notification event in filesystem driver and will trigger reload if notified. However since C:\Windows\System32\inetsrv\w3wp.exe is not a .NET EXE, reflector can not show you what is happening there. You can only try to view it with an analysing debugger / decompiler.

    Friday, June 10, 2016 1:41 AM
    Answerer