Преобразование файлов с помощью msdeploy - PullRequest
4 голосов
/ 20 января 2011

Могу ли я использовать механизм преобразования конфигурации MSDeploy для преобразования других файлов?

Ответы [ 4 ]

5 голосов
/ 08 февраля 2011

(другой подход)

Пакет msdeploy вызывается jsut во время выполнения MSbuild для вашего проекта.

TransformXml является включенной задачей .csproj или.vsproj build.

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

Например, что мы делаем, это пишем пользовательскую цель

<Target Name="TransformFile">

    <TransformXml Source="$(DestinationPath)\$(Sourcefile)" 
       Transform="$(DestinationPath)\$(TransformFile)" 
       Destination="$(DestinationPath)\$(DestFile)" />
    </Target>

Затем измените ваш .csproj, чтобы запускать ПЕРЕД вызовом задачи публикации.

<CallTarget Targets="TransformFile" 
   Condition="'$(CustomTransforms)'=='true'" />
4 голосов
/ 21 марта 2011

Ответ Тейлора на меня не сработал, и он не предоставил подробностей.Поэтому я начал изучать файл Microsoft.Web.Publishing.targets , чтобы найти решение.Следующая MSBuild Target может быть добавлена ​​в файл проекта для преобразования всех других файлов конфигурации в корневой каталог приложения.Наслаждайтесь:)

<Target Name="TransformOtherConfigs" AfterTargets="CollectWebConfigsToTransform">
<ItemGroup>
    <WebConfigsToTransform Include="@(FilesForPackagingFromProject)"
                           Condition="'%(FilesForPackagingFromProject.Extension)'=='.config'"
                           Exclude="*.$(Configuration).config;$(ProjectConfigFileName)">
    <TransformFile>%(RelativeDir)%(Filename).$(Configuration).config</TransformFile>
    <TransformOriginalFile>$(TransformWebConfigIntermediateLocation)\original\%(DestinationRelativePath)</TransformOriginalFile>
    <TransformOutputFile>$(TransformWebConfigIntermediateLocation)\transformed\%(DestinationRelativePath)</TransformOutputFile>
    <TransformScope>$([System.IO.Path]::GetFullPath($(_PackageTempDir)\%(DestinationRelativePath)))</TransformScope>
  </WebConfigsToTransform>
  <WebConfigsToTransformOuputs Include="@(WebConfigsToTransform->'%(TransformOutputFile)')" />
</ItemGroup>
</Target>
2 голосов
/ 03 февраля 2011

Краткий ответ: Да, вы можете. Но это "сложно".

Длинный ответ: При развертывании сайтов по назначению у нас были обычные web.test.config и web.prod.config. Это работало нормально, пока мы не представили log4net.test.config и log4net.prod.config. MSBuild не будет автоматически проходить и заменять все это. Это будет делать только web.config.

Если вы хотите, чтобы все было в порядке, перейдите к последнему фрагменту кода. Он показывает функции, чтобы взять один конфиг и заменить его на замену. Но ... это будет иметь больше смысла, если я опишу весь процесс.

Процесс:

  1. Msbuild создает пакет zip-файлов сайта.
  2. Мы написали специальное приложение .net, которое возьмет этот zip-файл и выполнит замену конфигурации для каждого из файлов. Восстановите почтовый файл.
  3. Выполните команду msdeploy для развертывания упакованного файла.

MSbuild не будет автоматически заменять все дополнительные настройки. Что интересно, MSBuild удалит все «лишние» конфиги. Таким образом, ваш log4net.test.config исчезнет после сборки. Поэтому первое, что вам нужно сделать, это сказать msdbuild, чтобы эти дополнительные файлы оставались на месте.

Вы должны изменить свой файл vbProj, чтобы включить новый параметр:

<AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>

Откройте файл vbProj для веб-приложения в своем любимом текстовом редакторе. Перейдите к каждой конфигурации развертывания, к которой вы хотите применить эту настройку (release, prod, debug и т. Д.) И добавьте эту конфигурацию в нее. Вот пример нашего «релизного» конфига.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <DefineDebug>false</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DocumentationFile>Documentation.xml</DocumentationFile>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022,42353,42354,42355</NoWarn>
    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
    <DeployIisAppPath>IISAppPath</DeployIisAppPath>
    <AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>
  </PropertyGroup>
  ...
</Project>

Так что теперь msbduild создаст проект и сохранит эти дополнительные файлы на месте, а не заменит их. Теперь вы должны сделать их вручную.

Мы написали приложение .net, которое будет следить за этими новыми файлами zip. Я написал некоторый код, который прокручивает весь zip-пакет и находит все конфиги, которые соответствуют {configname}. {Env} .config. Он извлечет их, заменит их и вернет обратно. Для фактической замены мы используем те же DLL, что и MSDeploy. Я также использую Ionic.Zip, чтобы делать вещи из почтового индекса.

Добавьте ссылку на:

Microsoft.Build.dll
Microsoft.Build.Engine.dll
Microsoft.Web.Publishing.Tasks (possibly, not sure if you need this or not)

Импорт:

Imports System.IO
Imports System.Text.RegularExpressions
Imports Microsoft.Build.BuildEngine
Imports Microsoft.Build 

Вот код, который вращается через zip-файл

specificpackage = "mypackagedsite.zip"
configenvironment = "DEV" 'stupid i had to pass this in, but it's the environment in web.dev.config

Directory.CreateDirectory(tempdir)

Dim fi As New FileInfo(specificpackage)

'copy zip file to temp dir   
Dim tempzip As String = tempdir & fi.Name

File.Copy(specificpackage, tempzip)

''extract configs to merge from file into temp dir
'regex for the web.config 
'regex for the web.env.config
'(?<site>\w+)\.(?<env>\w+)\.config$

Dim strMainConfigRegex As String = "/(?<configtype>\w+)\.config$"
Dim strsubconfigregex As String = "(?<site>\w+)\.(?<env>\w+)\.config$"
Dim strsubconfigregex2 As String = "(?<site>\w+)\.(?<env>\w+)\.config2$"

Dim MainConfigRegex As New Regex(strMainConfigRegex, RegexOptions.Compiled Or RegexOptions.IgnoreCase)
Dim SubConfigRegex As New Regex(strsubconfigregex, RegexOptions.Compiled Or RegexOptions.IgnoreCase)
Dim SubConfigRegex2 As New Regex(strsubconfigregex2, RegexOptions.Compiled Or RegexOptions.IgnoreCase)

Dim filetoadd As New Dictionary(Of String, String)
Dim filestoremove As New List(Of ZipEntry)
Using zip As ZipFile = ZipFile.Read(tempzip)
    For Each entry As ZipEntry In From a In zip.Entries Where a.IsDirectory = False
        For Each myMatch As Match In MainConfigRegex.Matches(entry.FileName)
            If myMatch.Success Then
                'found main config. 
                're-loop through, find any that are in the same dir as this, and also match the config name
                Dim currentdir As String = Path.GetDirectoryName(entry.FileName)
                Dim conifgmatchname As String = myMatch.Groups.Item("configtype").Value

                For Each subentry In From b In zip.Entries Where b.IsDirectory = False _
                                     And UCase(Path.GetDirectoryName(b.FileName)) = UCase(currentdir) _
                                     And (UCase(Path.GetFileName(b.FileName)) = UCase(conifgmatchname & "." & configenvironment & ".config") Or
                                          UCase(Path.GetFileName(b.FileName)) = UCase(conifgmatchname & "." & configenvironment & ".config2"))

                    entry.Extract(tempdir)
                    subentry.Extract(tempdir)

                    'Go ahead and do the transormation on these configs
                    Dim newtransform As New doTransform
                    newtransform.tempdir = tempdir
                    newtransform.filename = entry.FileName
                    newtransform.subfilename = subentry.FileName
                    Dim t1 As New Threading.Tasks.Task(AddressOf newtransform.doTransform)
                    t1.Start()
                    t1.Wait()
                    GC.Collect()
                    'sleep here because the build engine takes a while. 
                    Threading.Thread.Sleep(2000)
                    GC.Collect()

                    File.Delete(tempdir & entry.FileName)
                    File.Move(tempdir & Path.GetDirectoryName(entry.FileName) & "/transformed.config", tempdir & entry.FileName)
                    'put them back into the zip file
                    filetoadd.Add(tempdir & entry.FileName, Path.GetDirectoryName(entry.FileName))
                    filestoremove.Add(entry)
                Next
            End If
        Next
    Next

    'loop through, remove all the "extra configs"
    For Each entry As ZipEntry In From a In zip.Entries Where a.IsDirectory = False

        Dim removed As Boolean = False

        For Each myMatch As Match In SubConfigRegex.Matches(entry.FileName)
            If myMatch.Success Then
                filestoremove.Add(entry)
                removed = True
            End If
        Next
        If removed = False Then
            For Each myMatch As Match In SubConfigRegex2.Matches(entry.FileName)
                If myMatch.Success Then
                    filestoremove.Add(entry)
                End If
            Next
        End If
    Next

    'delete them
    For Each File In filestoremove
        zip.RemoveEntry(File)
    Next

    For Each f In filetoadd
        zip.AddFile(f.Key, f.Value)
    Next
    zip.Save()
End Using

Наконец, но самое главное, где мы на самом деле делаем замену web.configs.

Public Class doTransform
    Property tempdir As String
    Property filename As String
    Property subfilename As String
    Public Function doTransform()
        'do the config swap using msbuild
        Dim be As New Engine
        Dim BuildProject As New BuildEngine.Project(be)
        BuildProject.AddNewUsingTaskFromAssemblyFile("TransformXml", "$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll")
        BuildProject.Targets.AddNewTarget("null")
        BuildProject.AddNewPropertyGroup(True)
        DirectCast(BuildProject.PropertyGroups(0), Microsoft.Build.BuildEngine.BuildPropertyGroup).AddNewProperty("GenerateResourceNeverLockTypeAssemblies", "true")

        Dim bt As BuildTask
        bt = BuildProject.Targets("null").AddNewTask("TransformXml")

        bt.SetParameterValue("Source", tempdir & filename)
        bt.SetParameterValue("Transform", tempdir & subfilename)
        bt.SetParameterValue("Destination", tempdir & Path.GetDirectoryName(filename) & "/transformed.config")
        'bt.Execute()
        BuildProject.Build()
        be.Shutdown()

    End Function

End Class

Как я уже сказал ... это сложно, но это можно сделать.

1 голос
/ 20 октября 2016

Просто для добавления в этот awnser, чтобы изменить другие файлы, кроме web.config в приложении, опубликованном с помощью msdeploy (webdeploy), вы можете установить атрибут scope в файле parameters.xml в корне проекта. :

<parameters>
  <parameter name="MyAppSetting" defaultvalue="_defaultValue_">
    <parameterentry match="/configuration/appSettings/add[@key='MyAppSetting']/@value" scope=".exe.config$" kind="XmlFile">
    </parameterentry>
  </parameter>
</parameters>

scope - это регулярное выражение, которое будет использоваться для поиска файлов, к которым применяется match xpath. Я не экспериментировал с этим подробно, но, насколько я понимаю, он просто заменяет то, что когда-либо совпадает с xpath, значением, предоставленным позже.

Существуют также другие значения, которые можно использовать для kind, которые будут вести себя иначе, чем xpath, см. https://technet.microsoft.com/en-us/library/dd569084(v=ws.10).aspx для подробностей

примечание: это относится к случаям, когда вы используете файл parameters.xml, а не к файлам web.config.Debug / Release

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