簡體   English   中英

Powershell遠程靜態IP通過腳本

[英]Powershell remote static IP via script

我正在尋找一個Powershell函數來遠程地為運行時指定的計算機分配靜態IP地址。 我做了一些研究,發現了Win32_NetworkAdapterConfiguration類,這看起來就像我需要的那樣。 所以我坐下來給自己寫了一個函數:

Function Set-StaticIPAddress
{
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 0,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [String] $ComputerName
        ,
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [Alias("IPv4Address")]
        [String] $IPAddress
        ,
        [Parameter(Position = 2)]
        [String] $SubnetMask = "none"
        ,
        [Parameter(Position = 3)]
        [String] $DefaultGateway = "none"
        ,
        [Parameter(Position = 4)]
        [String[]] $DNSServers = ("172.16.1.36","172.16.1.78")
        ,
        [Parameter(Position = 5)]
        [PSCredential] $Credential
    )

    process
    {
        # There's some error-checking here that I've snipped out for convenience

        Write-Verbose "Testing connection to $ComputerName"
        if (-not (Test-Connection $ComputerName))
        {
            Write-Error "Unable to connect to $ComputerName."
            return
        }


        Write-Verbose "Obtaining remote WMI reference"
        if ($Credential)
        {
            $wmi = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -Filter "IPEnabled = 'True'" -Credential $Credential
        } else {
            $wmi = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -Filter "IPEnabled = 'True'"
        }

        Write-Verbose "Attempting to set DNS servers"
        $wmi.SetDNSServerSearchOrder($DNSServers)

        Write-Verbose "Attempting to set dynamic DNS registration"
        $wmi.SetDynamicDNSRegistration($true)

        Write-Verbose "Attempting to set static IP address and subnet mask"
        $wmi.EnableStatic($IPAddress, $SubnetMask)

        Clear-DnsClientCache   #This may not be necessary; I added it as a troubleshooting step

        Write-Verbose "Attempting to set default gateway"
        $wmi.SetGateways($DefaultGateway, 1)

        Write-Output $wmi
    }
}

問題是, EnableStatic方法似乎永遠不會返回一個值 - 成功或失敗代碼。 我在一台坐在我旁邊的機器上測試了這個功能,當腳本仍在等待“嘗試設置靜態IP地址和子網掩碼”階段時,我在機器上提取了配置並找到了靜態IP和子網面具套裝。 沒有默認網關(這是有道理的,因為我在腳本中沒有那么遠)。 有問題的計算機沒有網絡訪問權限,因為缺少默認網關。

我也嘗試從交互式shell運行相同的命令,並在同一命令上發生相同的“凍結”:

$wmi.EnableStatic($IPAddress, $SubnetMask)

我最好的猜測是,更改網絡適配器配置會破壞遠程WMI連接。 有沒有辦法使這項工作,所以我可以腳本100%遠程分配靜態IP地址?

編輯:我MacGyvered另一個創建ScriptBlock對象並使用Invoke-Command將其發送到遠程計算機的嘗試。 我不得不做一些有趣的步法來獲得一個IP地址數組轉換成字符串文字,包括引號,但我現在可以確認腳本塊具有正確的語法和所有這些。 不幸的是,這樣做會導致我的PS窗口抱怨網絡連接已丟失(因為IP地址已更改)並且腳本塊未成功完成。

$wmiLiteral = '$wmi' # used so the script block actually creates and references a variable, $wmi
$script = 
    "$wmiLiteral = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter ""IPEnabled = 'True'"";
     $wmiLiteral.EnableStatic(""$IPAddress"", ""$SubnetMask"");
     $wmiLiteral.SetGateways(""$DefaultGateway"", 1);
     $wmiLiteral.SetDNSServerSearchOrder($DNSServersList);
     Write-Output $wmiLiteral"

Write-Verbose "Script block:`n-------------`n$script`n---------------"
$scriptBlock = [scriptblock]::Create($script)

Write-Verbose "Testing connection to $ComputerName"
if (-not (Test-Connection $ComputerName))
{
    Write-Error "Unable to connect to $ComputerName."
    return
}

Write-Verbose "Invoking scriptblock"
if ($Credential)
{
    $output = Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock -Credential $Credential
} else {
    $output = Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock
}

我會在一個使用localHost作為$computername參數的腳本中調用你的函數,然后在遠程計算機上遠程執行( invoke-command )這個腳本,使用powershell遠程會話( New-PSSession ),或者用這個腳本創建一個遠程PowerShell進程作為WMI的參數(在這種情況下,您必須復制遠程計算機上的srcript)。

您還可以在遠程計算機上安排此腳本...一般的想法是在操作期間不使用網絡。

使用Invoke-Command在遠程計算機上運行netsh可能會更幸運,它在一個命令中設置IP地址,子網掩碼和網關。 但是, netsh為接口使用不同的名稱,您可以從Win32_NetworkAdapter類的NetConnectionID屬性獲取該名稱。

$InterfaceName = $Get-WmiObject Win32_NetworkAdapter | ?{$_.Description -eq $wmi.Description} | select -ExpandProperty NetConnectionID
Invoke-Command -ComputerName $ComputerName -Credential $Credential -ScriptBlock {netsh interface ip set address $InterfaceName static $IPAddress $SubnetMask $DefaultGateway 1}

您可以將第二行包裝在另一個if ($Credential)塊中。

但是,我強烈建議您驗證過濾器是否返回一個對象而不是一個對象數組,如上面的評論所示。 或者,為了安全起見,改變

$wmi = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -Filter "IPEnabled = 'True'" -Credential $Credential

$wmi = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -Filter "IPEnabled = 'True'" -Credential $Credential | select -First 1

這將確保您只獲得一個對象,但當然,如果有多個IPEnabled為 true,則無法確保它必然是您想要的對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM