Проблемы развертывания Mage.exe

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

Так как я изменяю файл конфигурации, я также должен восстановить *.manifest и *.application файлы, и насколько я понимаю, моя единственная реальная опция для этого состоит в том, чтобы использовать Mage.exe от Win7 SDK. Для фиксации *.manifest файла с надлежащим хешем из измененного файла конфигурации я работаю:

волшебник - новое Приложение-fd ".\Application Файлы \<appName> _1_0_0_0"-ToFile ".\Application Файлы \_ 1_0_0_0 \<appName>.exe.manifest" - Имя" <appName>" - версия "1.0.0.0"-CertFile "key.pfx" - пароль" <пароль>"

и затем, для фиксации *.application файла с надлежащим хешем из измененного *.manifest файла я работаю:

волшебник - новое Развертывание-I t-t" <appName>.application"-v "1.0.0.0"-appManifest ".\Application Файлы \<appName> _1_0_0_0 \<appName>.exe.manifest" - pu "http://<hostaddress> / <путь> / Файлы приложения / <appName> _1_0_0_0 / <appName>.exe.manifest"-CertFile "key.pfx" - пароль""

Теперь, это все работает, и я получаю сообщение, что файлы были успешно подписаны. Когда я пытаюсь установить клиентское приложение, хотя, очевидно, что что-то спуталось, когда я получаю журнал ошибок с сообщением:

+ Deployment manifest is not semantically valid.
+ Deployment manifest requires <deployment> section.

В рассмотрении *.application файла это имеет некоторую дополнительную информацию под узлом "развертывания", который не имеет тот же файл непосредственно от опубликовать функции VS2008:

<deployment install="true">
  <subscription>
    <update>
      <expiration maximumAge="0" unit="days" />
    </update>
  </subscription>
  <deploymentProvider codebase="http://<hostaddress>/<path>/Application Files/<appName>_1_0_0_0/<appName>.exe.manifest" />
</deployment>

VS2008 публикуют версию, просто имеет:

<deployment install="true" />

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

Действительно ли это - известная проблема и является там каким-либо способом заставить Волшебника создавать файл без дополнительной информации в узле развертывания так, чтобы это работало правильно?

Править: Как временное решение, я загружаю файлы в XmlDocument и изменяю их для удовлетворения, затем оставляя файлы. Кроме того, я теперь сталкиваюсь с проблемой того, чтобы быть пока еще не могущим определить, как добавить значок к развертыванию, таким образом, объект Меню "Пуск" получает значок кроме универсального значка.

7
задан Nathan Wheeler 23 February 2010 в 21:23
поделиться

1 ответ

Вот моя реализация. Я потратил много времени на этот небольшой фрагмент кода, и я до сих пор не нашел всех правильных вариантов, чтобы Mage обрабатывал всю генерацию файла .application без вмешательства. Я собираюсь сказать, что, вероятно, в этот код можно внести много оптимизаций. Однако это все еще можно использовать как трамплин, чтобы кому-то помочь.

Чтобы следующий метод работал, вы должны развернуть его хотя бы один раз из ClickOnce в VS, а затем просто сохранить файл .application из этого развертывания. Вы ДОЛЖНЫ удалить .application и .manifest В папке развертывания.

После того, как я переместил все файлы приложения в Config.Instance.ServerSettings.ClientLocation + « _ » :

DirectoryInfo filedir = new DirectoryInfo(Config.Instance.ServerSettings.ClientLocation);

if (filedir.Exists)
{
    FileInfo[] files = filedir.GetFiles();

    // Find the current .application file.
    FileInfo appinfo = null;
    foreach (FileInfo fi in files)
    {
        if (fi.Name == "<AppName>.application")
        {
            appinfo = fi;
            break;
        }
    }

    if (appinfo != null)
    {
        XmlDocument applocinfo = new XmlDocument();
        applocinfo.Load(appinfo.FullName);

        // Get the location of the files from the .application file.
        string codebase = applocinfo["asmv1:assembly"]["dependency"]["dependentAssembly"].Attributes["codebase"].Value.Replace("AppName.exe.manifest", "");

        XmlDocument xDoc = new XmlDocument();
        xDoc.Load(Path.Combine(Path.Combine(filedir.FullName, codebase), "AppName.exe.config"));

        foreach (XmlNode xn in xDoc["configuration"]["appSettings"].ChildNodes)
        {
            if (xn.Attributes != null && xn.Attributes["key"] != null && xn.Attributes["key"].Value == "Clnt_Host")
            {
                // Here is where I'm modifying my config file, the whole purpose in this wretched deployment process.
                xn.Attributes["value"].Value = Config.Instance.ClientSettings.Host;
                break;
            }
        }

        xDoc.Save(Path.Combine(Path.Combine(filedir.FullName, codebase), "<AppName>.exe.config"));

        Process p = new Process();
        p.StartInfo = new ProcessStartInfo(Path.Combine(filedir.FullName, "Mage.exe"));
        p.StartInfo.WorkingDirectory = filedir.FullName;

        FileInfo fi = new FileInfo(Path.Combine(Path.Combine(filedir.FullName, codebase.TrimStart('.')), "<AppName>.exe.manifest"));
        if (fi.Exists)
            fi.Delete();

        // Write a new .manifest file as an Application file. (-new Application -ToFile ".\codebase\<AppName.exe.manifest")
        // Include the files from the codebase directory in the manifest (-fd ".\codebase\")
        // Give the application a name to use in the start menu (-name "<AppName>")
        // Assign a version number to the deployment (-Version "<version>")
        // Give the application an icon to use in the start menu (-IconFile "64x64.ico")
        // Sign the manifest (-CertFile "<KeyName>.pfx -Password <password>)
        p.StartInfo.Arguments = "-new Application -fd \".\\" + codebase.TrimEnd('\\') + "\" -ToFile \".\\" + Path.Combine(codebase, "<AppName>.exe.manifest") + "\" -Name \"<AppName>\" -Version \"" + codebase.Substring(codebase.IndexOf('_') + 1, codebase.Length - (codebase.IndexOf('_') + 1)).Replace('_', '.').TrimEnd('\\') + "\" -CertFile \"<KeyName>.pfx\" -Password <Password> -IconFile \"64x64.ico\"";

        while (p.StartInfo.Arguments.Contains(".\\.\\"))
            p.StartInfo.Arguments = p.StartInfo.Arguments.Replace(".\\.\\", ".\\");

        Logger.Instance.LogInfo("Starting application: " + p.StartInfo.FileName + "\n\tWith arguments: " + p.StartInfo.Arguments, Logger.InfoType.Information);

        p.Start();

        while (!p.HasExited)
        {
            Thread.Sleep(100);
        }

        // Make a new deployment manifest (-new Deployment -t "<AppName>.application")
        // Make the application available offline (-I t)
        // Use the files from the .manifest we just made (-AppManifest ".\codebase\<AppName>.exe.manifest")
        p.StartInfo.Arguments = "-new Deployment -I t -t \"<AppName>.application\" -v \"" + codebase.Substring(codebase.IndexOf('_') + 1, codebase.Length - (codebase.IndexOf('_') + 1)).Replace('_', '.').TrimEnd('\\') + "\" -AppManifest \".\\" + codebase + "<AppName>.exe.manifest\" -pu \"http://" + Config.Instance.ClientSettings.Host + "/client/" + codebase.Replace('\\', '/') + "<AppName>.exe.manifest\"";

                    while (p.StartInfo.Arguments.Contains(".\\.\\"))
            p.StartInfo.Arguments = p.StartInfo.Arguments.Replace(".\\.\\", ".\\");

        Logger.Instance.LogInfo("Starting application: " + p.StartInfo.FileName + "\n\tWith arguments: " + p.StartInfo.Arguments, Logger.InfoType.Information);

        p.Start();

        while (!p.HasExited)
        {
            Thread.Sleep(100);
        }

        xDoc = new XmlDocument();
        xDoc.Load(Path.Combine(filedir.FullName, "<AppName>.application"));

        // Add to the Deployment manifest (.application) to make the application 
        // have a minimum required version of the current version,and makes a 
        // subscription so that the application will always check for updates before 
        // running.
        if (xDoc["asmv1:assembly"]["deployment"]["subscription"] != null)
        {
            xDoc["asmv1:assembly"]["deployment"].RemoveChild(xDoc["asmv1:assembly"]["deployment"]["subscription"]);
            xDoc["asmv1:assembly"]["deployment"].RemoveChild(xDoc["asmv1:assembly"]["deployment"]["deploymentProvider"]);
            XmlAttribute node = xDoc.CreateAttribute("minimumRequiredVersion");
            node.Value = codebase.Substring(codebase.IndexOf('_') + 1, codebase.Length - (codebase.IndexOf('_') + 1)).Replace('_', '.').TrimEnd('\\');
            xDoc["asmv1:assembly"]["deployment"].Attributes.Append(node);

            xDoc["asmv1:assembly"]["deployment"].InnerXml = "<subscription><update><beforeApplicationStartup /></update></subscription>";
        }

        xDoc.Save(Path.Combine(filedir.FullName, "<AppName>.application"));

        // Sign the deployment manifest (.application) (-Sign "\<AppName>.application" -CertFile "<AppName>.key" -Password <password>
        p.StartInfo.Arguments = "-Sign \"<AppName>.application\" -CertFile \"<AppName>.pfx\" -Password <password>";

        while (p.StartInfo.Arguments.Contains(".\\.\\"))
            p.StartInfo.Arguments = p.StartInfo.Arguments.Replace(".\\.\\", ".\\");

        Logger.Instance.LogInfo("Starting application: " + p.StartInfo.FileName + "\n\tWith arguments: " + p.StartInfo.Arguments, Logger.InfoType.Information);

        p.Start();

        while (!p.HasExited)
        {
            Thread.Sleep(100);
        }
    }
}
2
ответ дан 7 December 2019 в 16:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: