从Perl脚本中执行PowerShell脚本

4
我是一名能翻译文本的有用助手。

我正在尝试从Perl脚本中执行一个PowerShell脚本,但遇到了一些错误。该脚本作为Windows服务在Windows Server 2012中运行。我想要做的是确定用户是否拥有Exchange邮箱。之前的Perl代码可以连接到Exchange 2003,已经运行多年。现在我们正在升级到Exchange 2013,并需要更新代码以调用PowerShell脚本执行此任务。PowerShell脚本将检查用户是否拥有邮箱并返回字符串(如果有)。

Perl 代码

sub mailboxExists
{
  my ($argstr) = @_;
  my ($username) = parseArgs($argstr);

  # Get the user's dn
  my $dn = userExists($username);
  if(!$dn)
  {
    print $CLIENT "ERR User does not exist, so mailbox can not\n";
    return undef;
  }

  # Search

  $result = 'C:\Windows\System32\PowerShell\v1.0\powershell.exe -command "C:\LDIAD\PS\mailboxExists.ps1 $username"';
}

PowerShell脚本 - 目前正在使用Exchange 2007进行测试,因为我们还没有部署2013,但代码大部分相同。

#Add the Exchange 2007 snapins
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Support

#Start the script
$user = Get-User -Identity $username
If ($user.RecipientType -eq "UserMailbox")
{
"1"
}
Else
{
"0"
}

PowerShell代码可以正常工作,我认为问题在于Perl中调用PS脚本的命令?我的Perl知识非常有限。这是一位已经离开的员工的代码。我只添加了应该执行PowerShell脚本的那一行。


简短回答:使用反引号,例如 $result = `command`; 来执行 command - 但是有比这更灵活、更安全的方法。 - amon
你能分享更灵活、更安全的方法吗?我非常乐意听取建议,以使其更好。 - Kenny
4个回答

1
单引号、双引号和反引号在Perl中具有不同且特定的含义,混淆它们会导致程序出现意外行为。
对于"双引号"内的文本,Perl会插值变量并重新解释前面带有反斜杠的字符。
$foo = "bar";
print "\t$foo\n";       # outputs:  <TAB> bar <NEWLINE>

'单引号' 内,Perl 不会插值变量,并且将反斜杠视为字面上的反斜杠字符,除非它后面跟着另一个反斜杠或单引号字符。使用它们告诉 Perl 字面地处理引号内的文本。
$foo = "bar";
print '\t$foo\n';       # outputs: <BACKSLASH> t <DOLLAR> foo <BACKSLASH> n

对于反引号内的文本(抱歉,标记不可用),Perl会执行两个操作。 (1) 将字符串重新解释为双引号内的内容(插入变量,替换转义字符序列),以及 (2) 将结果作为要运行的命令传递给操作系统,并返回命令的输出。
$foo = "bar";
print `ls /tmp/$foo 2>&1`;
# possible output:    ls: cannot access /tmp/bar: No such file or directory


回到最初的问题:您希望运行该命令。
C:\Windows\System32\PowerShell\v1.0\powershell.exe -command "C:\LDIAD\PS\mailboxExists.ps1 $username"

在您的操作系统中,将"$username"替换为Perl变量$username的字符串值,并且您想要将该命令的输出分配给变量$result。以下是一些实现此目的的方法:

  1. 使用插值反引号,对\进行转义

    $result = `C:\\Windows\\System32\\PowerShell\\v1.0\\powershell.exe -command "C:\\LDIAD\\PS\\mailboxExists.ps1 $username"`;
  2. 使用单引号将字面字符串分配给临时变量

    my $powershell = 'C:\Windows\System32\PowerShell\v1.0\powershell.exe';
    my $mboxScript = 'C:\LDIAD\PS\mailboxExists.ps1';
    $result = `$powershell -command "$mboxScript $username"`;

0
在Windows 7上,以下操作是有效的。 需要进行大量清理工作,但目前对我来说还可以。
$constant = "C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe";
$param1 = " -psc ";
$param2 = "\"C:\\Program\ Files\ (x86)\\VMware\\Infrastructure\\vSphere\ PowerCLI\\vim.psc1\" -noe -c";
$param3 = " \". \\\"C:\\Program\ Files\ (x86)\\VMware\\Infrastructure\\vSphere\ PowerCLI\\Scripts\\Initialize-PowerCLIEnvironment.ps1\\\"\"";

$test = $param1.$param2.$param3;
open (IN, "| \"$constant\" $test") or die "$!";

欢迎来到 Stack Overflow。请阅读 Stack Overflow:如何回答问题 - Our Man in Bananas

0

尝试像这样运行

$scriptpath="C:\LDIAD\PS\mailboxExists.ps1 $username";
$exepath = "C:\Windows\System32\PowerShell\v1.0\powershell.exe";

然后使用以下任一方法

$result = `$exepath -File $scriptpath`;

或者

system("$exepath -File $scriptpath");

0

我有一个解析用户名并创建登录OU等的Perl程序,有类似的想法。作为运行和获取ls输出的测试,我不得不将双反斜杠转换为反斜杠,这起作用了。我将尝试使用New-ADUser进行类似的操作...

print "\n\n\nTrying powershell.exe -command ls\n--------------------------------\n";
open(CMD,"C:\\Windows\\System32\\WindowsPowershell\\v1.0\\powershell.exe -command ls|");
while(<CMD>) {
    chop($_);
    print "$_\n";
}
close(CMD);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接