0
votes

I am creating an exchange user (new-mailbox) and then setting some AD parameters on them after the user is created in the same runspace with commands that will not run in the Exchange runspace unless import-module 'activedirecty' is ran. Is there a way to import the module after the runspace is created as I can do with the Powershell prompt?

inside the same runspace session I want to run:

new-mailbox
set-mailbox
set-user
set-aduser 

The last one is what requires me to import the AD module I can successfully run the command inside of Powershell directly, but can't seem to figure out how to add the module mid runspace session? I'd tried

powershell.AddParameter("import-module -name 'activedirectory'; set-aduser xxxx")

and

powershell.AddParameter("import-module -name 'activedirectory'")
powershell.AddParameter("set-aduser xxxx")

and

powershell.AddScript("import-module -name 'activedirectory'; set-aduser xxxx")

This works below

public void SetPasswordNeverExpiresProperty(bool PasswordNeverExpires, string alias)
    {           
        string dn = "CN=xxx,OU=xxx,OU=xxx=xxx=xxx=xxx,DC=xx,DC=xx,DC=xxx,DC=xxx"

        DirectoryEntry objRootDSE = new DirectoryEntry("LDAP://" + dn);
        ArrayList props = new ArrayList();
        int NON_EXPIRE_FLAG = 0x10000;
        int EXPIRE_FLAG = 0x0200;
        int valBefore = (int) objRootDSE.Properties["userAccountControl"].Value;            
        objRootDSE.Properties["userAccountControl"].Value = EXPIRE_FLAG;
        objRootDSE.CommitChanges();
        string valAfter = objRootDSE.Properties["userAccountControl"].Value.ToString();`

And I'm out of guesses, any help would be appreciated.

        PSCredential ExchangeCredential = new PSCredential(PSDomain + @"\" + PSUsername, PSpwd);
        WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri("xxxxxx/powershell"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", ExchangeCredential);
        connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos;


        using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            PowerShell powershell = PowerShell.Create();

                if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
                {
                    // do nothing
                }
                else
                {
                    runspace.Open();
                    powershell.Runspace = runspace;
                }
            try
                {
                    psobjs = powershell.Invoke();
                }
                catch (Exception ex)
                {
                    result = "Failed: " + ex.Message;
                }

                powershell.Commands.Clear();

        }

enter image description here

1
I don't see where you are setting the Runspace property on the PowerShell object i.e. $powershell.Runspace = $runspaceBruce Payette
I've added the code that I'm using to do that. I should also mention that the first 3 commands work correctly with the current code, the only one I'm having trouble with is the one dependent on the ActiveDirectory module.Bbb
Can you put the actual code in-line (i.e. where it says //code here)? Looking at the fragments, this powershell.AddParameter("import-module -name 'activedirectory'") is wrong and won't work but this powershell.AddScript("import-module -name 'activedirectory'; set-aduser xxxx") should work. However the preferred way would be to do powershell.AddCommand("Import-Module").AddParameter("Name", "ActiveDirectory"). What happens with you do the Import-Module -do you get an error? And are you sure that the ActiveDirectory module is available on the Exchange server (as opposed to your local box)Bruce Payette
The code fails at psobjs = powershell.Invoke(); Failed: The term ' Set-AdUser' 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. I've edited what you've requested.Bbb
I found that too: You can't use Import-Module when using remote PowerShell like that. You may be better off to use DirectoryEntry instead of PowerShell to modify the AD account, but the problem is replication (if you have more than one domain controller). If you do have more than one DC, you have to make sure you do both things on the same one.Gabriel Luci

1 Answers

1
votes

I'll sum up my comments in an answer, since it seems I was unexpectedly helpful :)

I also had found that you can't use Import-Module when using remote PowerShell like that. It's kind of annoying, but such is life.

Years ago, I implemented an automatic account creation service in our environment for AD and Exchange 2010. I found I had to do the AD account manipulation with DirectoryEntry and then only the Exchange stuff with PowerShell.

The problem is making sure that both things happen on the same domain controller so you don't run into replication problems.

So you have two options: Use New-Mailbox to create the mailbox and AD account in one shot. As you pointed out, the OriginatingServer property of the result has the domain controller. But there is also a DistinguishedName property there too! (I just found this when you mentioned the server property) Then you can create a DirectoryEntry object against the same domain controller like this:

new DirectoryEntry($"LDAP://{domainController}/{distinguishedName}")

Or, what I did (I think because I didn't realize at the time that I could get the DC from the result of New-Mailbox), is create the AD object first with DirectoryEntry, pull the domain controller it got created on from .Options.GetCurrentServerName(), then pass that in the DomainController parameter to Enable-Mailbox.