我目前正在使用 .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 的样子推测,这不是我可以改变的。它正在尝试从库中加载类型,为此它仍然需要查看注册表,所以我不能只修复一个变量。