2009-06-18 45 views
2

我运行下面的代码:的PowerShell /运行空间

RunspaceConfiguration config = RunspaceConfiguration.Create(); 
PSSnapInException warning; 
config.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out warning); 
if (warning != null) throw warning;    

Runspace thisRunspace = RunspaceFactory.CreateRunspace(config); 
thisRunspace.Open(); 

string alias = usr.AD.CN.Replace(' ', '.'); 
string letter = usr.AD.CN.Substring(0, 1); 
string email = alias + "@" + (!usr.Mdph ? Constantes.AD_DOMAIN : Constantes.MDPH_DOMAIN) + "." + Constantes.AD_LANG; 
string db = "CN=IS-" + letter + ",CN=SG-" + letter + ",CN=InformationStore,CN=" + ((char)letter.ToCharArray()[0] < 'K' ? Constantes.EXC_SRVC : Constantes.EXC_SRVD) + Constantes.EXC_DBMEL; 
string cmd = "Enable-Mailbox -Identity \"" + usr.AD.CN + "\" -Alias " + alias + " -PrimarySmtpAddress " + email + " -DisplayName \"" + usr.AD.CN + "\" -Database \"" + db + "\""; 
Pipeline thisPipeline = thisRunspace.CreatePipeline(cmd); 
thisPipeline.Invoke(); 

的代码是在一个线程中运行的创建方式:

 t.WorkThread = new Thread(cu.CreerUser); 
     t.WorkThread.Start(); 

如果我直接运行的代码(不通过一个线程),它的工作。

在线程中抛出以下异常:ObjectDisposedException“安全句柄已关闭。” (译自法语)

然后,我替换了“Open”wirh“OpenAsync”,它帮助没有得到以前的异常。 但是,当调用时,我得到以下异常:InvalidRunspaceStateException“无法调用管道,因为其执行状态未打开,其当前状态为打开。” (同样来自法国的翻译)

我无言以对......

任何帮助,欢迎! 谢谢!


随着开放:

à Microsoft.Win32.Win32Native.GetTokenInformation(SafeTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, UInt32& ReturnLength) 
    à System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, UInt32& dwLength) 
    à System.Security.Principal.WindowsIdentity.get_User() 
    à System.Security.Principal.WindowsIdentity.GetName() 
    à System.Security.Principal.WindowsIdentity.get_Name() 
    à System.Management.Automation.MshLog.GetLogContext(ExecutionContext executionContext, InvocationInfo invocationInfo, Severity severity) 
    à System.Management.Automation.MshLog.GetLogContext(ExecutionContext executionContext, InvocationInfo invocationInfo) 
    à System.Management.Automation.MshLog.LogEngineLifecycleEvent(ExecutionContext executionContext, EngineState engineState, InvocationInfo invocationInfo) 
    à System.Management.Automation.MshLog.LogEngineLifecycleEvent(ExecutionContext executionContext, EngineState engineState) 
    à System.Management.Automation.Runspaces.LocalRunspace.OpenHelper() 
    à System.Management.Automation.Runspaces.RunspaceBase.CoreOpen(Boolean syncCall) 
    à System.Management.Automation.Runspaces.RunspaceBase.Open() 
    à Cg62.ComposantsCommuns.ActiveDirectory.Exchange.BoitesAuxLettres.CreationBAL(User usr, IList`1 log) dans D:\Applications\Commun\Sources .Net\COMIAD\COMIAD\Exchange.cs:ligne 141 
    à Cg62.ComposantsCommuns.ActiveDirectory.ComptesUtilisateurs.CreationUser.CreerUser() dans D:\Applications\Commun\Sources .Net\COMIAD\COMIAD\ComptesUtilisateurs.cs:ligne 199 
    à System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    à System.Threading.ExecutionContext.runTryCode(Object userData) 
    à System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 
    à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) 
    à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    à System.Threading.ThreadHelper.ThreadStart() 

随着OpenAsync:

à System.Management.Automation.Runspaces.RunspaceBase.AddToRunningPipelineList(PipelineBase pipeline) 
    à System.Management.Automation.Runspaces.RunspaceBase.DoConcurrentCheckAndAddToRunningPipelines(PipelineBase pipeline, Boolean syncCall) 
    à System.Management.Automation.Runspaces.PipelineBase.CoreInvoke(IEnumerable input, Boolean syncCall) 
    à System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input) 
    à System.Management.Automation.Runspaces.Pipeline.Invoke() 
    à Cg62.ComposantsCommuns.ActiveDirectory.Exchange.BoitesAuxLettres.CreationBAL(User usr, IList`1 log) dans D:\Applications\Commun\Sources .Net\COMIAD\COMIAD\Exchange.cs:ligne 149 
    à Cg62.ComposantsCommuns.ActiveDirectory.ComptesUtilisateurs.CreationUser.CreerUser() dans D:\Applications\Commun\Sources .Net\COMIAD\COMIAD\ComptesUtilisateurs.cs:ligne 199 
    à System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    à System.Threading.ExecutionContext.runTryCode(Object userData) 
    à System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) 
    à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) 
    à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    à System.Threading.ThreadHelper.ThreadStart() 

很抱歉这么晚才回复...我怎么回事


升级到了很多Powershell 2.0和我通过了打开错误 但现在我在Invoke上有以下内容。 我将我的命令更改为:

Enable-Mailbox -Identity "Aagtest Abe" -Alias Aagtest.Abe -PrimarySmtpAddress [email protected] -DisplayName "Aagtest Abe" -Database "myDb" -DomainController adc.domain.int 

该命令在PowerShell中正常工作。 我收到以下异常CmdletInvocationException: “没有例外,只能使用'<模块>'。” 如何把这种......不知道

堆栈跟踪:

à Microsoft.Exchange.Data.Directory.DSAccessTopologyProvider..ctor(String machineName) 
    à Microsoft.Exchange.Data.Directory.DSAccessTopologyProvider..ctor() 
    à Microsoft.Exchange.Data.Directory.DirectoryServicesTopologyProvider.DiscoverConfigDC() 
    à Microsoft.Exchange.Data.Directory.DirectoryServicesTopologyProvider..ctor() 
    à Microsoft.Exchange.Data.Directory.TopologyProvider.InitializeInstance() 
    à Microsoft.Exchange.Data.Directory.TopologyProvider.GetInstance() 
    à Microsoft.Exchange.Data.Directory.ADSession.GetConnection(String preferredServer, Boolean isWriteOperation, Boolean isNotifyOperation, ADObjectId& rootId) 
    à Microsoft.Exchange.Data.Directory.ADSession.GetReadConnection(String preferredServer, ADObjectId& rootId) 
    à Microsoft.Exchange.Data.Directory.ADSession.IsReadConnectionAvailable() 
    à Microsoft.Exchange.Configuration.Tasks.RecipientObjectActionTask`2.InternalBeginProcessing() 
    à Microsoft.Exchange.Management.RecipientTasks.EnableMailbox.InternalBeginProcessing() 
    à Microsoft.Exchange.Configuration.Tasks.Task.BeginProcessing() 
    à System.Management.Automation.Cmdlet.DoBeginProcessing() 
    à System.Management.Automation.CommandProcessorBase.DoBegin() 
+1

我遇到同样的问题。你有没有收到答案?问题出现在两年内运行正常的代码中(在Windows Vista,Windows 7和Windows Server 2003上测试过)。但是自从我们在Windows Server 2008上部署以来,我们遇到了这个错误。 – 2009-09-24 14:24:56

回答

2

因此,对于该问题的最终答案是,如果通过advapi32 LogonUser模拟,则无法执行远程Exchange PowerShell命令。

只要我测试过,命令是否在线程中执行完全没有关系。

什么似乎是正确的方式 - 以及适合我的方法 - 是在连接到Runspace后进行身份验证。

至于为什么发生这种情况......随时告诉我!

此代码不得在模仿时执行。

 IContexteRemotePowerShell crp: 
     crp.ConfigurationName = "Microsoft.Exchange"; 
     crp.RemoteUri = "http://exhangeserver/powershell"; 
     crp.User = "account who has rights to do stuff on the exchange server"; 
     crp.Password = "its password"; 
     crp.Domaine = "Domain"; 


private static void Connect(IContexteRemotePowerShell contexte) 
    { 
     try 
     { 
      Espace = RunspaceFactory.CreateRunspace(); 
      Espace.Open(); 
     } 
     catch (InvalidRunspaceStateException ex) 
     { 
      throw new TechniqueException(MethodBase.GetCurrentMethod(), "Error while creating runspace.", ex); 
     } 

     // Create secure password 
     SecureString password = new SecureString(); 
     foreach (char c in contexte.Password) 
     { 
      password.AppendChar(c); 
     } 

     // Create credential 
     PSCredential psc = new PSCredential(contexte.User, password); 

     PSCommand command = new PSCommand(); 
     command.AddCommand("New-PSSession"); 
     command.AddParameter("Credential", psc); 

     if (!String.IsNullOrEmpty(contexte.Serveur)) 
      command.AddParameter("computername", contexte.Serveur); 
     if (!String.IsNullOrEmpty(contexte.RemoteUri)) 
      command.AddParameter("ConnectionUri", new Uri(contexte.RemoteUri)); 
     if (!string.IsNullOrEmpty(contexte.ConfigurationName)) 
      command.AddParameter("ConfigurationName", contexte.ConfigurationName); 

     //// Create the session 
     PowerShell powershell = PowerShell.Create(); 
     powershell.Commands = command; 
     powershell.Runspace = Espace; 
     Collection<PSObject> result = ExecuterCommande(command); 

     if (result.Count != 1) 
      throw new TechniqueException(MethodBase.GetCurrentMethod(), 
              "Error while connecting."); 

     // Create session variable 
     command = new PSCommand(); 
     command.AddCommand("Set-Variable"); 
     command.AddParameter("Name", "ra"); 
     command.AddParameter("Value", result[0]); 
     ExecuterCommande(command); 
    } 

private const string InvokeCommand = "Invoke-Command -ScriptBlock {{ {0} }} -Session $ra"; 

    private static string ExecuteRemoteScript(string cmd) 
    { 
     PSCommand command = new PSCommand(); 
     command.AddScript(string.Format(InvokeCommand, cmd)); 
     Collection<PSObject> result = ExecuterCommande(command); 

     StringBuilder sb = new StringBuilder(); 
     foreach (PSObject obj in result) 
     { 
      sb.AppendLine(obj.ToString()); 
     } 
     return sb.ToString().Trim(); 
    } 
1

你试试这个?

//set the default runspace for this thread 
System.Management.Automation.Runspaces.Runspace.DefaultRunspace = runspace; 
1

,当你调用Runspace.Open从另一个线程是同一个问题的症状描述here什么不顺心。在Web项目中,我从完成请求的线程开始创建新线程时遇到了完全相同的问题。新线程最终称为Enable-Mailbox cmdlet。

我遇到的问题是,在发生Runspace.Open的调用之前,web请求本身已经很久了。网络请求与存储在线程中的WindowsIdentity相关联。身份被传递给调用Runspace.Open的线程。但是,由于处理Web请求的线程在此调用之前完成,因此标识将在打开运行空间之前处理。在Runspace.Open调用期间,试图获取现在处置的身份的安全令牌(请参阅堆栈跟踪中的第一行:Microsoft.Win32.Win32Native.GetTokenInformation)。这失败了ObjectDisposedException

有两种方法来解决这个问题:

  1. 不要从另一个线程调用Runspace.Open。至少不会在调用线程完成之前调用Runspace.Open
  2. 在致电Runspace.Open之前,请确保线程上有另一个标识。例如,你可以做到以下几点:

    Thread.CurrentPrincipal = 
        new GenericPrincipal(new GenericIdentity("PSTest"), null) 
    

    您填写什么在为GenericIdentity的名字其实并不重要。

1

谢谢,罗纳德。即使你的回答没有帮助OP,它也帮助了我。

我刚刚尝试在Web服务器上的AppDomain中启动某些内容时遇到了问题。对线:

ObjectHandle handle = domain.CreateInstance(_assemblyName, _className); 

......它爆炸与一个ObjectDisposedException。我无法想象出我的生活 - AppDomain中没有任何东西被处置,而且这似乎在其他服务器上工作。我进入了反汇编,看到它试图序列化线程执行上下文,包含在那里的逻辑调用上下文和包含在其中的主体,而主体就是它爆炸的内容。

原来,在此当用户已登录,和IIS在“冒充”模式正在运行的创建线程,因此线程的当前主要是原始用户的过期本金。

我把这个代码周围:

IPrincipal oldPrincipal = Thread.CurrentPrincipal; 
try 
{ 
    Thread.CurrentPrincipal = new GenericPrincipal(
     new GenericIdentity("NetPlugins"), null); 
    ObjectHandle handle = domain.CreateInstance(_assemblyName, _className); 
    // unwrapping and calling code omitted 
} 
finally 
{ 
    Thread.CurrentPrincipal = oldPrincipal; 
} 

我可能不需要把老校长回来,也可能通过改变创造有问题的线程之前,在当前主要解决这个问题,但是谢谢你,罗纳德:这个作品像顶级!

相关问题