Script works in powershell but not c#

1

This script works when running in PowerShell ISE (it sets the given user's Remote Desktop Services Profile settings in Active Directory):

Get-ADUser FirstName.LastName | ForEach-Object {
    $User = [ADSI]"LDAP://$($_.DistinguishedName)"
    $User.psbase.invokeset("TerminalServicesProfilePath","\\Server\Share\HomeDir\Profile")
    $User.psbase.invokeset("TerminalServicesHomeDrive","H:")
    $User.psbase.invokeset("TerminalServicesHomeDirectory","\\Server\Share\HomeDir") 
    $User.setinfo()
}

But when I try running it from a C# application I get an error for each invokeset that I call:

Exception calling "InvokeSet" with "2" argument(s):

"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"

Here is the code, which is inside my PowerShell class:

public static List<PSObject> Execute(string args)
{
    var returnList = new List<PSObject>();

    using (var powerShellInstance = PowerShell.Create())
    {
        powerShellInstance.AddScript(args);
        var psOutput = powerShellInstance.Invoke();


        if (powerShellInstance.Streams.Error.Count > 0)
        {
            foreach (var error in powerShellInstance.Streams.Error)
            {
                Console.WriteLine(error);
            }
        }

        foreach (var outputItem in psOutput)
        {
            if (outputItem != null)
            {
                returnList.Add(outputItem);
            }
        }
    }

    return returnList;
}

And I call it like this:

var script = $@"
                Get-ADUser {newStarter.DotName} | ForEach-Object {{
                    $User = [ADSI]""LDAP://$($_.DistinguishedName)""
                    $User.psbase.invokeset(""TerminalServicesProfilePath"",""\\file\tsprofiles$\{newStarter.DotName}"")
                    $User.psbase.invokeset(""TerminalServicesHomeDrive"",""H:"")
                    $User.psbase.invokeset(""TerminalServicesHomeDirectory"",""\\file\home$\{newStarter.DotName}"") 
                    $User.setinfo()
                }}";

PowerShell.Execute(script);

Where newStarter.DotName contains the (already existing) AD user's account name.


I tried including Import-Module ActveDirectory at the top of the C# script, but with no effect. I also called $PSVersionTable.PSVersion in both the script running normally and the C# script and both return that version 3 is being used.


After updating the property names to

msTSProfilePath
msTSHomeDrive
msTSHomeDirectory
msTSAllowLogon

I am getting this error in C#:

Exception calling "setinfo" with "0" argument(s): "The attribute syntax specified to the directory service is invalid.

And querying those properties in PowerShell nothing (no error but also no output)


Does anyone happen to know what could cause this?

Many thanks

c#
powershell
active-directory
terminal-services
asked on Stack Overflow Nov 11, 2016 by Bassie • edited Jun 20, 2020 by Community

1 Answer

1

Updated answer: It seems that these attributes don't exist in 2008+. Try these ones instead:

  • msTSAllowLogon
  • msTSHomeDirectory
  • msTSHomeDrive
  • msTSProfilePath

See the answer in this thread for the full explanation.

Original Answer:

The comment from Abhijith pk is probably the answer. You need to run Import-Module ActiveDirectory, just like you need to do in the command line PowerShell.

If you've ever run Import-Module ActiveDirectory in the PowerShell command line, you'll know it takes a while to load. It will be the same when run in C#. So if you will be running several AD commands in your application, you would be better off keeping a Runspace object alive as a static object and reuse it, which means you only load the ActiveDirectory module once.

There is details here about how to do that in C#: https://blogs.msdn.microsoft.com/syamp/2011/02/24/how-to-run-an-active-directory-ad-cmdlet-from-net-c/

Particularly, this is the code:

InitialSessionState iss = InitialSessionState.CreateDefault(); 
iss.ImportPSModule(new string[] { "activedirectory" }); 
Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss); 
myRunSpace.Open();
answered on Stack Overflow Nov 12, 2016 by Gabriel Luci • edited Nov 14, 2016 by Gabriel Luci

User contributions licensed under CC BY-SA 3.0