Powershell удаленный статический IP через скрипт
Я собираюсь написать функцию 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
    }
}
Я также пробовал запускать те же команды из интерактивной оболочки, и та же самая "заморозка" происходит на том же самом команда:
$wmi.EnableStatic($IPAddress, $SubnetMask)
Мое лучшее предположение заключается в том, что изменение конфигурации сетевого адаптера нарушает удаленное соединение WMI. Есть ли способ сделать это так, чтобы я мог написать сценарий назначения статического IP-адреса 100% удаленно?
Edit: I MacGyvered еще одна попытка, которая создает объект ScriptBlock и отправляет его на удаленный компьютер с помощью команды Invoke. Мне пришлось проделать кое-какую интересную работу ногами, чтобы получить массив 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
}
2 ответа:
Возможно, Вам повезет больше, если вы используете Invoke-Command для запуска netsh на удаленном компьютере, который устанавливает IP-адрес, маску подсети и шлюз в одной команде. Однако netsh использует другое имя для интерфейса, которое можно получить из свойства NetConnectionID класса Win32_NetworkAdapter.
$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 $CredentialTo
$wmi = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -Filter "IPEnabled = 'True'" -Credential $Credential | select -First 1Это гарантирует, что вы получаете только один объект, но, конечно, он не может гарантировать, что это обязательно тот, который вы хотите, если есть более одного с IPEnabled true.
Я бы вызвал вашу функцию в скрипте, который использует
localHostв качестве параметра$computername, а затем удаленно выполнил (invoke-command) этот скрипт на удаленном компьютере, используя удаленные сеансы powershell (New-PSSession) или создав удаленный процесс PowerShell с этим скриптом в качестве параметра с помощью WMI (в этом случае вам нужно скопировать srcript на удаленный комптер).Вы также можете запланировать этот сценарий на удаленном компьютере ... общая идея заключается в том, чтобы не использовать сеть во время работы.