使用msdeploy转换文件

时间:2011-01-20 17:00:57

标签: msdeploy webdeploy

我可以使用MSDeploy的配置转换机制来转换其他文件吗?

4 个答案:

答案 0 :(得分:5)

(另一种方法)

msdeploy打包是在项目的MSbuild运行期间调用的jsut。

TransformXml 是.csproj或.vsproj版本的附带任务。

只需修改构建过程即可在您需要的任何文件上调用该任务。

例如,我们所做的是编写自定义目标

<Target Name="TransformFile">

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

然后修改.csproj以在调用Publish任务之前运行它。

<CallTarget Targets="TransformFile" 
   Condition="'$(CustomTransforms)'=='true'" />

答案 1 :(得分:4)

泰勒的答案对我不起作用,他没有提供进一步的细节。所以我深入研究 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 :(得分:2)

简短回答:是的,你可以。但这很“困难”。

答案很长: 当我们将站点部署到目的地时,我们有通常的web.test.config和web.prod.config。在我们引入log4net.test.config和log4net.prod.config之前,这很好用。 MSBuild不会自动完成并替换所有这些。它只会执行web.config。

如果你想要细节,请转到最后一段代码片段。它显示了采用一个配置并将其替换为替换的功能。但是......如果我描述整个过程会更有意义。

流程:

  1. Msbuild制作该网站的zip文件包。
  2. 我们编写了一个自定义.net应用程序,它将获取该zip文件并对每个文件执行配置替换。重新保存zip文件。
  3. 执行msdeploy命令以部署打包文件。
  4. MSbuild不会自动替换所有额外的配置。有趣的是,MSBuild将删除任何“额外”配置。所以你的log4net.test.config将在它构建之后消失。所以你要做的第一件事就是告诉msdbuild保留那些额外的文件。

    您必须修改vbProj文件以包含新设置:

    <AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>
    

    将Web应用程序的vbProj文件打开到您喜欢的文本编辑器中。导航到您希望其应用的每个部署配置(发布,生产,调试等),并将该配置添加到其中。这是我们的“发布”配置的一个例子。

    <?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匹配的任何配置。它将提取它们,替换它们并将它们放回去。要进行实际替换,我们使用MSDeploy使用的相同DLL。我也用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
    
    像我说的那样......很难,但可以做到。

答案 3 :(得分:1)

只是要添加到此awnser,为了修改使用msdeploy(webdeploy)发布的应用程序中的web.config之外的其他文件,您可以在parameters.xml文件的根目录中设置scope属性。该项目:

<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文件