从C#调用Exchange命令行管理程序

时间:2012-07-26 13:21:42

标签: c# powershell exchange-server

我目前正在使用.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密钥也具有授予everbody的完全读取权限
  • 我在服务器上启用了未签名的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这样的猜测来看,这不是我可以改变的。它正在尝试从库中加载类型,并且为此需要查看注册表,所以我不能只修复变量。

3 个答案:

答案 0 :(得分:1)

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

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

(我从中获得了线索:“其中一件事与其他人不同|可怕的DBA之家”:http://www.scarydba.com/2010/06/30/one-of-these-things-is-not-like-the-other/

答案 1 :(得分: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\"

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

答案 2 :(得分:0)

遇到同样的问题,实际上终于明白了。我之前的回答是完全错误的。

我正确地回答了here