脚本在 powershell 中有效,但在 c# 中无效 [英] Script works in powershell but not c#

查看:26
本文介绍了脚本在 powershell 中有效,但在 c# 中无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此脚本在 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.ImportPSModule(new string[] { "activedirectory" }); 
Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss); 
myRunSpace.Open();

这篇关于脚本在 powershell 中有效,但在 c# 中无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆