Xp_CmdShell Powershell脚本找不到有效的模块

时间:2019-07-17 17:42:12

标签: sql-server powershell

我正在尝试使用XP_CMDSHELL在T-SQL中运行PS1文件,如下所示:

exec xp_cmdshell 'powershell -ExecutionPolicy bypass -command "C:\Users\sleven\Documents\DimAcctImport.ps1"'

powershell脚本如下:

import-module dbatools
Import-DbaCsv -SqlInstance 'MSSQL' -Database 'Test' -Table 'Account' -Path "R:\Data\Account.csv" -Delimiter ',' -Quote '"' -KeepNulls -NoProgress

此脚本使用模块Import-DbaCSV的cmdlet DbaTools将CSV导入目标表。

这是我在SSMS中收到的错误:

import-module : The specified module 'dbatools' was not loaded because no valid module file was found in any module 
directory.
At C:\Users\sleven\Documents\DimAcctImport.ps1:1 char:1
+ import-module dbatools
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (dbatools:String) [Import-Module], FileNotFoundException
    + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand

如果我复制PowerShell脚本并在PS ISE中运行该模块,则该模块将按预期安装并运行。

我正在与用于运行sp的本地PC在同一台PC上使用SQL Developer Edition。

我想念什么?

编辑:从get-module和$ PSVersionTable添加输出

PS> (Get-Module -ListAvailable dbatools).Path:
C:\Users\sleven\Documents\WindowsPowerShell\Modules\dbatools\0.9.834\dbatools.psd1

PS> $PSVersionTable

Name                           Value                                                                                                  
----                           -----                                                                                                  
PSVersion                      5.1.18362.145                                                                                          
PSEdition                      Desktop                                                                                                
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                
BuildVersion                   10.0.18362.145                                                                                         
CLRVersion                     4.0.30319.42000                                                                                        
WSManStackVersion              3.0                                                                                                    
PSRemotingProtocolVersion      2.3                                                                                                    
SerializationVersion           1.1.0.1 

2 个答案:

答案 0 :(得分:4)

使用Import-Module cmdlet告诉PowerShell仅在某些文件夹中查找cmdlet。您可以通过检查环境变量PSModulePath(添加分隔符以获得更好的可见性)来检查这些文件夹:

$env:PSModulePath -split ';'

在这种情况下,当通过xp_cmdshell运行PowerShell时,该文件夹不包括在PSModulePath中(如果您使用其他帐户,因为当前模块文件位于您的配置文件文件夹中,也可能会发生此文件夹)。现在,您有两个选择:

  1. 使用模块的路径而不是名称来引用模块。您可以使用(get-module -ListAvailable dbatools).path获取路径:
# Replace the path with the path you found with Get-Module
Import-Module 'C:\path\to\module\dbatools.psd1
  1. 修改您的$env:PSModulePath。由于该主题的范围更广,让我给您the link to the docs。请记住,您应该为运行xp_cmdshell的用户设置该变量。 As RThomas mentioned,默认情况下,它不是您的用户帐户。有关该主题的说明,请参见链接的答案。

注意(信用来自他的评论,@David Browne - Microsoft):

  

如果您要设置环境变量,则它应该是系统环境变量,因为如果您更改SQL Server服务帐户,您不会希望此过程中断。记住,设置系统环境变量需要重新引导服务才能看到更改。

答案 1 :(得分:2)

可能是帐户问题。请记住,默认情况下运行xp_cmdshell会将所有内容作为SQL Server实例后面的服务帐户运行。因此,您需要验证这是什么帐户。

如果它是内置的系统帐户,那么涉及权限时可能会导致奇怪的行为。

如果它是Windows帐户或域帐户,则需要通过运行PS文件而不是您本人而是以SQL Server用作服务帐户的同一帐户来对SQL Server进行外部测试。您可以通过使用shift /右键单击打开cmd shell并指定其他帐户来轻松地做到这一点。

您的另一个选择是为xp_cmdshell调用设置代理帐户以使用。 Instructions on how to do this can be found in Microsoft documentation.