2009-06-18 88 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; 
} 

我可能不需要把老校長回來,也可能通過改變創造有問題的線程之前,在當前主要解決這個問題,但是謝謝你,羅納德:這個作品像頂級!

相關問題