iis - 从 Visual Studio Team Services 中的构建部署到私有(private) IIS 服务器

标签 iis deployment azure-devops azure-pipelines

完成此处建议的操作:Deploy from Visual Studio Online build to private IIS server ... 当我构建整个分支 **/*.sln 时,如何将自动部署设置为构建的一部分?

我试过的...

在 VS 中,我可以获得最新版本的代码,打开一个解决方案,然后...... 右键单击 > 发布 > 选择发布配置文件 > 部署

我将我的发布配置文件命名为“dev”、“qa”、“production”,这些指的是项目将部署到的环境,配置文件包含 VS 部署所需的所有配置信息(通过 webdeploy/msdeploy)使用“一键部署”该应用程序。

我想让构建服务器上的 Team Services 对在构建代码后定义了发布配置文件的项目执行完全相同的操作。

我的理解是我可以像这样添加 msbuild args ...

Build Step - With deploy

这导致构建的部署部分在构建日志中抛出以下异常......

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets(4288,5): 
Error ERROR_USER_NOT_ADMIN: Web deployment task failed. 
(Connected to 'server' using the Web Deployment Agent Service, but could not authorize. Make sure you are an administrator on 'server'. 
Learn more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_USER_NOT_ADMIN.)

如果不是发布配置文件中定义的用户,这使用的是什么用户?

相关问题:

我向有问题的服务器添加了一个帐户(因为构建和要部署的服务器是同一台服务器,这使事情变得更容易),我还向服务器添加了一个名为“MSDepSvcUsers”的组,并将新帐户添加到向它和盒子上的管理员组提问。

然后我告诉 Web Deployment Agent 服务和 Team Services Agent 服务在这个帐户下运行(并重新启动它们)。

不幸的是,结果是一样的……我现在真的很想知道如何确保用于 msdeploy 命令的帐户是我所期望的,而不依赖于大量脚本……或者这就是为什么 Microsoft尚未将其设置为 Team Services 中的默认部署步骤选项!

最佳答案

好吧,我与微软的 VSTS 团队就此进行了长时间的对话,总而言之......

微软:

We understand your frustration with this area and a big project is about to spin up to resolve this issue

...

我就是我,想出了一些“实现它的技巧”。

由于某些奇怪的原因,我设法弄清楚了构建框不能与您正在部署的服务器相同(不知道为什么),但在弄清楚这一点后,我编写了一个简单的控制台应用程序,并从中获得了一些额外的反馈微软表现不错。

它甚至可以将进度报告回流程,并且可以将部署中的异常记录为异常,以便通过调用“内部命令”来使构建失败(这对团队来说是如何工作的)。

这里有一些 hack,它并不完美,但希望它能帮助其他人,我这样调用它是因为它是在我的 repo 中构建的代码的一部分,所以我能够在构建过程中添加一个步骤从传递我要部署到的环境名称的构建输出中调用它。

这个实习生抓取所有包(按照上面的设置)并使用它们的发布配置文件来确定包需要去哪里并将它们发送到正确的服务器以进行部署...

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace Deploy
{
    class Program
    {
        static string msDeployExe = @"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";

        static void Main(string[] args)
        {
            var env = args[0];
            var buildRoot = Path.Combine(Assembly.GetExecutingAssembly().Location.Replace("Deploy.exe", ""), env);
            //var commands = GetCommands(buildRoot);
            var packages = new DirectoryInfo(buildRoot).GetFiles("*.zip", SearchOption.AllDirectories);

            bool success = true;
            for (int i = 0; i < packages.Length; i++)
            {
                if (!Deploy(packages[i], env)) success = false;
                Console.WriteLine("##vso[task.setprogress]" + (int)(((decimal)i / (decimal)packages.Length) * 100m));
            }

            Console.WriteLine("##vso[task.setprogress]100");

            if(success) Console.WriteLine("##vso[task.complete result=Succeeded]");
            else        Console.WriteLine("##vso[task.complete result=SucceededWithIssues]");
        }

        static bool Deploy(FileInfo package, string environment)
        {
            bool succeeded = true;
            Console.WriteLine("Deploying " + package.FullName);
            var procArgs = new ProcessStartInfo
            {
                FileName = msDeployExe,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                Arguments =
                    "-source:package='" + package.FullName + "' " +
                    "-dest:auto,ComputerName='" + environment + ".YourDomain.com',UserName='deployment user',Password='password',AuthType='ntlm',IncludeAcls='False' " +
                    "-verb:sync " +
                    "-disableLink:AppPoolExtension " +
                    "-disableLink:ContentExtension " +
                    "-disableLink:CertificateExtension " +
                    "-setParamFile:\"" + package.FullName.Replace("zip", "SetParameters.xml") + "\""
            };

            try
            {
                Console.WriteLine(msDeployExe + " " + procArgs.Arguments);
                using (var process = Process.Start(procArgs))
                {
                    var result = process.StandardOutput.ReadToEnd().Split('\n');
                    var error = process.StandardError.ReadToEnd();
                    process.WaitForExit();

                    if (!string.IsNullOrEmpty(error))
                    {
                        Console.WriteLine("##vso[task.logissue type=error]" + error);
                        succeeded = false;
                    }

                    foreach (var l in result)
                        if (l.ToLowerInvariant().StartsWith("error"))
                        {
                            Console.WriteLine("##vso[task.logissue type=error]" + l);
                            succeeded = false;
                        }
                        else
                            Console.WriteLine(l);
                }
            }
            catch (Exception ex) {
                succeeded = false;
                Console.WriteLine("##vso[task.logissue type=error]" + ex.Message);
                Console.WriteLine("##vso[task.logissue type=error]" + ex.StackTrace);
            }

            return succeeded;
        }
    }
}

关于iis - 从 Visual Studio Team Services 中的构建部署到私有(private) IIS 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38684714/

相关文章:

php exec() 挂起

iis - 如何获取 IIS_FailureTrace 目录中的 freb.xsl 文件

deployment - MsDeploy 虚拟目录在部署时转换为虚拟应用程序

python - 如何将 Django App 部署到 1and1 (ionos)

git - 使用 git 作为部署实用程序时的安全问题

azure - 如何针对 Visualstudio.com 进行身份验证?

azure - 如何从azure构建管道(CI)中的预定义变量获取拉取请求编号

azure - 在 azure-pipeline 中从 AZURE-ARTIFACT 获取 NPM 包时出现 404 错误?

c# - 删除子目录时IIS重新启动MVC3应用程序

windows - PHP 7.0.5 : Use of undefined constant FTP_BINARY - assumed 'FTP_BINARY'