2

我目前正在使用 .NET 3.5 / C# 开发执行自动化 Exchange 操作的 Windows 服务。该服务基本上监视 SQL 数据库以执行操作,然后生成 PowerShell 并重定向输出,以便可以从位于其他地方的 UI 监视结果。下面是我用来调用该过程的代码...

Action<object, DataReceivedEventArgs> DataReceived = (sender, data) =>
{
    // Log data in SQL
};
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "powershell.exe"
p.StartInfo.Arguments = arguments;

// Arguments are (they're coming from SQL, didn't feel like escaping everything just for this example)
// -command ". 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; Get-Mailbox –ResultSize unlimited | Search-Mailbox -SearchQuery ... stuff ...

p.StartInfo.LoadUserProfile = true;           
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.OutputDataReceived += new DataReceivedEventHandler(DataReceived);
p.Start();

这段代码可以执行诸如运行 ping、tracert、nslookup、echo、dir 以及所有常见的命令行嫌疑人之类的操作,其行为与我在命令提示符中键入它时的行为相同。例如,我可以将上面的内容复制粘贴到“运行”框中,它会完美运行。但是,每当我尝试按上述方式运行它时,我都会收到以下信息:

Get-ItemProperty : Cannot find path 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup' because it does not exist.
At C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:46 char:34
+ $global:exbin = (get-itemproperty <<<<  HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup).MsiInstallPath + "bin\"
    + CategoryInfo          : ObjectNotFound: (HKLM:\SOFTWARE\...erver\v14\Setup:String) [Get-ItemProperty], ItemNotFo 
    undException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand

Get-ItemProperty : Cannot find path 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup' because it does not exist.
At C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:47 char:38
+ $global:exinstall = (get-itemproperty <<<<  HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup).MsiInstallPath
    + CategoryInfo          : ObjectNotFound: (HKLM:\SOFTWARE\...erver\v14\Setup:String) [Get-ItemProperty], ItemNotFo 
    undException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand

Get-ItemProperty : Cannot find path 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup' because it does not exist.
At C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:48 char:38
+ $global:exscripts = (get-itemproperty <<<<  HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup).MsiInstallPath + "scri
pts\"
    + CategoryInfo          : ObjectNotFound: (HKLM:\SOFTWARE\...erver\v14\Setup:String) [Get-ItemProperty], ItemNotFo 
    undException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand

The term 'bin\CommonConnectFunctions.ps1' is not recognized as the name of a cmdlet, function, script file, or operable
    program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:52 char:2
+ . <<<<  $global:exbin"CommonConnectFunctions.ps1"
    + CategoryInfo          : ObjectNotFound: (bin\CommonConnectFunctions.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

在此之后会出现大量其他错误,但通过查看 RemoteExchange PowerShell 脚本,我确定这一切都归结为前三个错误:无法从注册表中读取。有谁知道为什么会发生这种情况?

我试图让它工作的事情:

  • 在控制台应用程序中运行此代码,而不是在服务上下文中。
  • 每次我运行它时,我都是作为域和 Exchange 管理员这样做的,但我从来没有收到过 UAC 提示,所以我怀疑问题是凭据之一
  • 检查注册表项...它正在查看的 HKLM 密钥也具有授予所有人的完全读取权限
  • 我在服务器上启用了未签名的 PowerShell 脚本执行
  • 将命令放入 PowerShell 脚本并以编程方式调用它
  • 将注册表项的值硬编码到 PowerShell 脚本中(这只是给了我另一组注册表读取错误进一步向下行)
  • 在进程上使用 ShellExecute(这不能通过输出重定向来完成,我需要)
  • 在 StartInfo 上显式设置环境变量以匹配生成环境中的环境变量

感谢任何可以帮助我的人...谢谢十亿!

***编辑:也许我应该澄清硬编码位。我已经破解了打开 RemoteExchange.ps1 并将出错的变量设置为正确的值(而不是使用 GetProperty 或其他),我稍微走得更远:

Exception calling "TryLoadExchangeTypes" with "2" argument(s): "Unable to determine the installed file version from the
 registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\v14\Setup'."
At C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:79 char:92
+ $typeLoadResult = [Microsoft.Exchange.Configuration.Tasks.TaskHelper]::TryLoadExchangeTypes <<<< ($ManagementPath, $t
ypeListToCheck)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

根据我从 79 的样子推测,这不是我可以改变的。它正在尝试从库中加载类型,为此它仍然需要查看注册表,所以我不能只修复一个变量。

4

3 回答 3

1

只需尝试在 x64 中编译您的程序。

我知道这很奇怪,但是在 x86 托管的 powershell 中,一些 cmdlet 看不到 x64 程序的注册表项。

(我的线索来自:“其中一个与另一个不同 | 可怕的 DBA 之家”:http ://www.scarydba.com/2010/06/30/one-of-these-things-is -not-like-the-other/ )

于 2012-08-16T19:42:52.177 回答
0

有同样的问题,实际上终于弄清楚了。我之前的回答是完全错误的。

我在这里回答正确。

于 2012-12-18T20:57:52.937 回答
0

您可以打开位于 \bin 中的 Exchange.ps1,然后编辑出现在下面的变量

## EXCHANGE VARIABLEs ########################################################

将 $global:exbin、$global:exinstall 和 $global:exscripts 更改为硬编码路径

"C:\Program Files\Microsoft\Exchange Server\V14\bin\"
"C:\Program Files\Microsoft\Exchange Server\V14\"
"C:\Program Files\Microsoft\Exchange Server\V14\scripts\"

这不是一个理想的解决方案,但解决方法不应影响调用这些变量的任何其他内容。

于 2012-07-26T14:42:44.347 回答