【问题标题】:PowerShell script runs from the shell, but not from my applicationPowerShell 脚本从 shell 运行,但不是从我的应用程序运行
【发布时间】:2011-07-15 16:49:30
【问题描述】:

我正在尝试创建一个能够运行各种 Powershell 脚本的 Windows 应用程序。

我有一个可以正常工作的脚本(从 Powershell 提示符运行时),我的 Windows 应用程序似乎可以正常执行它,但它无法在我的 OU 上找到方法。

当我从 Windows 应用程序执行脚本时,我会收到以下消息:

错误:检索成员“Create”时发生以下异常:“那里 服务器上没有这样的对象。 "

错误:检索成员“删除”时发生以下异常:“那里 服务器上没有这样的对象。”

Powershell 脚本:

function New-AdUser {

param (
    [string] $Username = $(throw "Parameter -Username [System.String] is required."),
    [string] $Password = $(throw "Parameter -Password [System.String] is required."),
    [string] $OrganizationalUnit = "Users",
    [string] $DisplayName,

    [string] $FirstName,

    [string] $LastName,

    [string] $Initials,
[string] $MobilePhone,
    [string] $Description,
    [switch] $CannotChangePassword,

    [switch] $PasswordNeverExpires,
    [switch] $Disabled

)

try {

    $currentDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

    $dn = $currentDomain.GetDirectoryEntry().distinguishedName
    $ou = [ADSI] "LDAP://CN=$OrganizationalUnit,$dn"

    $userAccount = $ou.Create("user", "cn=$Username")

    $userAccount.SetInfo()



    $userAccount.userAccountControl = ($userAccount.userAccountControl.Item(0) -bxor 0x0002) #Enable the account

    $userAccount.SetInfo()


    $userAccount.sAMAccountName = $Username

    $userAccount.SetInfo()

    $userAccount.userPrincipalName = ("{0}@{1}" -f $Username, $currentDomain.Name)

    if ($DisplayName) {

        $userAccount.displayName = $DisplayName
    }

    if ($Description) {

        $userAccount.description = $Description
    }

    if ($FirstName) {

        $userAccount.givenName = $FirstName
    }


    if ($LastName) {
        $userAccount.SN = $LastName

    }


    if ($Initials) {

        $userAccount.initials = $Initials

    }



if ($MobilePhone) {
        $userAccount.mobile = $MobilePhone

}


    $userAccount.SetInfo()


    $userAccount.SetPassword($Password)

    # Password

    if ($PasswordNeverExpires) {

        $userAccount.userAccountControl = ($userAccount.userAccountControl.Item(0) -bxor 0x10000)
    }


    if ($CannotChangePassword) {
        $everyOne = [System.Security.Principal.SecurityIdentifier]'S-1-1-0'
        $EveryoneDeny = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($Everyone,'ExtendedRight','Deny', [System.Guid]'ab721a53-1e2f-11d0-9819-00aa0040529b')
        $self = [System.Security.Principal.SecurityIdentifier]'S-1-5-10'
        $SelfDeny = new-object System.DirectoryServices.ActiveDirectoryAccessRule ($self,'ExtendedRight','Deny', [System.Guid]'ab721a53-1e2f-11d0-9819-00aa0040529b')

        $userAccount.get_ObjectSecurity().AddAccessRule($selfDeny)

       $userAccount.get_ObjectSecurity().AddAccessRule($EveryoneDeny)


       $userAccount.CommitChanges()
    }

    $userAccount.SetInfo()


    if ($Disabled) {
        $userAccount.userAccountControl = ($userAccount.userAccountControl.Item(0) -bxor 0x0002)

    }
    $userAccount.SetInfo()

} catch {

    Write-Error $_

    $ou.Delete("user", "cn=$Username")

    return $false

}

return $true

}

我的 C# 代码是这样的:

PowerShell ps = PowerShell.Create();

            ps.AddScript(GetScript("New-AdUser.ps1"));
            ps.Invoke();

            ps.AddCommand("New-AdUser").AddParameters(
                new List<CommandParameter>() {
                    new CommandParameter("Username", username),
                    new CommandParameter("Password", password),
                    new CommandParameter("FirstName", firstName),
                    new CommandParameter("LastName", lastName),
                    new CommandParameter("DisplayName", realName),
                    new CommandParameter("Initials", initials),
                    new CommandParameter("MobilePhone", mobilePhone),
                    new CommandParameter("OrganizationalUnit", "Users"),
                    new CommandParameter("PasswordNeverExpires")
                }
            );

            var results = ps.Invoke();

            foreach (var obj in results)
                Console.WriteLine(obj.ToString());

            if (ps.Streams.Error.Count > 0)
            {
                foreach (var err in ps.Streams.Error)
                    Console.WriteLine("ERROR: {0}", err.ToString());
            }

【问题讨论】:

标签: c# powershell active-directory


【解决方案1】:

问题似乎是您的 ADSI 对象 $ou 上的 Create 方法不存在。我会检查它是否被正确创建。在您的应用程序外部运行脚本以确保其正常工作,或者有一个额外的行来显示其成员:

$ou | Get-Member

【讨论】:

  • 正如另一条评论中提到的 - 当我从 Powershell 提示符运行它时,完全相同的脚本可以工作。
  • 那么 Get-Member 在应用程序运行时返回什么?我怀疑应用程序正在以不同的用户身份或在与您运行脚本本身时不同的上下文中运行。
  • 它只是输出这个static string ConvertDNWithBinaryToString(psobject deInstance, psobject dnWithBi naryInstance) static long ConvertLargeIntegerToInt64(psobject deInstance, psobject largeIntege rInstance) Windows 应用程序是从与我测试脚本本身时相同的 Windows 用户执行的。
  • 好像参数没有正确传递。如果我在 powershell 脚本的开头添加一行“$Username”,当 Windows 应用程序执行脚本时,我会得到不同的输出。从提示符运行时,我正确地得到了我传递的字符串值。从 Windows 应用程序运行时,我得到:“System.Management.Automation.Runspaces.CommandParameter”
  • 也许 PowerShell 在通过应用程序运行时加载的配置文件与在命令行上不同?那是造成差异的原因吗?
【解决方案2】:

看起来好像应用程序中的Runspace 是使用限制性RunspaceConfiguration 创建的,因此它找不到您需要的AD 功能的System.DirectoryServices。

当您在应用程序中运行以下内容时,您会得到什么?

string script = @"[AppDomain]::CurrentDomain.GetAssemblies()";
PowerShell ps = new PowerShell();
ps.AddScript(script);
var output = ps.Invoke();
foreach (var a in output.Select(pso => (System.Reflection.Assembly)pso.BaseObject))
    Console.WriteLine("Assembly: " + a.FullName);

当我在普通控制台应用程序的调试器下运行它时,我得到 28 个程序集(19 个在调试器之外),包括 System.DirectoryServices。当我在 vanilla 命令提示符下运行 [AppDomain]::CurrentDomain.GetAssemblies() 位时,它显示 16。 System.DirectoryServices 出现在所有三个列表中。

【讨论】:

    【解决方案3】:

    似乎您只是在 AD 中创建用户。通过让 c# 代码调用 powershell 脚本,您将在脚本中添加另一个移动部分。为什么不直接在 C# 代码中调用它。查看这篇MSDN 文章。

    【讨论】:

    • 我决定采用这种方式而不是 PowerShell 解决方案。起初我想运行 PowerShell 文件,因为 sys.tech.'s 可以自己维护文件。
    【解决方案4】:

    从 C# 中运行时,我发现我需要添加 PowerShell 管理单元“Microsoft.Windows.AD”才能运行它提供的 cmdlet。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-07
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多