Azure部署中的插件子目录 [英] Plugin subdirectory in Azure deployment

查看:45
本文介绍了Azure部署中的插件子目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用MEF扩展Web应用程序,并使用以下文件夹结构

I use MEF to extend my web application and I use the following folder structure


> bin
  > extensions
    > Plugin1
    > Plugin2
    > Plugin3

要自动实现此目的,插件项目的输出路径设置为这些目录.我的应用程序在有和没有天蓝色的情况下都可以使用.现在我的问题是,似乎不可能将扩展子目录自动包含到azure部署程序包中.

To achive this automatically, the plugin projects output paths are set to these directories. My application is working with and without azure. My problem is now, that it seems to be inpossible to include the extensions subdirectory automatically to the azure deployment package.

我也尝试设置构建依赖项,但没有成功.

I've tried to set the build dependencies too, without success.

还有另一种方法吗?

推荐答案

嗯,

我一直在使用 bin 文件夹.问题(如果我们说问题")是打包过程,只是打包仅针对Web应用程序(Web角色)项目设置为如果更新/删除副本,则复制"的复制到目录".在BIN中有其他未由Web应用程序明确引用的程序集将无法部署.

I've struggled with the bin folder. The issue (if we may say "issue") is that the packaging process, just packs what is "copy to out directory" set to "copy if newer/aways" only for the Web application (Web Role) project. Having another assemblies in the BIN which are not explicitly referenced by the Web Application will not get deployed.

对于我来说,在我有漂亮的静态"引用的情况下,我只是将它们打包在ZIP中,将它们放在BLOB容器中,然后使用 Azure Bootstrapper 来下载,提取这些引用并将其放入BIN文件夹中.但是,由于我不知道启动任务中BIN文件夹的实际位置,因此我使用引导程序的帮助程序包装程序来完成此操作.

For my case, where I have pretty "static" references I just pack them in a ZIP, put them in a BLOB container and then use the Azure Bootstrapper to download, extract and put in the BIN folder these references. However, because I don't know the actual location of the BIN folder in a startup task, I use helper wrappers for the bootstrapper to make the trick.

您将需要获取本地站点列表,这可以通过类似以下操作来实现:

You will need to get the list of local sites, which can be accomplished by something similar to:

public IEnumerable<string> WebSiteDirectories
        {
            get
            {
                string roleRootDir = Environment.GetEnvironmentVariable("RdRoleRoot");
                string appRootDir = (RoleEnvironment.IsEmulated) ? Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) : roleRootDir;

                XDocument roleModelDoc = XDocument.Load(Path.Combine(roleRootDir, "RoleModel.xml"));

                var siteElements = roleModelDoc.Root.Element(_roleModelNs + "Sites").Elements(_roleModelNs + "Site");

                return
                    from siteElement in siteElements
                    where siteElement.Attribute("name") != null
                            && siteElement.Attribute("name").Value == "Web"
                            && siteElement.Attribute("physicalDirectory") != null
                    select Path.Combine(appRootDir, siteElement.Attribute("physicalDirectory").Value);
            }
        }

_roleModelNs变量的定义如下:

Where the _roleModelNs variable is defined as follows:

private readonly XNamespace _roleModelNs = "http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition";

接下来,您将需要与该方法类似的东西:

Next you will need something similar to that method:

 public void GetRequiredAssemblies(string pathToWebBinfolder)
        {
            string args = string.Join("",
                @"-get https://your_account.blob.core.windows.net/path/to/plugin.zip -lr $lr(temp) -unzip """,
                pathToWebBinfolder,
                @""" -block");
            this._bRunner.RunBootstrapper(args);
        }

RunBootstrapper具有以下签名:

And the RunBootstrapper has following signature:

public bool RunBootstrapper (string args)
        {
            bool result = false;
            ProcessStartInfo psi = new ProcessStartInfo();
            psi.FileName = this._bootstrapperPath;
            psi.Arguments = args;
            Trace.WriteLine("AS: Calling " + psi.FileName + " " + psi.Arguments + " ...");
            psi.CreateNoWindow = true;
            psi.ErrorDialog = false;
            psi.UseShellExecute = false;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardInput = false;
            psi.RedirectStandardError = true;
            // run elevated
            // psi.Verb = "runas";
            try
            {
                // Start the process with the info we specified.
                // Call WaitForExit and then the using statement will close.
                using (Process exeProcess = Process.Start(psi))
                {
                    exeProcess.PriorityClass = ProcessPriorityClass.High;
                    string outString = string.Empty;
                    // use ansynchronous reading for at least one of the streams
                    // to avoid deadlock
                    exeProcess.OutputDataReceived += (s, e) =>
                    {
                        outString += e.Data;
                    };
                    exeProcess.BeginOutputReadLine();
                    // now read the StandardError stream to the end
                    // this will cause our main thread to wait for the
                    // stream to close
                    string errString = exeProcess.StandardError.ReadToEnd();
                    Trace.WriteLine("Process out string: " + outString);
                    Trace.TraceError("Process error string: " + errString);
                    result = true;
                }
            }
            catch (Exception e)
            {
                Trace.TraceError("AS: " + e.Message + e.StackTrace);
                result = false;
            }
            return result;
        }

当然,在您的情况下,您可能需要更复杂的方法,在这种情况下,您将首先尝试通过代码获取所有插件(如果每个插件都在其自己的ZIP中),然后对每个插件多次执行GetRequiredAssemblies插入.而且此代码可能在RoleEntryPoint的OnStart方法中执行.

Of course, in your case you might want something a bit more complex, where you'll first try to fetch all plugins (if each plugin is in its own ZIP) via code, and then execute the GetRequiredAssemblies multiple times for each plugin. And this code might be executing in the RoleEntryPoint's OnStart method.

此外,如果您打算提高动态性,还可以重写RoleEntryPoint子类的Run()方法,例如每分钟检查新插件.

And also, if you plan to be more dynamic, you can also override the Run() method of your RoleEntryPoint subclass, and check for new plugins every minute for example.

希望这会有所帮助!

编辑

以及如何部署插件.好了,您可以手动上传插件,也可以开发一个小的自定义BuildTask ,以便在构建时自动上传您的插件.

And how can you get the plugins deployed. Well, you can either manually upload your plugins, or you can develop a small custom BuildTask to automatically upload your plugin upon build.

这篇关于Azure部署中的插件子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆