Подкаталог подключаемого модуля в развертывании Azure - PullRequest
4 голосов
/ 14 декабря 2011

Я использую MEF для расширения своего веб-приложения и использую следующую структуру папок

> bin
  > extensions
    > Plugin1
    > Plugin2
    > Plugin3

Чтобы добиться этого автоматически, плагин проецирует выходные пути к этим каталогам. Мое приложение работает с лазурью и без нее. Моя проблема сейчас в том, что кажется невозможным автоматическое включение подкаталога расширений в пакет развертывания Azure.

Я тоже пытался установить зависимости при сборке, но безуспешно.

Есть ли другой способ?

1 Ответ

1 голос
/ 14 декабря 2011

Ну,

Я боролся с папкой bin .Проблема (если мы можем сказать «проблема») состоит в том, что процесс упаковки просто упаковывает то, что «скопировать в каталог», установлено как «копировать, если новее / нет» только для проекта веб-приложения (веб-роли).Наличие других сборок в BIN, на которые веб-приложение не ссылается явным образом, не будет развернуто.

Для моего случая, когда у меня есть довольно «статичные» ссылки, я просто упаковываю их в ZIP, помещаю их вBLOB-контейнер, а затем используйте Azure Bootstrapper , чтобы загрузить, извлечь и поместить в папку BIN эти ссылки.Однако из-за того, что я не знаю фактического расположения папки BIN в задаче запуска, я использую вспомогательные оболочки для загрузчика, чтобы добиться цели.

Вам потребуется получить список локальных сайтов, которыйможет быть выполнено с помощью чего-то похожего на:

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 определяется следующим образом:

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

Далее вам потребуется нечто похожее на этот метод:

 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 имеет следующую подпись:

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 несколько раз для каждого плагина.И этот код может выполняться в методе OnStart RoleEntryPoint.

А также, если вы планируете быть более динамичным, вы также можете переопределить метод Run () вашего подкласса RoleEntryPoint и каждую минуту проверять наличие новых плагинов.например.

Надеюсь, это поможет!

РЕДАКТИРОВАТЬ

И как вы можете развернуть плагины.Ну, вы можете либо вручную загрузить свои плагины, либо вы можете разработать небольшой специальный BuildTask для автоматической загрузки вашего плагина при сборке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...