Преобразование файлов с помощью msdeploy
Вопрос
Могу ли я использовать механизм преобразования конфигурации MSDeploy для преобразования других файлов?
Решение
(Другой подход)
Упаковка MSDeploy приводится в эксплуатацию во время пробега MSBuild для вашего проекта.
Transformxml является включенной задачей .csproj или .vsproj сборка.
Просто измените процесс сборки, чтобы вызвать эту задачу в любой файл, который вам нужен.
Например, мы пишем пользовательскую цель
<Target Name="TransformFile">
<TransformXml Source="$(DestinationPath)\$(Sourcefile)"
Transform="$(DestinationPath)\$(TransformFile)"
Destination="$(DestinationPath)\$(DestFile)" />
</Target>
Затем измените свой.
<CallTarget Targets="TransformFile"
Condition="'$(CustomTransforms)'=='true'" />
Другие советы
Ответ Тейлора не работал для меня, и он не предоставил дополнительных подробностей. Итак, я пошел в Microsoft.Web.Publishing.Targets Файл, чтобы найти решение. Следующая MSBuild Target
может быть добавлен в файл проекта, чтобы преобразовать все другие файлы конфигурации в каталоге Root Application. Наслаждаться :)
<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>
Короткий ответ: Да, ты можешь. Но это "сложно".
Длинный ответ: Когда мы развертываем сайты в пункты назначения, у нас был обычный web.test.config и web.prod.config. Это работало нормально, пока мы не представили log4net.test.config и log4net.prod.config. MSBuild не будет автоматически проходить и заменить все это. Он будет делать только Web.Config.
Если вы хотите, чтобы Nitty Gritty перейти к последнему фрагменту кода. Он показывает функции, чтобы взять одну конфигурацию и заменить его на замену. Но ... это будет иметь больше смысла, если я опишу весь процесс.
Процесс:
- MSBUILD производит пакет файлов ZIP на сайте.
- Мы написали пользовательское приложение .NET, которое возьмет этот ZIP -файл и выполнит замену конфигурации в каждом из файлов. Поменить файл ZIP.
- Выполните команду MSDEPLOY, чтобы развернуть упакованный файл.
MSBuild не будет автоматически заменить все дополнительные конфигурации. Что интересно, так это то, что MSBuild удалит любые «дополнительные» конфигурации. Таким образом, ваш log4net.test.config уйдет после его сборки. Так что первое, что вам нужно сделать, это сказать MSDBuild, чтобы сохранить эти дополнительные файлы на месте.
Вы должны изменить свой файл VBPROJ, чтобы включить новую настройку:
<AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>
Откройте свой файл VBPROJ для веб -приложения в ваш любимый текстовый редактор. Перейдите к каждой конфигурации развертывания, которую вы хотите, чтобы это также применило (выпуск, 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 и найдет любые конфигурации, которые соответствуют {contigname}. {Env} .config. Это извлечет их, заменит их и поставит обратно. Чтобы сделать фактическую замену, мы используем тот же DLL, который использует MSDeploy. Я также использую ionic.zip, чтобы сделать 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
Как я уже сказал ... это сложно, но это можно сделать.
Просто чтобы добавить к этому 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 to. Я не экспериментировал с этим тщательно, но, насколько я понимаю, это просто заменяет то, что когда -либо совпадает со значением, которое предоставлено позже.
Есть также и другие значения, которые можно использовать для kind
это будет иметь другое поведение, чем xpath, см. https://technet.microsoft.com/en-us/library/dd569084(v=ws.10).aspx Для деталей
Примечание. Это относится к тому, когда вы используете параметры. xml, а не при использовании файлов web.config.debug/lepred