【问题标题】:Call powershell script in post-built with parameters使用参数在后期构建中调用 powershell 脚本
【发布时间】:2011-06-27 18:09:25
【问题描述】:

我正在尝试让 Powershell 在构建后运行我的 PS 脚本 - 但不知何故,它并没有像预期的那样工作:

构建后的以下命令:

C:\WINDOWS\system32\windowspowershell\1.0\powershell.exe
  -Command "& $(MSBuildProjectDirectory)\CreateSite.ps1 'auto'"

(插入换行符以便于阅读)

该命令成功执行了powershell脚本,但它不能做的是运行(从构建输出)中的命令: Rund 构建后命令:

Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 2
At C:\path\CreateSite.ps1:4 char:
38
+ Add-PsSnapin <<<< Microsoft.SharePoint.PowerShell}
+ CategoryInfo : InvalidArgument: (Microsoft.SharePoint.PowerShell:String) [Add-PSSnapin], PSArgumentException
+ FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand

然后出现很多错误,因为所有后续命令都需要 Sharepoint 管理单元。

  • 从 cmd 运行 powershell C:\path\CreateSite.ps1 auto 时 - 一切正常。
  • 打开 powershell.exe 并运行 C:\path\CreateSite.ps1 auto - 一切正常。
  • 右键单击 CreateSite.ps1 --> 使用 powershell 运行 - 一切正常。

脚本中的相关行只是Add-PsSnapin Microsoft.SharePoint.PowerShell

我怎样才能只运行该死的脚本(并让它包含 PSSnapIn)在 Visual Studio 后期构建中传递一个参数?

【问题讨论】:

    标签: visual-studio-2010 powershell sharepoint-2010 build-process


    【解决方案1】:

    当您直接运行脚本时,您可能使用 32 位 PowerShell,而在您的 msbuild 脚本中使用 64 位,反之亦然。也可以看看Error msg: “No snap-ins have been registered for Windows PowerShell version 2.”

    【讨论】:

    • 他正在运行 64 位 PowerShell(这将是 64 位操作系统的默认设置)。
    • 我已经阅读了有关 64 位/32 位争议的信息,这就是为什么我使用直接路径 C:\windows\system32\... 到 64 位版本的 powershell 而不是通向 32 位 PowerShell 的 SysWOW64 路径。它与使用“任何 CPU”而不是 x64 构建项目有什么关系吗?
    • 您使用什么版本的 msbuild - 64 位还是 32 位?
    • 从获得虚拟化文件系统访问权限的 32 位应用程序,路径 C:\windows\system32` is remapped to C:\Windows\SysWow64`。
    【解决方案2】:

    由于文件系统虚拟化,您无法真正指定从 32 位进程(即 Visual Studio - 托管 msbuild 引擎)到 64 位版本 PowerShell 的路径。解决此问题的一种 hack-ish 方法是创建一个 64 位启动器,该启动器以 64 位运行,并将启动 64 位版本的 PowerShell。这是一个简单的 C# 程序,可以做到这一点:

    using System;
    using System.Diagnostics;
    
    class App
    {
      static int Main(string[] args)
      {
        Process process = Process.Start("PowerShell.exe", String.Join(" ", args));
        process.WaitForExit();
        return process.ExitCode;
      }
    }
    

    请务必像这样将其编译为 64 位:

    csc .\PowerShell64.cs /platform:x64
    

    然后,从您的构建后事件执行此启动器 exe,将您要调用 64 位 PowerShell 的参数传递给它。此外,对于 PowerShell 2.0,我建议使用 File 参数来执行脚本,例如:

    c:\path\PowerShell64.exe -File "$(MSBuildProjectDirectory)\CreateSite.ps1" auto
    

    也就是说,肯定有其他方式(实用程序)可以从 64 位进程启动 exe。

    【讨论】:

    • 先生,这非常很有趣,而且完美无瑕! (但无需使用 csc.exe - 将目标平台设置为 x64 就足够了)
    【解决方案3】:

    输出重定向的稍微好一点的变体:

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class App
        {
            static int Main(string[] args)
            {
                Console.WriteLine("sh64 args: " + string.Join(", ", args));
                var start = new ProcessStartInfo
                    {
                        FileName = args.First(),
                        Arguments = string.Join(" ", args.Skip(1).ToArray()),
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true,
                        RedirectStandardInput = false,
                        CreateNoWindow = true
                    };
    
                using (var process = Process.Start(start))
                {
                    while (!process.HasExited)
                    {
                        using (var reader = process.StandardOutput)
                            Drain(reader, false);
                        using (var reader = process.StandardError)
                            Drain(reader, true);
                    }
                    process.WaitForExit();
                    return process.ExitCode;
                }
            }
    
            static void Drain(TextReader reader, bool error)
            {
                ColourizeError(error, () =>
                    {
                        var buf = new char[256];
                        int read;
                        while ((read = reader.Read(buf, 0, buf.Length)) != 0)
                            Console.Write(new string(buf, 0, read));
                    });
            }
    
            static void ColourizeError(bool error, Action a)
            {
                var prev = Console.ForegroundColor;
                Console.ForegroundColor = error ? ConsoleColor.Red : ConsoleColor.White;
                var mre = new ManualResetEventSlim(false);
                try
                {
                    a();
                }
                finally
                {
                    Console.ForegroundColor = prev;
                    mre.Set(); // runs on GC thread on servers and is reentrant/interleaved concurrency in workstations!
                }
                mre.Wait();
            }
        }
    }
    

    拨打sh64 powershell -File ./buildscripts/deploy.ps1 -Ex RemoteSigned

    【讨论】:

    • 您确定要在此处发帖吗?这个问题是关于在 64 位而不是 32 位上运行 Powershell - 你如何从那里获得输出重定向?
    • 因为如果尝试创建 CI 环境,就会遇到问题。在 CI 环境中,我们需要能够从 PS 获取输出作为构建的一部分。因此我们需要修复这个线程以及输出重定向。
    • 非常好。 CI 确实如此。我仍然认为它与这个问题有些无关,人们很可能不会找到你的答案;-)
    • 没关系,我只是想添加它,因为这就是我自己提出这个问题的原因。
    【解决方案4】:

    (这个帖子不是新的,但我是从谷歌上来的,所以我认为分享我发现的解决方案会对其他人感兴趣)

    我尝试将 powershell.exe 的路径更改为“%WINDIR%\SysNative\WindowsPowerShell\v1.0\powershell.exe”,效果很好。从 Post Build 事件调用 64 位版本,它成功添加了 SharePoint 管理单元。

    本文致谢:http://msdn.microsoft.com/en-us/library/ff798298.aspx,“使用 Windows PowerShell 脚本在 Visual Studio 中自动执行任务”。

    【讨论】:

    • +1 非常优雅且实际正确的解决方案!谢谢分享。
    • 我的 Jenkins 奴隶拒绝通过我尝试过的所有其他方式在 64 位进程中执行 Powershell,但您的解决方案有效!
    【解决方案5】:

    添加带有此内容的 cmd 文件(例如 run-script.cmd):

    @echo 关闭 设置 pspath=%windir%\Sysnative\WindowsPowerShell\v1.0 如果不存在 %pspath%\powershell.exe 设置 pspath=%windir%\System32\WindowsPowerShell\v1.0 %pspath%\powershell.exe -ExecutionPolicy RemoteSigned %*

    并以这种方式从构建事件中调用它:

    $(SolutionDir)scripts\run-script.cmd $(SolutionDir)scripts\restore-default-file.ps1 -source $(ProjectDir)App_Data\Configs\Mip.Security.Sample.config -destination $(ProjectDir)App_Data\Configs \Mip.Security.config

    【讨论】:

      猜你喜欢
      • 2020-12-04
      • 2012-05-02
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      相关资源
      最近更新 更多