脚本在 powershell 中有效,但在 c# 中无效
Script works in powershell but not c#
此脚本在 PowerShell ISE 中 运行 时有效(它在 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()
}
但是当我从 C# 应用程序中尝试 运行 它时,我调用的每个 invokeset
都会出错:
Exception calling "InvokeSet" with "2" argument(s):
"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"
这是代码,在我的里面 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\tsprofiles$\{newStarter.DotName}"")
$User.psbase.invokeset(""TerminalServicesHomeDrive"",""H:"")
$User.psbase.invokeset(""TerminalServicesHomeDirectory"",""\file\home$\{newStarter.DotName}"")
$User.setinfo()
}}";
PowerShell.Execute(script);
其中 newStarter.DotName
包含(已经存在的)AD 用户的帐户名。
我尝试在 C#
脚本的顶部包含 Import-Module ActveDirectory
,但没有效果。我还在脚本 运行 和 C#
脚本中都调用了 $PSVersionTable.PSVersion
,并且都使用了版本 3 return。
将 属性 名称更新为
后
msTSProfilePath
msTSHomeDrive
msTSHomeDirectory
msTSAllowLogon
我在 C# 中遇到此错误:
Exception calling "setinfo" with "0" argument(s): "The attribute syntax specified to the directory service is invalid.
并且在 PowerShell 中查询这些属性没有任何问题(没有错误但也没有输出)
有没有人碰巧知道是什么原因造成的?
非常感谢
更新答案:这些属性似乎在 2008+ 中不存在。试试这些:
- msTSAllowLogon
- msTSHomeDirectory
- msTSHomeDrive
- msTSProfilePath
请参阅 this thread 中的答案以获得完整解释。
原答案:
来自 Abhijith pk 的评论可能就是答案。您需要 运行 Import-Module ActiveDirectory
,就像您需要在命令行 PowerShell 中执行的操作一样。
如果您曾在 PowerShell 命令行中 运行 Import-Module ActiveDirectory
,您就会知道加载需要一段时间。在 C# 中 运行 时也是一样的。因此,如果您将 运行 在您的应用程序中使用多个 AD 命令,您最好将 Runspace 对象作为静态对象保持活动状态并重用它,这意味着您只加载 ActiveDirectory 模块一次。
这里有关于如何在 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.ImportPSModule(new string[] { "activedirectory" });
Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss);
myRunSpace.Open();
此脚本在 PowerShell ISE 中 运行 时有效(它在 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()
}
但是当我从 C# 应用程序中尝试 运行 它时,我调用的每个 invokeset
都会出错:
Exception calling "InvokeSet" with "2" argument(s):
"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"
这是代码,在我的里面 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\tsprofiles$\{newStarter.DotName}"")
$User.psbase.invokeset(""TerminalServicesHomeDrive"",""H:"")
$User.psbase.invokeset(""TerminalServicesHomeDirectory"",""\file\home$\{newStarter.DotName}"")
$User.setinfo()
}}";
PowerShell.Execute(script);
其中 newStarter.DotName
包含(已经存在的)AD 用户的帐户名。
我尝试在 C#
脚本的顶部包含 Import-Module ActveDirectory
,但没有效果。我还在脚本 运行 和 C#
脚本中都调用了 $PSVersionTable.PSVersion
,并且都使用了版本 3 return。
将 属性 名称更新为
后msTSProfilePath
msTSHomeDrive
msTSHomeDirectory
msTSAllowLogon
我在 C# 中遇到此错误:
Exception calling "setinfo" with "0" argument(s): "The attribute syntax specified to the directory service is invalid.
并且在 PowerShell 中查询这些属性没有任何问题(没有错误但也没有输出)
有没有人碰巧知道是什么原因造成的?
非常感谢
更新答案:这些属性似乎在 2008+ 中不存在。试试这些:
- msTSAllowLogon
- msTSHomeDirectory
- msTSHomeDrive
- msTSProfilePath
请参阅 this thread 中的答案以获得完整解释。
原答案:
来自 Abhijith pk 的评论可能就是答案。您需要 运行 Import-Module ActiveDirectory
,就像您需要在命令行 PowerShell 中执行的操作一样。
如果您曾在 PowerShell 命令行中 运行 Import-Module ActiveDirectory
,您就会知道加载需要一段时间。在 C# 中 运行 时也是一样的。因此,如果您将 运行 在您的应用程序中使用多个 AD 命令,您最好将 Runspace 对象作为静态对象保持活动状态并重用它,这意味着您只加载 ActiveDirectory 模块一次。
这里有关于如何在 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.ImportPSModule(new string[] { "activedirectory" });
Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss);
myRunSpace.Open();