Function 首次尝试时未找到函数

Function 首次尝试时未找到函数,function,powershell,active-directory,Function,Powershell,Active Directory,我有一个脚本,它创建了一个GUI来输入参数来创建一个广告用户。该脚本包含一个大函数(创建我在网上找到的广告浏览器的函数)。该函数在脚本开始时调用(一个文本框需要函数输入以预先填充值),或者通过单击GUI中的按钮来调用。问题是,当我运行脚本时,会收到错误消息,提示“术语‘Browse AD’(=函数名称)未被识别为cmdlet、函数的名称…”当我从PowerShell ISE运行脚本时,我第一次尝试时会收到此错误,脚本会启动(但浏览器不工作)取消脚本并再次运行后,浏览器工作正常,不会显示任何错误消

我有一个脚本,它创建了一个GUI来输入参数来创建一个广告用户。该脚本包含一个大函数(创建我在网上找到的广告浏览器的函数)。该函数在脚本开始时调用(一个文本框需要函数输入以预先填充值),或者通过单击GUI中的按钮来调用。问题是,当我运行脚本时,会收到错误消息,提示“术语‘Browse AD’(=函数名称)未被识别为cmdlet、函数的名称…”当我从PowerShell ISE运行脚本时,我第一次尝试时会收到此错误,脚本会启动(但浏览器不工作)取消脚本并再次运行后,浏览器工作正常,不会显示任何错误消息。我没有在同一时间触摸脚本,我只是第二次运行它,没有做任何更改。但更大的问题是,当脚本直接从文件启动时(这自然是它的预期使用方式),它总是第一次尝试,因此总是显示错误,浏览器无法工作。知道发生了什么吗

这就是功能:

function Browse-AD()
{
    # original inspiration: https://itmicah.wordpress.com/2013/10/29/active-directory-ou-picker-in-powershell/
    # author: Rene Horn the.rhorn@gmail.com
<#
    Copyright (c) 2015, Rene Horn
    All rights reserved.
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#>
    $dc_hash = @{}
    $selected_ou = $null
    Import-Module ActiveDirectory
    $forest = Get-ADForest
    [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
    [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null

    function Get-NodeInfo($sender, $dn_textbox)
    {
        $selected_node = $sender.Node
        $dn_textbox.Text = $selected_node.Name
    }

    function Add-ChildNodes($sender)
    {
        $expanded_node = $sender.Node
        if ($expanded_node.Name -eq "root") {
            return
        }
        $expanded_node.Nodes.Clear() | Out-Null
        $dc_hostname = $dc_hash[$($expanded_node.Name -replace '(OU=[^,]+,)*((DC=\w+,?)+)','$2')]
        $child_OUs = Get-ADObject -Server $dc_hostname -Filter 'ObjectClass -eq "organizationalUnit" -or ObjectClass -eq "container"' -SearchScope OneLevel -SearchBase $expanded_node.Name
        if($child_OUs -eq $null) {
            $sender.Cancel = $true
        } else {
            foreach($ou in $child_OUs) {
                $ou_node = New-Object Windows.Forms.TreeNode
                $ou_node.Text = $ou.Name
                $ou_node.Name = $ou.DistinguishedName
                $ou_node.Nodes.Add('') | Out-Null
                $expanded_node.Nodes.Add($ou_node) | Out-Null
            }
        }
    }

    function Add-ForestNodes($forest, [ref]$dc_hash)
    {
        $ad_root_node = New-Object Windows.Forms.TreeNode
        $ad_root_node.Text = $forest.RootDomain
        $ad_root_node.Name = "root"
        $ad_root_node.Expand()
        $i = 1
        foreach ($ad_domain in $forest.Domains) {
            Write-Progress -Activity "Querying AD forest for domains and hostnames..." -Status $ad_domain -PercentComplete ($i++ / $forest.Domains.Count * 100)
            $dc = Get-ADDomainController -Server $ad_domain
            $dn = $dc.DefaultPartition
            $dc_hash.Value.Add($dn, $dc.Hostname)
            $dc_node = New-Object Windows.Forms.TreeNode
            $dc_node.Name = $dn
            $dc_node.Text = $dc.Domain
            $dc_node.Nodes.Add("") | Out-Null
            $ad_root_node.Nodes.Add($dc_node) | Out-Null
        }
        return $ad_root_node
    }

    $main_dlg_box = New-Object System.Windows.Forms.Form
    $main_dlg_box.ClientSize = New-Object System.Drawing.Size(400,600)
    $main_dlg_box.MaximizeBox = $false
    $main_dlg_box.MinimizeBox = $false
    $main_dlg_box.FormBorderStyle = 'FixedSingle'

    # widget size and location variables

    $ctrl_width_col = $main_dlg_box.ClientSize.Width/20
    $ctrl_height_row = $main_dlg_box.ClientSize.Height/15
    $max_ctrl_width = $main_dlg_box.ClientSize.Width - $ctrl_width_col*2
    $max_ctrl_height = $main_dlg_box.ClientSize.Height - $ctrl_height_row
    $right_edge_x = $max_ctrl_width
    $left_edge_x = $ctrl_width_col
    $bottom_edge_y = $max_ctrl_height
    $top_edge_y = $ctrl_height_row

    # setup text box showing the distinguished name of the currently selected node

    $dn_text_box = New-Object System.Windows.Forms.TextBox

    # can not set the height for a single line text box, that's controlled by the font being used

    $dn_text_box.Width = (14 * $ctrl_width_col)
    $dn_text_box.Location = New-Object System.Drawing.Point($left_edge_x, ($bottom_edge_y - $dn_text_box.Height))
    $main_dlg_box.Controls.Add($dn_text_box)

    # /text box for dN

    # setup Ok button

    $ok_button = New-Object System.Windows.Forms.Button
    $ok_button.Size = New-Object System.Drawing.Size(($ctrl_width_col * 2), $dn_text_box.Height)
    $ok_button.Location = New-Object System.Drawing.Point(($right_edge_x - $ok_button.Width), ($bottom_edge_y - $ok_button.Height))
    $ok_button.Text = "Ok"
    $ok_button.DialogResult = 'OK'
    $main_dlg_box.Controls.Add($ok_button)

    # /Ok button

    # setup tree selector showing the domains

    $ad_tree_view = New-Object System.Windows.Forms.TreeView
    $ad_tree_view.Size = New-Object System.Drawing.Size($max_ctrl_width, ($max_ctrl_height - $dn_text_box.Height - $ctrl_height_row*1.5))
    $ad_tree_view.Location = New-Object System.Drawing.Point($left_edge_x, $top_edge_y)
    $ad_tree_view.Nodes.Add($(Add-ForestNodes $forest ([ref]$dc_hash))) | Out-Null
    $ad_tree_view.Add_BeforeExpand({Add-ChildNodes $_})
    $ad_tree_view.Add_AfterSelect({Get-NodeInfo $_ $dn_text_box})
    $main_dlg_box.Controls.Add($ad_tree_view)

    # /tree selector

    if ($main_dlg_box.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK)
    {
        return  $dn_text_box.Text
    }
    return $null
}
此外,我将函数设置为文本框的值,以便浏览器在脚本运行之前启动,并将AD路径直接预先填充为我需要的值:

$Location_val                    = New-Object system.Windows.Forms.TextBox
$Location_val.multiline          = $false
$Location_val.text               = Browse-AD
$Location_val.width              = 250
$Location_val.height             = 20
$Location_val.location           = New-Object System.Drawing.Point(200,160)
准确的错误信息如下:

Browse-AD : The term 'Browse-AD' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\a.Petr.Synek\Documents\New_ADuser_woodgroup_complete.ps1:204 char:42
+ $Location_standard_val.Text            = Browse-AD
+                                          ~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Browse-AD:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

第204行有以下文字:
$Location\u val.text=根据要求浏览广告

,我的评论作为答案:


在脚本中,需要将
浏览广告
功能放在顶部,并将所有其他代码放在其下方

如果此顺序不正确,在第一次运行时,函数在解析之前被调用,并给出错误消息


第二次,PowerShell已经解析了整个代码,因此该函数是已知的。PowerShell(与VBScript不同)从上到下解析代码。

您能发布完整的错误消息吗。同样
$Location\u val.text=Browse AD
应该是
$Location\u val.text=“Browse AD”
,但是如果我写
$Location\u val.text=“Browse AD”
我只会将“Browse AD”文本放在变量中,而不是调用函数并打开浏览器。我会把错误信息带到问题中。我想为了帮助我,我需要看到完整的代码,就像你写的一样。当然要减去任何密码或用户名。在你的脚本中,你需要把
浏览广告
功能放在上面,把所有其他代码放在下面。如果此顺序不正确,则在第一次运行时,将在解析函数之前调用该函数,并给出错误消息。第二次,PowerShell已经解析了整个代码,因此该函数是已知的。PowerShell(与VBScript不同)自上而下地解析代码,真不敢相信这么简单
@Theo
。实际上,在将函数移到顶部之后,问题就消失了。请把它写下来作为答复,以便我能接受。
Browse-AD : The term 'Browse-AD' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\a.Petr.Synek\Documents\New_ADuser_woodgroup_complete.ps1:204 char:42
+ $Location_standard_val.Text            = Browse-AD
+                                          ~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Browse-AD:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException