2013-07-23 1 views
3

런타임에 지정된 컴퓨터에 고정 IP 주소를 원격으로 할당하는 Powershell 함수를 작성하려고합니다. 몇 가지 조사를 해본 결과 Win32_NetworkAdapterConfiguration 클래스가 발견되었습니다. 그래서 앉아서 자신에게 기능 썼다 :Powershell 원격 정적 IP를 통해 스크립트

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 및 서브넷을 발견했습니다 마스크 세트. 기본 게이트웨이가 없었습니다. (필자가 스크립트에서 그다지 이해하지 못했기 때문에 의미가 있습니다.) 기본 게이트웨이가 없기 때문에 문제의 컴퓨터에 네트워크 액세스 권한이 없습니다.

나는 또한 대화 형 쉘에서 같은 명령을 실행 시도하고 같은 명령에서 발생 "동결"같은 :

$wmi.EnableStatic($IPAddress, $SubnetMask) 

내 추측은 네트워크 어댑터 구성을 변경하는 것을 리모컨을 파괴한다 WMI 연결. 정적 IP 주소 할당을 원격으로 100 % 스크립트 할 수 있도록이 작업을 수행 할 수있는 방법이 있습니까?

편집 : 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 
} 
+0

글쎄, 스크립트는 필터가 항상 하나의 개체 만 반환한다고 가정하지만 개체 배열을 반환 할 수 있습니다. 그건 제쳐두고, 당신의 이론은 그럴듯 해 보입니다. 이것을 시도하십시오 : EnableStatic 메소드를 호출하기 전에, 당신이보고있는 어댑터에 대한 설명을 변수에 저장하십시오 :'$ description = $ wmi.Description' EnableStatic을 호출 한 후 WMI 객체를 다시 얻습니다 :'$ wmi = Get- WmiObject Win32_NetworkAdapterConfiguration -Filter "Description = '$ description'" –

+0

응답 해 주셔서 감사합니다. 그러나 차이는 없습니다. 스크립트를 처음부터 EnableStatic 메서드 호출을 지나칠 수는 없습니다. 그 이후의 Write-Verbose cmdlet조차도 실행되지 않습니다. –

+0

EnableStatic을 먼저 실행 한 다음 추가 메서드를 실행하면 어떻게됩니까? 다른 스크립트를 탐색 한 후에는 차이점 중 하나 일 수 있습니다. 또한 하나 이상의 컴퓨터에서이 작업을 시도해 보셨습니까? 이게 문제가있는 유일한 사람입니까? –

답변

1

당신은 하나의 명령으로 IP 주소, 서브넷 마스크, 게이트웨이를 설정하는 원격 컴퓨터에 netsh를를 실행하는 호출-명령를 사용하여 더 많은 행운을 가질 수 있습니다. 그러나 netshNetConnectionID 속성 인 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 $Credential 

당신은 단지 하나 개의 객체를 얻고 있지만, 물론 그것이 필요하다고이 있다면 당신이 원하는 일을 보장 할 수 있도록 것이라고

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

에 둘 이상의 숫자가 이고 IPEnabled가입니다.

+0

"파일 이름, 디렉터리 이름 또는 볼륨 레이블 구문이 잘못되었습니다."라는 오류 메시지가 나타납니다. 어딘가에 따옴표가 누락 된 것처럼 들리지만 Invoke-Command를 사용하면 실행중인 실제 명령을 표시하는 방법을 모르겠습니다. 'Invoke-Command -ComputerName $ ComputerName -ScriptBlock {netsh interface ip set address "$ InterfaceName"static $ IPAddress $ SubnetMask $ DefaultGateway}' –

+0

일반적으로이 오류는 유효하지 않은 문자를 나타냅니다. 너는 netsh에 대한 논쟁에서 어떤 것을 인용하는 기회인가? 따옴표를 사용하지 않고 사용해보십시오. 그래도 작동하지 않는다면 모든 변수를 이중 인용 부호로 묶으십시오.하지만 그렇게 할 필요는 없습니다. –

+0

오, 잠깐. 나는 뭔가를 남겼다. 그것이 오류의 원인인지는 확실치 않지만 기본 게이트웨이 다음에 메트릭이 있어야합니다. 간단히 말해서, 대부분의 경우 명령의 끝에 '1'을 붙입니다. 나는 그것을 반영하기 위해 답을 편집 할 것이다. –

1

내가 PowerShell을 원격 세션 (New-PSSession)를 사용하여, 또는 원격 PowerShell을 프로세스에를 작성, $computername 매개 변수로 localHost을 사용하고 원격 원격 컴퓨터에서이 스크립트를 (invoke-command)을 실행하는 스크립트에서 함수를 호출 할 것 이 스크립트는 WMI의 매개 변수로 사용됩니다 (이 경우 원격 컴파일러에서 srcript를 복사해야합니다).

원격 컴퓨터에서이 스크립트를 예약 할 수도 있습니다 ... 일반적인 생각은 작동 중에 네트워크를 사용하지 않는 것입니다.

+0

응답 해 주셔서 감사합니다. :) Invoke-Command와 스크립트 블록을 사용하도록 스크립트를 조정하려했지만 전체 블록을 성공적으로 완료하지 못했습니다. (편집 : 질문에서 추가 정보를 참조하십시오.) 정말로 작업 할 각 컴퓨터에 스크립트를 복사하는 것이 좋지 않을 것입니다. 로컬에서 실행되도록하는 유일한 방법입니까? –

+0

** 처음 ** 스크립트 (.ps1)를 작성하십시오. 그러면 "localhost"를 사용하여 원하는 것을 수행 할 수 있습니다. ** 두 번째 ** 관리자 컴퓨터에 스크립트를 보관하고 PSSession을 사용합니다. 스크립트를 Invoke-Command의 filepath 매개 변수에 넣으면이 매개 변수를 사용할 때 Windows PowerShell이 ​​지정된 스크립트 파일의 내용을 스크립트 블록으로 변환하고 스크립트 블록을 원격 컴퓨터로 전송 한 다음 원격 컴퓨터에서 실행합니다. – JPBlanc

+0

이 작업을 수행했지만, 내 목표는 Powershell 함수이므로 주위에 다른 스크립트를 처리하지 않아도됩니다. 이 기술은 미래에 알아두면 도움이됩니다. 도와 줘서 고마워! –

관련 문제