Beispiel #1
0
        void RevertImpersonation()
        {
            if (!ShouldImpersonate())
            {
                return;
            }

            Tracer.Enter("revertimpersonation");
            Tracer.Indent();
            try
            {
                Tracer.TraceInformation("closing-impersonation-context");
                m_ImpersonationContext.Undo();

                Tracer.TraceInformation("closing-impersonation-tokenhandle {0}", impersonationToken);
                NativeMethods.CloseHandle(impersonationToken);
                Tracer.TraceInformation("closing-impersonation-duplicated-tokenhandle {0}", tokenDuplicate);
                NativeMethods.CloseHandle(tokenDuplicate);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("revertimpersonation", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("revertimpersonation");
            }
        }
Beispiel #2
0
        public CloseImportConnectionResults CloseImportConnection(CloseImportConnectionRunStep importRunStep)
        {
            Tracer.Enter("closeimportconnectionresults");
            Tracer.Indent();
            try
            {
                CloseRunspace();

                //RevertImpersonation();

                CloseImportConnectionResults cicr = new CloseImportConnectionResults();
                Tracer.TraceInformation("custom-data {0}", importRunStep.CustomData);
                Tracer.TraceInformation("close-reason {0}", importRunStep.Reason);
                if (importRunStep.Reason == CloseReason.Normal)
                {
                    cicr.CustomData = importRunStep.CustomData;
                }
                Dispose();
                return(cicr);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("closeimportconnection", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("closeimportconnectionresults");
            }
        }
Beispiel #3
0
        void IMAExtensible2CallExport.OpenExportConnection(System.Collections.ObjectModel.KeyedCollection <string, ConfigParameter> configParameters, Schema types, OpenExportConnectionRunStep exportRunStep)
        {
            Tracer.IndentLevel = 0;
            Tracer.Enter("openexportconnection");
            Tracer.Indent();
            try
            {
                InitializeConfigParameters(configParameters);

                OpenRunspace();
                schema = types;

                exportType = exportRunStep.ExportType;
                Tracer.TraceInformation("export-type '{0}'", exportType);
                exportBatchSize = exportRunStep.BatchSize;
                Tracer.TraceInformation("export-batch-size '{0}'", exportBatchSize);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("openexportconnection", ex);
                throw new TerminateRunException(ex.Message);
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("openexportconnection");
            }
        }
Beispiel #4
0
        void SetupImpersonationToken()
        {
            Tracer.Enter("setupimpersonationtoken");
            try
            {
                if (!ShouldImpersonate())
                {
                    Tracer.TraceInformation("impersonation-not-configured-running-as-sync-service-account");
                    WhoAmI();
                    return;
                }
                WindowsIdentity m_ImpersonatedUser;

                Tracer.TraceInformation("user-before-impersonation: {0}", WindowsIdentity.GetCurrent(TokenAccessLevels.MaximumAllowed).Name);

                //bool success = NativeMethods.LogonUser(impersonationUsername, impersonationUserDomain, impersonationUserPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out impersonationToken);
                bool success = NativeMethods.LogonUser(impersonationUsername, impersonationUserDomain, impersonationUserPassword, (int)LogonType.LOGON32_LOGON_NETWORK_CLEARTEXT, (int)LogonProvider.LOGON32_PROVIDER_WINNT50, out impersonationToken);
                if (!success)
                {
                    SecurityException ex = new SecurityException(string.Format("failed-to-impersonate: domain: '{0}', username: '******', password: **secret***", impersonationUserDomain, impersonationUsername));
                    Tracer.TraceError(ex.ToString());
                    throw ex;
                }
                else
                {
                    Tracer.TraceInformation("succeeded-in-impersonating: domain: '{0}', username: '******', password: **secret***", impersonationUserDomain, impersonationUsername);
                    if (NativeMethods.DuplicateToken(impersonationToken, (int)ImpersonationLevel.SecurityImpersonation, ref tokenDuplicate) != 0)
                    {
                        m_ImpersonatedUser     = new WindowsIdentity(tokenDuplicate);
                        m_ImpersonationContext = m_ImpersonatedUser.Impersonate();
                        Tracer.TraceInformation("succeeded-in-duplicating-impersonation-token");
                        if (m_ImpersonationContext != null)
                        {
                            Tracer.TraceInformation("user-after-impersonation: {0}", WindowsIdentity.GetCurrent(TokenAccessLevels.MaximumAllowed).Name);
                            WhoAmI();
                        }
                        else
                        {
                            throw new Exception("impersonation-context-is-null");
                        }
                    }
                    else
                    {
                        throw new Exception("could-not-duplicate-impersonation-token");
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("setupimpersonationtoken", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("setupimpersonationtoken");
            }
        }
Beispiel #5
0
        public PowerShellManagementAgent()
        {
            Tracer.IndentLevel = 0;
            Tracer.Enter("initialize");
            Tracer.Indent();
            try
            {
                Tracer.TraceInformation("memory-usage {0:n} Mb", GC.GetTotalMemory(true) / 102400);
                System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
                FileVersionInfo            fvi      = FileVersionInfo.GetVersionInfo(assembly.Location);
                string version = fvi.FileVersion;
                Tracer.TraceInformation("psma-version {0}", version);
                Tracer.TraceInformation("reading-registry-settings");
                RegistryKey machineRegistry = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
                RegistryKey mreRootKey      = machineRegistry.OpenSubKey(@"SOFTWARE\Granfeldt\FIM\ManagementAgents\PowerShell", false);

                if (mreRootKey != null)
                {
                    Tracer.TraceInformation("adding-eventlog-listener-for name: {0}, source: {1}", EventLogName, EventLogSource);
                    EventLog evl = new EventLog(EventLogName);
                    evl.Log    = EventLogName;
                    evl.Source = EventLogSource;

                    EventLogTraceListener eventLog = new EventLogTraceListener(EventLogSource);
                    eventLog.EventLog = evl;
                    EventTypeFilter filter = new EventTypeFilter(SourceLevels.Warning | SourceLevels.Error | SourceLevels.Critical);
                    eventLog.TraceOutputOptions = TraceOptions.Callstack;
                    eventLog.Filter             = filter;
                    Tracer.Trace.Listeners.Add(eventLog);
                    if (!EventLog.SourceExists(EventLogSource))
                    {
                        Tracer.TraceInformation("creating-eventlog-source '{0}'", EventLogSource);
                        EventLog.CreateEventSource(EventLogSource, EventLogName);
                    }

                    string logFileValue = mreRootKey.GetValue("DebugLogFileName", null) as string;
                    if (logFileValue != null)
                    {
                        Tracer.TraceWarning("Logging to file is no longer supported. Please remove registrykey DebugLogFileName and use DebugView or similar instead to catch traces from this Management Agent");
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("could-not-initialize", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("initialize");
            }
        }
Beispiel #6
0
        void CallPasswordScript(PasswordOperation Action, CSEntry csentry, SecureString oldPassword, SecureString newPassword, PasswordOptions options)
        {
            Tracer.Enter("callpasswordscript");
            Tracer.Indent();
            PSDataCollection <PSObject> passwordPipeline = new PSDataCollection <PSObject>();

            try
            {
                Command cmd = new Command(Path.GetFullPath(PasswordManagementScript));
                cmd.Parameters.Add(new CommandParameter("User", Username));
                cmd.Parameters.Add(new CommandParameter("Password", Password));
                cmd.Parameters.Add(new CommandParameter("Credentials", GetSecureCredentials()));
                cmd.Parameters.Add(new CommandParameter("Action", Action.ToString()));

                if (options.HasFlag(PasswordOptions.UnlockAccount))
                {
                    cmd.Parameters.Add(new CommandParameter("UnlockAccount"));
                }
                if (options.HasFlag(PasswordOptions.ForceChangeAtLogOn))
                {
                    cmd.Parameters.Add(new CommandParameter("ForceChangeAtLogOn"));
                }
                if (options.HasFlag(PasswordOptions.ValidatePassword))
                {
                    cmd.Parameters.Add(new CommandParameter("ValidatePassword"));
                }
                cmd.Parameters.Add(new CommandParameter("NewPassword", newPassword.ConvertToUnsecureString()));
                if (Action == PasswordOperation.Change)
                {
                    cmd.Parameters.Add(new CommandParameter("OldPassword", oldPassword.ConvertToUnsecureString()));
                }
                passwordPipeline.Add(new PSObject(csentry));
                passwordResults = InvokePowerShellScript(cmd, passwordPipeline);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("callpasswordscript", ex);
                throw;
            }
            finally
            {
                passwordPipeline = null;
                Tracer.Unindent();
                Tracer.TraceInformation("callpasswordscript");
            }
        }
Beispiel #7
0
 ParameterValidationResult IMAExtensible2GetParameters.ValidateConfigParameters(System.Collections.ObjectModel.KeyedCollection <string, ConfigParameter> configParameters, ConfigParameterPage page)
 {
     try
     {
         Tracer.Enter("validateconfigparameters");
         Tracer.Indent();
         if (page == ConfigParameterPage.Connectivity)
         {
             string schemaScriptFilename = Path.GetFullPath(configParameters[Constants.Parameters.SchemaScript].Value);
             if (!File.Exists(schemaScriptFilename))
             {
                 return(new ParameterValidationResult(ParameterValidationResultCode.Failure, string.Format("Can not find or access Schema script '{0}'. Please make sure that the FIM Synchronization Service service account can read and access this file.", schemaScriptFilename), Constants.Parameters.SchemaScript));
             }
         }
         if (page == ConfigParameterPage.Global)
         {
             string importScriptFilename = Path.GetFullPath(configParameters[Constants.Parameters.ImportScript].Value);
             if (!File.Exists(importScriptFilename))
             {
                 return(new ParameterValidationResult(ParameterValidationResultCode.Failure, string.Format("Can not find or access Import script '{0}'. Please make sure that the FIM Synchronization Service service account can read and access this file.", importScriptFilename), Constants.Parameters.ImportScript));
             }
             string exportScriptFilename = Path.GetFullPath(configParameters[Constants.Parameters.ExportScript].Value);
             if (!File.Exists(exportScriptFilename))
             {
                 return(new ParameterValidationResult(ParameterValidationResultCode.Failure, string.Format("Can not find or access Export script '{0}'. Please make sure that the FIM Synchronization Service service account can read and access this file.", exportScriptFilename), Constants.Parameters.ExportScript));
             }
             string passwordManagementScriptFilename = Path.GetFullPath(configParameters[Constants.Parameters.PasswordManagementScript].Value);
             if (!File.Exists(passwordManagementScriptFilename))
             {
                 return(new ParameterValidationResult(ParameterValidationResultCode.Failure, string.Format("Can not find or access Password Management script '{0}'. Please make sure that the FIM Synchronization Service service account can read and access this file.", passwordManagementScriptFilename), Constants.Parameters.PasswordManagementScript));
             }
         }
     }
     catch (Exception ex)
     {
         Tracer.TraceError("validateconfigparameters", ex);
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("validateconfigparameters");
     }
     return(new ParameterValidationResult(ParameterValidationResultCode.Success, "", ""));
 }
Beispiel #8
0
 void IMAExtensible2Password.SetPassword(CSEntry csentry, SecureString newPassword, PasswordOptions options)
 {
     Tracer.Enter("setpassword");
     Tracer.Indent();
     try
     {
         CallPasswordScript(PasswordOperation.Set, csentry, new SecureString(), newPassword, options);
     }
     catch (Exception ex)
     {
         Tracer.TraceError("setpassword", ex);
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("setpassword");
     }
 }
Beispiel #9
0
 void IMAExtensible2Password.ChangePassword(CSEntry csentry, SecureString oldPassword, SecureString newPassword)
 {
     Tracer.Enter("changepassword");
     Tracer.Indent();
     try
     {
         CallPasswordScript(PasswordOperation.Change, csentry, oldPassword, newPassword, PasswordOptions.None);
     }
     catch (Exception ex)
     {
         Tracer.TraceError("changepassword", ex);
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("changepassword");
     }
 }
Beispiel #10
0
 void IMAExtensible2CallExport.CloseExportConnection(CloseExportConnectionRunStep exportRunStep)
 {
     Tracer.Enter("closeexportconnection");
     Tracer.Indent();
     try
     {
         CloseRunspace();
         Dispose();
     }
     catch (Exception ex)
     {
         Tracer.TraceError("closeexportconnection", ex);
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("closeexportconnection");
     }
 }
Beispiel #11
0
 void IMAExtensible2Password.ClosePasswordConnection()
 {
     Tracer.Enter("closepasswordconnection");
     Tracer.Indent();
     try
     {
         CloseRunspace();
         Dispose();
     }
     catch (Exception ex)
     {
         Tracer.TraceError("closepasswordconnection", ex);
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("closepasswordconnection");
     }
 }
Beispiel #12
0
        void CloseRunspace()
        {
            Tracer.Enter("closerunspace");
            Tracer.Indent();
            try
            {
                if (powershell != null)
                {
                    Tracer.TraceInformation("disposing-powershell");
                    powershell.Runspace.Close();
                    powershell.Dispose();
                    Tracer.TraceInformation("disposed-powershell");
                }

                if (runspace != null)
                {
                    Tracer.TraceInformation("runspace-state '{0}'", runspace.RunspaceStateInfo.State);
                    if (runspace.RunspaceStateInfo.State != RunspaceState.Closed)
                    {
                        Tracer.TraceInformation("removing-runspace-eventhandlers");
                        runspace.StateChanged        -= Runspace_StateChanged;
                        runspace.AvailabilityChanged -= Runspace_AvailabilityChanged;
                        Tracer.TraceInformation("removed-runspace-eventhandlers");
                        Tracer.TraceInformation("dispose-runspace");
                        runspace.Dispose();                         // dispose also closes runspace
                        Tracer.TraceInformation("disposed-runspace");
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("closerunspace", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("closerunspace");
            }
        }
Beispiel #13
0
        void IMAExtensible2Password.OpenPasswordConnection(KeyedCollection <string, ConfigParameter> configParameters, Partition partition)
        {
            Tracer.IndentLevel = 0;
            Tracer.Enter("openpasswordconnection");
            Tracer.Indent();
            try
            {
                InitializeConfigParameters(configParameters);

                OpenRunspace();
            }
            catch (Exception ex)
            {
                Tracer.TraceError("openpasswordconnection", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("openpasswordconnection");
            }
        }
Beispiel #14
0
 public void Dispose()
 {
     Tracer.Enter("dispose");
     Tracer.Indent();
     try
     {
         Tracer.TraceInformation("clearing-variables");
         csentryqueue = null;
         objectTypeAnchorAttributeNames = null;
         Tracer.TraceInformation("collection-garbage");
         GC.Collect(0, GCCollectionMode.Default, true);
     }
     catch (Exception ex)
     {
         Tracer.TraceError(ex.ToString());
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("dispose");
     }
 }
Beispiel #15
0
 void WhoAmI()
 {
     Tracer.Enter("show-identity");
     Tracer.Indent();
     try
     {
         using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent())
         {
             Tracer.TraceInformation("identity-name: {0}", currentIdentity.Name);
             Tracer.TraceInformation("identity-token: {0}", currentIdentity.Token);
             Tracer.TraceInformation("identity-user-value: {0}", currentIdentity.User.Value);
             if (currentIdentity.Actor != null)
             {
                 Tracer.TraceInformation("identity-actor: {0}", currentIdentity.Actor.Name);
                 Tracer.TraceInformation("identity-actor-auth-type: {0}", currentIdentity.Actor.AuthenticationType);
             }
             if (currentIdentity.Groups != null)
             {
                 foreach (IdentityReference group in currentIdentity.Groups)
                 {
                     NTAccount account = group.Translate(typeof(NTAccount)) as NTAccount;
                     Tracer.TraceInformation("group-membership {0}", account.Value);
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Tracer.TraceError("error-showing-current-identity", ex);
         throw;
     }
     finally
     {
         Tracer.Unindent();
         Tracer.Exit("show-identity");
     }
 }
Beispiel #16
0
        public void InitializeConfigParameters(System.Collections.ObjectModel.KeyedCollection <string, ConfigParameter> configParameters)
        {
            Tracer.Enter("initializeconfigparameters");
            Tracer.Indent();
            try
            {
                if (configParameters != null)
                {
                    foreach (ConfigParameter cp in configParameters)
                    {
                        Tracer.TraceInformation("{0}: '{1}'", cp.Name, cp.IsEncrypted ? "*** secret ***" : cp.Value);
                        if (cp.Name.Equals(Constants.Parameters.Username))
                        {
                            Username = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.Password))
                        {
                            Password             = configParameters[cp.Name].SecureValue.ConvertToUnsecureString();
                            SecureStringPassword = configParameters[cp.Name].SecureValue;
                        }

                        if (cp.Name.Equals(Constants.Parameters.ImpersonationDomain))
                        {
                            impersonationUserDomain = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.ImpersonationUsername))
                        {
                            impersonationUsername = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.ImpersonationPassword))
                        {
                            impersonationUserPassword = configParameters[cp.Name].SecureValue.ConvertToUnsecureString();
                        }

                        if (cp.Name.Equals(Constants.Parameters.SchemaScript))
                        {
                            SchemaScript = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.ImportScript))
                        {
                            ImportScript = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.ExportScript))
                        {
                            ExportScript = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.PasswordManagementScript))
                        {
                            PasswordManagementScript = configParameters[cp.Name].Value;
                        }
                        if (cp.Name.Equals(Constants.Parameters.ExportSimpleObjects))
                        {
                            ExportSimpleObjects = configParameters[cp.Name].Value == "0" ? false : true;
                        }
                        if (cp.Name.Equals(Constants.Parameters.UsePagedImport))
                        {
                            UsePagedImport = configParameters[cp.Name].Value == "0" ? false : true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("initializeconfigparameters", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("initializeconfigparameters");
            }
        }
Beispiel #17
0
        public GetImportEntriesResults GetImportEntries(GetImportEntriesRunStep importRunStep)
        {
            Tracer.Enter("getimportentries");
            Tracer.Indent();
            try
            {
                #region call import script

                // if results is null, then this is the first time that we're called,
                // so call script and get pipeline object and custom data
                Tracer.TraceInformation("more-to-import '{0}'", MoreToImport);

                if (MoreToImport)
                {
                    MoreToImport = false;                     // make sure we set more-to-import to false; could be overwritten further down if pagedimports is true, though

                    // on first call, we set customdata to value from last successful run
                    returnedCustomData = importRunStep.CustomData;

                    Command cmd = new Command(Path.GetFullPath(ImportScript));
                    cmd.Parameters.Add(new CommandParameter("User", Username));
                    cmd.Parameters.Add(new CommandParameter("Password", Password));
                    cmd.Parameters.Add(new CommandParameter("Credentials", GetSecureCredentials()));
                    cmd.Parameters.Add(new CommandParameter("OperationType", importOperationType.ToString()));
                    cmd.Parameters.Add(new CommandParameter("UsePagedImport", UsePagedImport));
                    cmd.Parameters.Add(new CommandParameter("PageSize", ImportRunStepPageSize));

                    Tracer.TraceInformation("setting-custom-data '{0}'", importRunStep.CustomData);
                    powershell.Runspace.SessionStateProxy.SetVariable("RunStepCustomData", importRunStep.CustomData);
                    Tracer.TraceInformation("setting-page-token '{0}'", pageToken);
                    powershell.Runspace.SessionStateProxy.SetVariable("PageToken", pageToken);

                    importResults = InvokePowerShellScript(cmd, null).ToList <PSObject>();

                    returnedCustomData = powershell.Runspace.SessionStateProxy.GetVariable("RunStepCustomData");
                    pageToken          = powershell.Runspace.SessionStateProxy.GetVariable("PageToken");

                    Tracer.TraceInformation("page-token-returned '{0}'", pageToken == null ? "(null)" : pageToken);
                    Tracer.TraceInformation("custom-data returned '{0}'", returnedCustomData);
                    Tracer.TraceInformation("number-of-object(s)-in-pipeline {0:n0}", importResults.Count);

                    if (UsePagedImport)
                    {
                        Tracer.TraceError("paged-import-not-supported-currently");
                        object moreToImportObject = powershell.Runspace.SessionStateProxy.GetVariable("MoreToImport");
                        if (moreToImportObject == null)
                        {
                            Tracer.TraceError("For paged imports, the global variable 'MoreToImport' must be set to 'true' or 'false'");
                        }
                        else
                        {
                            Tracer.TraceInformation("MoreToImport-value-returned '{0}'", moreToImportObject);
                            if (bool.TryParse(moreToImportObject == null ? bool.FalseString : moreToImportObject.ToString(), out MoreToImport))
                            {
                                Tracer.TraceInformation("paged-import-setting-MoreToImport-to '{0}'", MoreToImport);
                            }
                            else
                            {
                                Tracer.TraceError("Value returned in MoreToImport must be a boolean with value of 'true' or 'false'");
                            }
                        }
                    }
                    else
                    {
                        MoreToImport = false;
                        Tracer.TraceInformation("non-paged-import-setting-MoreToImport-to '{0}'", MoreToImport);
                    }
                }
                #endregion

                #region parse returned objects
                if (importResults != null && importResults.Count > 0)
                {
                    List <PSObject> importResultsBatch = importResults.Take(ImportRunStepPageSize).ToList();
                    if (importResults.Count > ImportRunStepPageSize)
                    {
                        importResults.RemoveRange(0, importResultsBatch.Count);
                    }
                    else
                    {
                        importResults.Clear();
                    }
                    Tracer.TraceInformation("converting-objects-to-csentrychange {0:n0}", importResultsBatch.Count);
                    foreach (PSObject obj in importResultsBatch)
                    {
                        HashSet <AttributeDefinition> attrs = new HashSet <AttributeDefinition>();

                        Tracer.TraceInformation("start-connector-space-object");
                        Tracer.Indent();
                        try
                        {
                            CSEntryChange csobject = CSEntryChange.Create();

                            if (obj.BaseObject.GetType() != typeof(System.Collections.Hashtable))
                            {
                                Tracer.TraceWarning("invalid-object-in-pipeline '{0}'", obj.BaseObject.GetType());
                                continue;
                            }

                            object        AnchorValue         = null;
                            string        AnchorAttributeName = null;
                            string        objectDN            = null;
                            string        objectClass         = "";              // should be string to prevent null exceptions
                            string        changeType          = null;
                            string        ErrorName           = null;
                            string        ErrorDetail         = null;
                            MAImportError ImportErrorType     = MAImportError.Success;                         // assume no error
                            Hashtable     hashTable           = (Hashtable)obj.BaseObject;

                            #region get control values
                            Tracer.TraceInformation("start-getting-control-values");
                            Tracer.Indent();
                            foreach (string key in hashTable.Keys)
                            {
                                if (key.Equals(Constants.ControlValues.ObjectClass, StringComparison.OrdinalIgnoreCase) || key.Equals(Constants.ControlValues.ObjectClassEx, StringComparison.OrdinalIgnoreCase))
                                {
                                    objectClass = (string)hashTable[key];
                                    Tracer.TraceInformation("got-objectclass {0}, {1}", objectClass, key);
                                    continue;
                                }
                                if (key.Equals(Constants.ControlValues.DN, StringComparison.OrdinalIgnoreCase))
                                {
                                    objectDN = (string)hashTable[key];
                                    Tracer.TraceInformation("got-dn {0}, {1}", objectDN, key);
                                    continue;
                                }
                                if (key.Equals(Constants.ControlValues.ChangeType, StringComparison.OrdinalIgnoreCase) || key.Equals(Constants.ControlValues.ChangeTypeEx, StringComparison.OrdinalIgnoreCase))
                                {
                                    changeType = (string)hashTable[key];
                                    Tracer.TraceInformation("got-changetype {0}, {1}", changeType, key);
                                    continue;
                                }
                                if (key.Equals(Constants.ControlValues.ErrorName, StringComparison.OrdinalIgnoreCase))
                                {
                                    ErrorName = (string)hashTable[key];
                                    Tracer.TraceInformation("got-errorname {0}, {1}", ErrorName, key);
                                    continue;
                                }
                                if (key.Equals(Constants.ControlValues.ErrorDetail, StringComparison.OrdinalIgnoreCase))
                                {
                                    ErrorDetail = (string)hashTable[key];
                                    Tracer.TraceInformation("got-errordetail {0}, {1}", ErrorDetail, key);
                                    continue;
                                }
                            }

                            if (string.IsNullOrEmpty(objectClass))
                            {
                                Tracer.TraceError("missing-objectclass");
                                ImportErrorType = MAImportError.ImportErrorCustomContinueRun;
                                ErrorName       = "missing-objectclass-value";
                                ErrorDetail     = "No value provided for objectclass attribute";
                            }
                            else
                            {
                                AnchorAttributeName = objectTypeAnchorAttributeNames[objectClass] == null ? "" : (string)objectTypeAnchorAttributeNames[objectClass];
                                if (string.IsNullOrEmpty(AnchorAttributeName))
                                {
                                    ImportErrorType = MAImportError.ImportErrorInvalidAttributeValue;
                                    ErrorName       = "invalid-objecttype";
                                    ErrorDetail     = "Objecttype not defined in schema";
                                }

                                foreach (string key in hashTable.Keys)
                                {
                                    if (key.Equals(AnchorAttributeName, StringComparison.OrdinalIgnoreCase))
                                    {
                                        AnchorValue = hashTable[key];
                                        Tracer.TraceInformation("got-anchor {0}, {1}", AnchorValue, key);
                                        break;
                                    }
                                }
                            }
                            Tracer.Unindent();
                            Tracer.TraceInformation("end-getting-control-values");

                            if (AnchorValue == null)
                            {
                                Tracer.TraceError("missing-anchor");
                                ImportErrorType = MAImportError.ImportErrorCustomContinueRun;
                                ErrorName       = "missing-anchor-value";
                                ErrorDetail     = "No value provided for anchor attribute";
                            }

                            if (AnchorValue != null && string.IsNullOrEmpty(objectDN))
                            {
                                Tracer.TraceInformation("setting-anchor-as-dn {0}", AnchorValue);
                                objectDN = AnchorValue.ToString();
                            }

                            if (!string.IsNullOrEmpty(ErrorName))
                            {
                                ImportErrorType = MAImportError.ImportErrorCustomContinueRun;
                                if (string.IsNullOrEmpty(ErrorDetail))
                                {
                                    ErrorDetail = "No error details provided";
                                }
                            }
                            #endregion control values

                            #region return invalid object
                            if (ImportErrorType != MAImportError.Success)
                            {
                                Tracer.TraceInformation("returning-invalid-object");
                                if (AnchorValue != null)
                                {
                                    csobject.AnchorAttributes.Add(AnchorAttribute.Create(AnchorAttributeName, AnchorValue));
                                }
                                csobject.ObjectModificationType = ObjectModificationType.Add;
                                if (!string.IsNullOrEmpty(objectClass))
                                {
                                    try
                                    {
                                        csobject.ObjectType = objectClass;
                                    }
                                    catch (NoSuchObjectTypeException otEx)
                                    {
                                        Tracer.TraceError("no-such-object '{0}'", otEx);
                                    }
                                }
                                if (!string.IsNullOrEmpty(objectClass))
                                {
                                    csobject.DN = objectDN;
                                }
                                Tracer.TraceError("invalid-object dn: {0}, type: {1}, name: {2}, details: {3} ", objectDN, ImportErrorType, ErrorName, ErrorDetail);
                                csobject.ErrorCodeImport = ImportErrorType;
                                csobject.ErrorName       = ErrorName;
                                csobject.ErrorDetail     = ErrorDetail;
                                csentryqueue.Add(csobject);
                                continue;
                            }
                            #endregion

                            #region return deleted object
                            // we must set ObjectModificationType before any other attributes; otherwise it will default to 'Add'
                            if (!string.IsNullOrEmpty(changeType) && changeType.Equals("delete", StringComparison.OrdinalIgnoreCase))
                            {
                                Tracer.TraceInformation("returning-deleted-object");
                                Tracer.TraceInformation("change-type {0}", changeType);
                                csobject.ObjectModificationType = ObjectModificationType.Delete;
                                csobject.ObjectType             = objectClass;
                                csobject.DN = objectDN;

                                // we need to get the object anchor value for the deletion
                                csobject.AnchorAttributes.Add(AnchorAttribute.Create(AnchorAttributeName, AnchorValue));
                                csentryqueue.Add(csobject);
                                continue;
                            }
                            #endregion

                            #region returned live object
                            Tracer.TraceInformation("returning-valid-object");
                            csobject.ObjectModificationType = ObjectModificationType.Add;
                            csobject.ObjectType             = objectClass;
                            csobject.DN = objectDN;
                            csobject.AnchorAttributes.Add(AnchorAttribute.Create(AnchorAttributeName, AnchorValue));
                            foreach (string key in hashTable.Keys)
                            {
                                try
                                {
                                    if (Regex.IsMatch(key, string.Format(@"^(objectClass|\[objectclass\]|changeType|\[changetype\]|\[DN\]|\[ErrorName\]|\[ErrorDetail\]|{0})$", AnchorAttributeName), RegexOptions.Compiled | RegexOptions.IgnoreCase))
                                    {
                                        Tracer.TraceInformation("skip-control-value {0}", key);
                                        continue;
                                    }
                                    if (hashTable[key] == null)
                                    {
                                        Tracer.TraceInformation("skip-null-value-for '{0}'", key);
                                        continue;
                                    }
                                    SchemaAttribute sa = schema.Types[objectClass].Attributes[key];
                                    Tracer.TraceInformation("attribute: {0} (type {1}, {2}): '{3}'", key, sa.DataType, sa.IsMultiValued ? "multi-value" : "single-value", hashTable[key]);
                                    if (sa.IsMultiValued)
                                    {
                                        //Tracer.TraceInformation("add-multivalue '{0}' [{1}]", key, hashTable[key].GetType());
                                        List <object> mvs = new List <object>();
                                        if (hashTable[key].ToString().EndsWith("[]"))
                                        {
                                            mvs.AddRange((object[])hashTable[key]);
                                        }
                                        else
                                        {
                                            mvs.Add(hashTable[key]);
                                        }
                                        csobject.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(key, mvs));
                                    }
                                    else
                                    {
                                        csobject.AttributeChanges.Add(AttributeChange.CreateAttributeAdd(key, hashTable[key]));
                                    }
                                }
                                catch (KeyNotFoundException keyexception)
                                {
                                    Tracer.TraceError("attribute-is-not-defined-for '{0}' / '{1}' ({2})", key, objectClass, keyexception.ToString());
                                }
                            }
                            #endregion

                            if (csobject.ErrorCodeImport != MAImportError.Success)
                            {
                                Tracer.TraceError("defective-csentrychange id: {0}, dn: {1}, errorcode: {2}, error: {3}, details: {4}", csobject.Identifier, csobject.DN, csobject.ErrorCodeImport, csobject.ErrorName, csobject.ErrorDetail);
                            }
                            Tracer.TraceInformation("returning-csentry dn: {0}, id: {1}", csobject.DN, csobject.Identifier);
                            csentryqueue.Add(csobject);
                        }
                        catch (Exception ex)
                        {
                            Tracer.TraceError("creating-csentrychange", ex);
                        }
                        finally
                        {
                            Tracer.Unindent();
                            Tracer.TraceInformation("end-connector-space-object");
                        }
                    }
                    // clearing results for next loop
                    importResultsBatch.Clear();
                }
                #endregion

                #region dequeue csentries

                GetImportEntriesResults importReturnInfo = null;

                Tracer.TraceInformation("total-import-object(s)-left {0:n0}", importResults.Count);
                Tracer.TraceInformation("total-connector-space-object(s)-left {0:n0}", csentryqueue.Count);

                List <CSEntryChange> batch = csentryqueue.Take(ImportRunStepPageSize).ToList();
                if (csentryqueue.Count > ImportRunStepPageSize)
                {
                    csentryqueue.RemoveRange(0, batch.Count);
                }
                else
                {
                    csentryqueue.Clear();
                }
                importReturnInfo = new GetImportEntriesResults();
                importReturnInfo.MoreToImport = MoreToImport || importResults.Count > 0 || (csentryqueue.Count > 0);
                importReturnInfo.CustomData   = returnedCustomData == null ? "" : returnedCustomData.ToString();
                importReturnInfo.CSEntries    = batch;

                Tracer.TraceInformation("should-return-for-more {0}", importReturnInfo.MoreToImport);
                Tracer.TraceInformation("custom-data '{0}'", importReturnInfo.CustomData);
                Tracer.TraceInformation("connector-space-object(s)-returned {0:n0}", importReturnInfo.CSEntries.Count);

                return(importReturnInfo);

                #endregion
            }
            catch (Exception ex)
            {
                Tracer.TraceError("getimportentries", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("getimportentries");
            }
        }
Beispiel #18
0
        PutExportEntriesResults IMAExtensible2CallExport.PutExportEntries(IList <CSEntryChange> csentries)
        {
            Tracer.Enter("putexportentries");
            Tracer.Indent();
            PutExportEntriesResults     exportEntries  = new PutExportEntriesResults();
            PSDataCollection <PSObject> exportPipeline = new PSDataCollection <PSObject>();

            try
            {
                Command cmd = new Command(Path.GetFullPath(ExportScript));
                cmd.Parameters.Add(new CommandParameter("User", Username));
                cmd.Parameters.Add(new CommandParameter("Password", Password));
                cmd.Parameters.Add(new CommandParameter("Credentials", GetSecureCredentials()));
                cmd.Parameters.Add(new CommandParameter("ExportType", exportType));

                foreach (CSEntryChange csentryChange in csentries)
                {
                    Tracer.TraceInformation("adding-object id: {0}, dn: '{1}' [{2}]", csentryChange.Identifier, csentryChange.DN, csentryChange.ObjectModificationType);
                    if (ExportSimpleObjects)
                    {
                        // http://karlprosser.com/coder/2008/06/12/generating-a-propertybag-aka-pscustomobject-in-c/
                        // creating a PSobject without any parameters in the constructor creates a PSCustomObject
                        PSObject obj = new PSObject();
                        // PSNoteProperties are not strongly typed but do contain an explicit type.
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.Identifier, csentryChange.Identifier.ToString()));
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.Anchor, csentryChange.AnchorAttributes.Count > 0 ? csentryChange.AnchorAttributes.FirstOrDefault().Value : ""));
                        obj.Properties.Add(new PSAliasProperty(Constants.ControlValues.IdentifierAsGuid, csentryChange.Identifier.ToString(), typeof(Guid)));
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.ObjectModificationType, csentryChange.ObjectModificationType.ToString()));
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.ObjectType, csentryChange.ObjectType));

                        List <string> attrs = schema.Types[csentryChange.ObjectType].Attributes.Select(a => a.Name).ToList <string>();
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.AttributeNames, attrs));

                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.ChangedAttributeNames, csentryChange.ChangedAttributeNames == null ? new List <string>() : csentryChange.ChangedAttributeNames));
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.DN, csentryChange.DN));
                        obj.Properties.Add(new PSNoteProperty(Constants.ControlValues.RDN, csentryChange.RDN));
                        foreach (AttributeChange ac in csentryChange.AttributeChanges)
                        {
                            if (!ac.IsMultiValued)
                            {
                                foreach (ValueChange vc in ac.ValueChanges)
                                {
                                    obj.Properties.Add(new PSNoteProperty(string.Format("{0}", ac.Name), vc.Value));
                                }
                            }
                            else
                            {
                                List <object> values = new List <object>();
                                foreach (ValueChange vc in ac.ValueChanges)
                                {
                                    values.Add(vc.Value);
                                }
                                obj.Properties.Add(new PSNoteProperty(string.Format("{0}", ac.Name), values.ToArray()));
                            }
                        }
                        exportPipeline.Add(obj);
                    }
                    else
                    {
                        exportPipeline.Add(new PSObject(csentryChange));
                    }
                }

                exportResults = InvokePowerShellScript(cmd, exportPipeline);

                if (exportResults != null)
                {
                    foreach (PSObject result in exportResults)
                    {
                        if (result.BaseObject.GetType() != typeof(System.Collections.Hashtable))
                        {
                            continue;
                        }
                        Hashtable hashTable   = (Hashtable)result.BaseObject;
                        string    ErrorName   = "unspecified-error";
                        string    ErrorDetail = "No details specified";
                        Guid      identifier  = new Guid();

                        // get anchor attribute changes
                        List <AttributeChange> attrchanges = new List <AttributeChange>();
                        foreach (string key in hashTable.Keys)
                        {
                            if (key.Equals(Constants.ControlValues.Identifier, StringComparison.OrdinalIgnoreCase))
                            {
                                try
                                {
                                    identifier = new Guid(hashTable[key].ToString());
                                    Tracer.TraceInformation("got-identifier {0}, {1}", identifier, key);
                                }
                                catch (FormatException fex)
                                {
                                    Tracer.TraceError("identifier-format-error '{0}'", fex.ToString());
                                }
                                continue;
                            }
                            if (key.Equals(Constants.ControlValues.ErrorName, StringComparison.OrdinalIgnoreCase))
                            {
                                ErrorName = hashTable[key].ToString();
                                Tracer.TraceInformation("got-errorname {0}, {1}", ErrorName, key);
                                continue;
                            }
                            if (key.Equals(Constants.ControlValues.ErrorDetail, StringComparison.OrdinalIgnoreCase))
                            {
                                ErrorDetail = hashTable[key].ToString();
                                Tracer.TraceInformation("got-errordetail {0}, {1}", ErrorDetail, key);
                                continue;
                            }
                            if (!(Regex.IsMatch(key, @"^\[.+\]$", RegexOptions.IgnoreCase)))
                            {
                                Tracer.TraceInformation("got-attribute-change {0}: '{1}'", key, hashTable[key]);
                                attrchanges.Add(AttributeChange.CreateAttributeAdd(key, hashTable[key]));
                                continue;
                            }
                        }

                        if (string.IsNullOrEmpty(ErrorName) || ErrorName.Equals("success", StringComparison.OrdinalIgnoreCase))
                        {
                            Tracer.TraceInformation("returning-success id: {0}", identifier);
                            CSEntryChangeResult cschangeresult = CSEntryChangeResult.Create(identifier, attrchanges, MAExportError.Success);
                            exportEntries.CSEntryChangeResults.Add(cschangeresult);
                        }
                        else
                        {
                            Tracer.TraceInformation("returning-error id: {0}, name: {1}, details: {2}", identifier, ErrorName, ErrorDetail);
                            CSEntryChangeResult cschangeresult = CSEntryChangeResult.Create(identifier, attrchanges, MAExportError.ExportErrorCustomContinueRun, ErrorName, ErrorDetail);
                            exportEntries.CSEntryChangeResults.Add(cschangeresult);
                        }
                    }
                }
                exportPipeline.Clear();
                exportResults.Clear();
                exportResults = null;
                return(exportEntries);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("putexportentries", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("putexportentries");
            }
        }
Beispiel #19
0
        public OpenImportConnectionResults OpenImportConnection(System.Collections.ObjectModel.KeyedCollection <string, ConfigParameter> configParameters, Schema types, OpenImportConnectionRunStep openImportRunStep)
        {
            Tracer.IndentLevel = 0;
            Tracer.Enter("openimportconnection");
            Tracer.Indent();
            try
            {
                Tracer.TraceInformation("getting-schema");
                Tracer.Indent();
                try
                {
                    foreach (SchemaType type in types.Types)
                    {
                        foreach (SchemaAttribute attr in type.AnchorAttributes)
                        {
                            Tracer.TraceInformation("{0}-anchor-attribute {1} [{2}]", type.Name, attr.Name, attr.DataType);
                            objectTypeAnchorAttributeNames.Add(type.Name, attr.Name);
                        }
                        foreach (SchemaAttribute attr in type.Attributes)
                        {
                            Tracer.TraceInformation("{0}-attribute {1} [{2}]", type.Name, attr.Name, attr.DataType);
                        }
                    }
                    schema = types;
                }
                catch (Exception ex)
                {
                    Tracer.TraceError("getting-schema", ex);
                }
                finally
                {
                    Tracer.Unindent();
                    Tracer.TraceInformation("got-schema");
                }

                InitializeConfigParameters(configParameters);

                //SetupImpersonationToken();

                OpenRunspace();

                Tracer.TraceInformation("resetting-pipeline-results-and-counters");
                importResults = new List <PSObject>();
                pageToken     = "";

                OpenImportConnectionResults oicr = new OpenImportConnectionResults();
                ImportRunStepPageSize = openImportRunStep.PageSize;
                Tracer.TraceInformation("openimportrunstep-pagesize '{0}'", ImportRunStepPageSize);

                oicr.CustomData = openImportRunStep.ImportType == OperationType.Full ? "" : openImportRunStep.CustomData;
                Tracer.TraceInformation("openimportrunstep-customdata '{0}'", oicr.CustomData);

                importOperationType = openImportRunStep.ImportType;
                Tracer.TraceInformation("openimportrunstep-importtype '{0}'", importOperationType);

                return(oicr);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("openimportconnection", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("openimportconnection");
            }
        }
Beispiel #20
0
        Schema IMAExtensible2GetSchema.GetSchema(KeyedCollection <string, ConfigParameter> configParameters)
        {
            Tracer.Enter("getschema");
            Tracer.Indent();
            try
            {
                Schema schema = Schema.Create();
                InitializeConfigParameters(configParameters);

                OpenRunspace();
                Command cmd = new Command(Path.GetFullPath(SchemaScript));
                cmd.Parameters.Add(new CommandParameter("Username", Username));
                cmd.Parameters.Add(new CommandParameter("Password", Password));
                cmd.Parameters.Add(new CommandParameter("Credentials", GetSecureCredentials()));
                schemaResults = InvokePowerShellScript(cmd, null);
                CloseRunspace();

                if (schemaResults != null)
                {
                    foreach (PSObject obj in schemaResults)
                    {
                        string objectTypeName = null;
                        HashSet <AttributeDefinition> attrs = new HashSet <AttributeDefinition>();

                        foreach (PSPropertyInfo p in obj.Properties)
                        {
                            string[] elements = p.Name.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                            string   attrName = elements[0].Trim();
                            string   attrType = elements[1].Trim();

                            if (string.Equals(attrName, Constants.ControlValues.ObjectClass, StringComparison.OrdinalIgnoreCase))
                            {
                                objectTypeName = p.Value.ToString();
                                Tracer.TraceInformation("object-class '{0}'", objectTypeName);
                            }
                            else
                            {
                                AttributeDefinition ad = new AttributeDefinition();
                                ad.Name         = Regex.Replace(attrName, "^Anchor-", "", RegexOptions.IgnoreCase);
                                ad.IsAnchor     = p.Name.StartsWith("anchor-", StringComparison.OrdinalIgnoreCase);
                                ad.IsMultiValue = p.Name.EndsWith("[]", StringComparison.OrdinalIgnoreCase);
                                switch (attrType.Replace("[]", "").ToLower())
                                {
                                case "boolean":
                                    ad.Type = AttributeType.Boolean;
                                    break;

                                case "binary":
                                    ad.Type = AttributeType.Binary;
                                    break;

                                case "integer":
                                    ad.Type = AttributeType.Integer;
                                    break;

                                case "reference":
                                    ad.Type = AttributeType.Reference;
                                    break;

                                case "string":
                                    ad.Type = AttributeType.String;
                                    break;

                                default:
                                    ad.Type = AttributeType.String;
                                    break;
                                }
                                Tracer.TraceInformation("name '{0}', isanchor: {1}, ismultivalue: {2}, type: {3}", ad.Name, ad.IsAnchor, ad.IsMultiValue, ad.Type.ToString());
                                attrs.Add(ad);
                            }
                        }
                        if (string.IsNullOrEmpty(objectTypeName))
                        {
                            Tracer.TraceError("missing-object-class");
                            throw new Microsoft.MetadirectoryServices.NoSuchObjectTypeException();
                        }

                        SchemaType objectClass = SchemaType.Create(objectTypeName, true);
                        foreach (AttributeDefinition def in attrs)
                        {
                            if (def.IsAnchor)
                            {
                                objectClass.Attributes.Add(SchemaAttribute.CreateAnchorAttribute(def.Name, def.Type));
                            }
                            else
                            {
                                if (def.IsMultiValue)
                                {
                                    objectClass.Attributes.Add(SchemaAttribute.CreateMultiValuedAttribute(def.Name, def.Type));
                                }
                                else
                                {
                                    objectClass.Attributes.Add(SchemaAttribute.CreateSingleValuedAttribute(def.Name, def.Type));
                                }
                            }
                        }
                        if (objectClass.AnchorAttributes.Count == 1)
                        {
                            schema.Types.Add(objectClass);
                        }
                        else
                        {
                            Tracer.TraceError("missing-anchor-definition-on-object");
                            throw new Microsoft.MetadirectoryServices.AttributeNotPresentException();
                        }
                    }
                }
                schemaResults.Clear();
                return(schema);
            }
            catch (Exception ex)
            {
                Tracer.TraceError("getschema", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("getschema");
            }
        }
Beispiel #21
0
        void OpenRunspace()
        {
            Tracer.Enter("openrunspace");
            Tracer.Indent();
            try
            {
                if (runspace == null)
                {
                    Tracer.TraceInformation("creating-runspace");
                    runspace = RunspaceFactory.CreateRunspace();
                    runspace.ApartmentState       = System.Threading.ApartmentState.STA;
                    runspace.ThreadOptions        = PSThreadOptions.Default;
                    runspace.StateChanged        += Runspace_StateChanged;
                    runspace.AvailabilityChanged += Runspace_AvailabilityChanged;
                    Tracer.TraceInformation("created-runspace");
                }
                else
                {
                    Tracer.TraceInformation("existing-runspace-state '{0}'", runspace.RunspaceStateInfo.State);
                }
                if (runspace.RunspaceStateInfo.State == RunspaceState.BeforeOpen)
                {
                    Tracer.TraceInformation("opening-runspace");
                    runspace.Open();
                }
                else
                {
                    Tracer.TraceInformation("runspace-already-open");
                }
                Tracer.TraceInformation("runspace-state '{0}'", runspace.RunspaceStateInfo.State);
                if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
                {
                    Tracer.TraceInformation("runspace-powershell-version {0}.{1}", runspace.Version.Major, runspace.Version.Minor);
                }

                if (powershell == null)
                {
                    Tracer.TraceInformation("creating-powershell");
                    powershell          = PowerShell.Create();
                    powershell.Runspace = runspace;

                    Tracer.TraceInformation("powershell instanceid: {0}, runspace-id: {1}", powershell.InstanceId, powershell.Runspace.InstanceId);
                    Tracer.TraceInformation("powershell apartmentstate: {0}, version: {1}", powershell.Runspace.ApartmentState, powershell.Runspace.Version);

                    // the streams (Error, Debug, Progress, etc) are available on the PowerShell instance.
                    // we can review them during or after execution.
                    // we can also be notified when a new item is written to the stream (like this):
                    powershell.Streams.ClearStreams();
                    powershell.Streams.Error.DataAdded    += new EventHandler <DataAddedEventArgs>(Error_DataAdded);
                    powershell.Streams.Verbose.DataAdded  += new EventHandler <DataAddedEventArgs>(Verbose_DataAdded);
                    powershell.Streams.Warning.DataAdded  += new EventHandler <DataAddedEventArgs>(Warning_DataAdded);
                    powershell.Streams.Debug.DataAdded    += new EventHandler <DataAddedEventArgs>(Debug_DataAdded);
                    powershell.Streams.Progress.DataAdded += new EventHandler <DataAddedEventArgs>(Progress_DataAdded);

                    Tracer.TraceInformation("created-powershell");
                }
            }
            catch (Exception ex)
            {
                Tracer.TraceError("openrunspace", ex);
                throw;
            }
            finally
            {
                Tracer.Unindent();
                Tracer.Exit("openrunspace");
            }
        }