问题描述
此脚本在 PowerShell ISE 中运行时有效(它在 Active Directory 中设置给定用户的远程桌面服务配置文件设置):
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","\ServerShareHomeDirProfile") $User.psbase.invokeset("TerminalServicesHomeDrive","H:") $User.psbase.invokeset("TerminalServicesHomeDirectory","\ServerShareHomeDir") $User.setinfo() }
但是当我尝试从 C# 应用程序运行它时,我会收到我调用的每个 invokeset 的错误:
But when I try running it from a C# application I get an error for each invokeset that I call:
异常调用InvokeSet"与2"参数:
Exception calling "InvokeSet" with "2" argument(s):
"未知名称.(来自 HRESULT 的异常:0x80020006 (DISP_E_UNKNOWNNAME))"
"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"
这是我的 PowerShell 类中的代码:
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; }
我这样称呼它:
var script = $@" Get-ADUser {newStarter.DotName} | ForEach-Object {{ $User = [ADSI]""LDAP://$($_.DistinguishedName)"" $User.psbase.invokeset(""TerminalServicesProfilePath"",""\file sprofiles${newStarter.DotName}"") $User.psbase.invokeset(""TerminalServicesHomeDrive"",""H:"") $User.psbase.invokeset(""TerminalServicesHomeDirectory"",""\filehome${newStarter.DotName}"") $User.setinfo() }}"; PowerShell.Execute(script);
其中 newStarter.DotName 包含(已经存在的)AD 用户的帐户名称.
Where newStarter.DotName contains the (already existing) AD user's account name.
我尝试在 C# 脚本的顶部包含 Import-Module ActveDirectory,但没有效果.我还在正常运行的脚本和 C# 脚本中调用了 $PSVersionTable.PSVersion 并且都返回了正在使用的版本 3.
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.
更新属性名称后
msTSProfilePath msTSHomeDrive msTSHomeDirectory msTSAllowLogon
我在 C# 中遇到此错误:
I am getting this error in C#:
异常调用setinfo"与0"参数:为目录服务指定的属性语法无效.
Exception calling "setinfo" with "0" argument(s): "The attribute syntax specified to the directory service is invalid.
在 PowerShell 中查询这些属性没有任何问题(没有错误但也没有输出)
And querying those properties in PowerShell nothing (no error but also no output)
有人碰巧知道是什么导致了这种情况吗?
Does anyone happen to know what could cause this?
非常感谢
推荐答案
更新的答案: 似乎这些属性在 2008+ 中不存在.试试这些:
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.
原答案:
来自Abhijith pk 的评论可能就是答案.您需要运行 Import-Module ActiveDirectory,就像您需要在命令行 PowerShell 中执行一样.
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.
如果您曾经在 PowerShell 命令行中运行过 Import-Module ActiveDirectory,您就会知道加载需要一段时间.在 C# 中运行时也是如此.因此,如果您将在应用程序中运行多个 AD 命令,最好将 Runspace 对象作为静态对象保持活动状态并重用它,这意味着您只需加载 ActiveDirectory 模块一次.
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.
这里有关于如何在 C# 中做到这一点的详细信息:https://blogs.msdn.microsoft.com/syamp/2011/02/24/how-to-run-an-active-directory-ad-cmdlet-from-net-c/
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/
特别是,这是代码:
InitialSessionState iss = InitialSessionState.CreateDefault(); iss.ImportP**odule(new string[] { "activedirectory" }); Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss); myRunSpace.Open();