【问题标题】:How to run a PowerShell script from a batch file如何从批处理文件运行 PowerShell 脚本
【发布时间】:2013-10-20 12:42:08
【问题描述】:

我正在尝试在 PowerShell 中运行此脚本。我已在桌面上将以下脚本保存为ps.ps1

$query = "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"
Register-WMIEvent -Query $query -Action { invoke-item "C:\Program Files\abc.exe"}

我已经制作了一个批处理脚本来运行这个 PowerShell 脚本

@echo off
Powershell.exe set-executionpolicy remotesigned -File  C:\Users\SE\Desktop\ps.ps1
pause

但我收到此错误:

【问题讨论】:

  • 请注意,如果在从 PowerShell 中调用脚本时有效的脚本执行这样的古怪错误,您可能需要在 bat 文件中使用 pwsh.exe 而不是 powershell.exe。快速解释:powershell.exe 是 v5.1-,pwsh.exe 是 6.0+。 More here.

标签: windows shell powershell batch-file


【解决方案1】:

你需要-ExecutionPolicy参数:

Powershell.exe -executionpolicy remotesigned -File  C:\Users\SE\Desktop\ps.ps1

否则 PowerShell 将参数视为要执行的行,而 Set-ExecutionPolicy cmdlet,它没有 -File 参数。

【讨论】:

  • 您是否必须以管理员身份运行才能更改执行策略?因为我认为它会更改注册表中的条目
  • @KolobCanyon:要更改它,您需要成为管理员,是的。不过,上面并没有改变它,它只是为给定实例指定了它的执行策略应该是什么。
  • @Joey 哈哈,因此您无需成为管理员即可有效地覆盖此策略。这是一个安全问题吗?
  • @KolobCanyon:如果您处于可以运行 PowerShell 的位置,那么您几乎可以执行其他所有操作。请注意,执行策略并不意味着 PowerShell 拥有比其他方式更多的权限。在某种程度上,它只是为了方便避免意外运行您可能不想运行的东西。类似于必须在当前目录中为命令添加前缀 ./ 并在 Unix 上具有可执行标志。
【解决方案2】:

我解释了为什么要从批处理文件中调用 PowerShell 脚本以及如何做到这一点in my blog post here

这基本上就是你要找的东西:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\Users\SE\Desktop\ps.ps1'"

如果您需要以管理员身份运行 PowerShell 脚本,请使用以下命令:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""C:\Users\SE\Desktop\ps.ps1""' -Verb RunAs}"

不过,我建议将批处理文件和 PowerShell 脚本文件放在同一目录中,而不是硬编码 PowerShell 脚本的整个路径,正如我的博文所述。

【讨论】:

  • 当我在 cmd 窗口中键入命令行时,Invoke-WebRequest 工作正常,但每当我从批处理文件中运行它时返回 404。我正在尝试PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass Invoke-WebRequest https://www.example.com/example.ics -OutFile C:\_my\script.ics' -Verb RunAs}";powershell -Command "Invoke-WebRequest https://www.example.com/example.ics -OutFile c:\_my\file.ics",或者在.ps1 文件或(New-Object Net.WebClient).DownloadFile 中使用相同的-File 选项。有什么想法吗?
  • 尝试使用 -ExecutionPolicy Unrestricted。我猜 Bypass 选项不会提供 PowerShell 网络访问权限。
  • @Belun 引用的博客文章显示了如何将参数传递给脚本。
【解决方案3】:

如果你想在没有完全限定路径的情况下从当前目录运行,你可以使用:

PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& './ps.ps1'"

【讨论】:

    【解决方案4】:

    如果您以管理员身份运行调用 PowerShell 的批处理文件,最好这样运行,省去所有麻烦:

    powershell.exe -ExecutionPolicy Bypass -Command "Path\xxx.ps1"
    

    最好用Bypass...

    【讨论】:

      【解决方案5】:

      小样test.cmd

      <# :
        @echo off
          powershell /nologo /noprofile /command ^
               "&{[ScriptBlock]::Create((cat """%~f0""") -join [Char[]]10).Invoke(@(&{$args}%*))}"
        exit /b
      #>
      Write-Host Hello, $args[0] -fo Green
      #You programm...
      

      【讨论】:

      • 非常酷的把戏。 [Char[]]10 是什么?它有什么限制吗?
      【解决方案6】:

      也在这里发布: How to run powershell command in batch file

      关注这个帖子:
      https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/converting-powershell-to-batch


      您可以使用此 PowerShell 函数轻松地将任何 PowerShell 脚本转换为批处理文件:

      function Convert-PowerShellToBatch
      {
          param
          (
              [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
              [string]
              [Alias("FullName")]
              $Path
          )
       
          process
          {
              $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
              $newPath = [Io.Path]::ChangeExtension($Path, ".bat")
              "@echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
          }
      }
      


      要转换目录中的所有 PowerShell 脚本,只需运行以下命令:

      Get-ChildItem -Path <DIR-PATH> -Filter *.ps1 |
        Convert-PowerShellToBatch
      

      所需文件夹的路径在哪里。例如:

      Get-ChildItem -Path "C:\path\to\powershell\scripts" -Filter *.ps1 |
        Convert-PowerShellToBatch
      


      要转换 单个 PowerShell 脚本,只需运行以下命令:

      Get-ChildItem -Path <FILE-PATH> |
        Convert-PowerShellToBatch
      

      所需文件的路径在哪里。

      转换后的文件位于源目录中。即,

      把它们放在一起:
      创建一个 .ps1 文件(PowerShell 脚本),其中包含以下代码:

      function Convert-PowerShellToBatch
      {
          param
          (
              [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
              [string]
              [Alias("FullName")]
              $Path
          )
       
          process
          {
              $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
              $newPath = [Io.Path]::ChangeExtension($Path, ".bat")
              "@echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
          }
      }
      
      # change <DIR> to the path of the folder in which the desired powershell scripts are.
      # the converted files will be created in the destination path location (in <DIR>).
      Get-ChildItem -Path <DIR> -Filter *.ps1 |
        Convert-PowerShellToBatch
      


      别忘了,如果你只想转换一个文件而不是多个文件,你可以替换下面的

      Get-ChildItem -Path <DIR> -Filter *.ps1 |
        Convert-PowerShellToBatch
      

      用这个:

      Get-ChildItem -Path <FILE-PATH> |
        Convert-PowerShellToBatch
      

      正如我之前解释的那样。

      【讨论】:

        【解决方案7】:

        如果你想运行几个脚本,你可以使用Set-executionpolicy -ExecutionPolicy Unrestricted,然后用Set-executionpolicy -ExecutionPolicy Default重置。

        请注意,只有在您开始执行(或看起来如此)时才会检查执行策略,因此您可以在后台运行作业并立即重置执行策略。

        # Check current setting
        Get-ExecutionPolicy
        
        # Disable policy
        Set-ExecutionPolicy -ExecutionPolicy Unrestricted
        # Choose [Y]es
        
        Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 example.com | tee ping__example.com.txt }
        Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 google.com  | tee ping__google.com.txt  }
        
        # Can be run immediately
        Set-ExecutionPolicy -ExecutionPolicy Default
        # [Y]es
        

        【讨论】:

          【解决方案8】:

          另一种从批处理执行 ps 脚本的简单方法是将其简单地合并到 ECHO 和重定向字符之间(> 和 >>), 示例:

          @echo off
          set WD=%~dp0
          ECHO New-Item -Path . -Name "Test.txt" -ItemType "file" -Value "This is a text string." -Force > "%WD%PSHELLFILE.ps1"
          ECHO add-content -path "./Test.txt" -value "`r`nThe End" >> "%WD%PSHELLFILE.ps1"
          powershell.exe -ExecutionPolicy Bypass -File "%WD%PSHELLFILE.ps1"
          del "%WD%PSHELLFILE.ps1"
          

          最后一行删除创建的临时文件。

          【讨论】:

            【解决方案9】:

            如果您的 PowerShell 登录脚本在 2012 年服务器上运行 5 分钟后(如我的那样),则服务器上有一个 GPO 设置 - '配置登录脚本延迟' 默认设置 '未配置' 这将留下 5 - 运行登录脚本前的一分钟延迟。

            【讨论】:

              猜你喜欢
              • 2012-10-20
              • 1970-01-01
              • 1970-01-01
              • 2013-02-18
              • 2013-07-30
              • 2015-01-03
              • 2020-03-22
              • 2011-06-15
              • 1970-01-01
              相关资源
              最近更新 更多