2017-09-19 11 views
1

私はpowershellスクリプトに取り組んできました。スクリプトには2つの部分があります。文字列の出力を別々の文字列に分割する

  1. 最初の部分は、ドメイン内のすべてのサーバーを取得する関数です。私たちは4つの異なるドメインを持っているので、それぞれを個別にチェックして結果を出力します。

  2. 第2部分は、特定のリモートマシン上でソフトウェアを出力する機能です。私の場合、上記の関数の出力はこの関数にシードされ、サーバーに特定のソフトウェアがインストールされているかどうかが確認されます。

ソフトウェアを検索する機能が正常に動作します。すべてのサーバーの出力を取得する機能は、私が問題を抱えていることです。 (サーバーA:例えば

問題は、ときに私は、出力サーバのリスト(出力が正確である)、それは単一の大規模な複数行の文字列にすべてを出力していること、である...

は私が5つのサーバーを持って言うことができます、ServerB、ServerC、ServerD、ServerE)。

私は、コードを実行すると、私はそうのように、各ドメインのすべてのサーバの出力が得られます:

TestA.com 

ServerA 
ServerB 
ServerC 
ServerD 
ServerE 

TestB.com 

ServerA 
ServerB 
ServerC 
ServerD 
ServerE 

TestC.com 

ServerA 
ServerB 
ServerC 
ServerD 
ServerE 

TestD.com 

ServerA 
ServerB 
ServerC 
ServerD 
ServerE 

しかし、各領域の出力は、すべて1つの文字列であるので、私は機能にそれをシードすることはできませんサーバーごとにではなく、「ServerA、ServerB、ServerC、ServerD、ServerE」でソフトウェアを検索しようとしているため、ソフトウェアをチェックする必要があります。

これは意味があると思います。ここで私のコードは、サーバーのリストを取得します。

#Clear Screen 
CLS 

function Get-Servers 
{ 
    #Variables 
    [array]$MyDomains="TestA.com","TestB.com","TestC.com","TestD.com" 
    [array]$MySearchBase="dc=TestA,dc=com","dc=TestB,dc=com","dc=TestC,dc=com","dc=TestD,dc=com" 


    for($i=0; $i -lt $MyDomains.Count; $i++) 
    { 
     Write-Output $($MyDomains[$i]) 

     $MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders | out-string 

     foreach ($MyServer in $MyServers) 
     { 
      $MyServer 
      pause 
     } 
    } 
} 

#Get list of servers 
Get-Servers 

「$ MyServer」変数に格納される各サーバーの出力を個別に取得するにはどうすればよいですか。

編集:私はそうのように私のサーバーの機能を変更する場合

for($i=0; $i -lt $MyDomains.Count; $i++) 
{ 
    Write-Output $($MyDomains[$i]) 

    $MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders 

    foreach ($MyServer in $MyServers) 
    { 
     Get-RemoteRegistryProgram -ComputerName $MyServer 
    } 

} 

私は次のエラーを取得する。ここ が

function Get-RemoteRegistryProgram 
{ 
    <# 
    .Synopsis 
     Uses remote registry to read installed programs 
    .DESCRIPTION 
     Use dot net and the registry key class to query installed programs from a 
     remote machine 
    .EXAMPLE 
     Get-RemoteRegistryProgram -ComputerName Server1 
    #> 
    [CmdletBinding()] 
    Param 
    (
     [Parameter(
      ValueFromPipeline=$true, 
      ValueFromPipelineByPropertyName=$true, 
      Position=0)] 
     [string[]] 
     $ComputerName = $env:COMPUTERNAME 
    ) 
    begin 
    { 
     $hives = @(
      [Microsoft.Win32.RegistryHive]::LocalMachine, 
      [Microsoft.Win32.RegistryHive]::CurrentUser 
     ) 

     $nodes = @(
      "Software\Microsoft\Windows\CurrentVersion\Uninstall", 
      "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" 
     ) 
    } 
    process 
    { 
     $ComputerName 

     forEach ($computer in $ComputerName) 
     { 
      forEach($hive in $hives) 
      { 
       try 
       { 
        $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive,$computer) 
       } 
       catch 
       { 
        throw $PsItem 
       } 
       forEach($node in $nodes) 
       { 
        try 
        { 
         $keys = $registry.OpenSubKey($node).GetSubKeyNames() 

         forEach($key in $keys) 
         { 
          $displayname = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayName') 

          if($displayname) 
          { 
           $installedProgram = @{ 
            # ComputerName = $computer 
            DisplayName = $displayname 
            # Version = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayVersion') 
           } 
           New-Object -TypeName PSObject -Property $installedProgram 
          } 
         } 
        } 
        catch 
        { 
         $orginalError = $PsItem 
         Switch($orginalError.FullyQualifiedErrorId) 
         { 
          'InvokeMethodOnNull' 
          { 
           #key maynot exists 
          } 
          default 
          { 
           throw $orginalError 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
    end 
    { 

    } 
} 

EDIT 2をリモートソフトウェアを見つけるために私の関数であります:

Microsoft.PowerShell.Commands.Internal.Format.FormatStartData 
Exception calling "OpenRemoteBaseKey" with "2" argument(s): "The network path was not found. 
" 
At line:47 char:21 
+      $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey ... 
+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
    + FullyQualifiedErrorId : IOException 

ご協力いただきありがとうございます!

+0

車輪を再発明する必要はありません。リモートコンピュータにインストールされたソフトウェアを入手する場合は、私が書いたスクリプトを使用します。[PowerShellで32ビットおよび64ビットアプリケーションを監査する](http://windowsitpro.com/scripting/auditing-32-bit) -and-64-bit-applications-powershell)を使用します。 –

+0

ありがとうございます。私は無知にすることを意味するわけではありませんが、私はこれを実行し、いくつかの問題を抱えようとしています。私は使用しようとするserver.txtファイルがあります。 Get-Content u:\ scripts \ servers.txt | get-installedapp2 -Publisher "* SysAid *" コードにエラーが発生しました。 – Koobah84

+0

1)あなたは何のエラーを伝えていませんでした(誰もあなたの画面を見ることはできません)。 2) '2 'は' Get-InstalledApp'の最後にどこから来たのですか?スクリプト名の末尾に '2 'はありません。 –

答えて

0

私はいくつかのものを書き直して問題を解決しました。文字列の問題を回避するために、結果をテキストファイルにエクスポートし、get-contentを使用してテキストファイルから1行ずつ読み込み、必要なソフトウェアがどのサーバーにあるかを知らせるために各サーバーをシードしました。最終結果がここにあります。

#Clear Screen 
CLS 

function Get-RemoteRegistryProgram 
{ 
    <# 
    .Synopsis 
     Uses remote registry to read installed programs 
    .DESCRIPTION 
     Use dot net and the registry key class to query installed programs from a 
     remote machine 
    .EXAMPLE 
     Get-RemoteRegistryProgram -ComputerName Server1 
    #> 
    [CmdletBinding()] 
    Param 
    (
     [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)][string]$ComputerName = $env:COMPUTERNAME, 
     [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=1)][string]$SoftwareName 
    ) 
    begin 
    { 
     $hives = @(
      [Microsoft.Win32.RegistryHive]::LocalMachine, 
      [Microsoft.Win32.RegistryHive]::CurrentUser 
     ) 

     $nodes = @(
      "Software\Microsoft\Windows\CurrentVersion\Uninstall", 
      "Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" 
     ) 
    } 
    process 
    { 
     $ComputerName 
     $skip = $false 

     forEach ($computer in $ComputerName) 
     { 
      forEach($hive in $hives) 
      { 
       try 
       { 
        $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive,$computer) 
       } 
       catch 
       { 
        $skip = $true     
       } 

       if($skip -eq $false) 
       { 
        forEach($node in $nodes) 
        { 
         try 
         { 
          $keys = $registry.OpenSubKey($node).GetSubKeyNames() 

          forEach($key in $keys) 
          { 
           $displayname = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayName') 

           #Modified by James 
           if(($displayname) -like "*$SoftwareName*") 
           { 
            $displayname + "`t" + $computer >> c:\scripts\sysaidServers.txt 
           } 

           <# Modified by James 
           if($displayname) 
           { 
            $installedProgram = @{ 
             # ComputerName = $computer 
             DisplayName = $displayname 
             # Version = $registry.OpenSubKey($node).OpenSubKey($key).GetValue('DisplayVersion') 
            } 
            New-Object -TypeName PSObject -Property $installedProgram 
           } 
           #> 
          } 
         } 
         catch 
         { 

         <# 
          $orginalError = $PsItem 
          Switch($orginalError.FullyQualifiedErrorId) 
          { 
           'InvokeMethodOnNull' 
           { 
            #key maynot exists 
           } 
           default 
           { 
            throw $orginalError 
           } 
          } 
         #> 
         } 
        } 
       } 
      } 
     } 
    } 
    end 
    { 

    } 
} 

#Output the servers to a txt file 
function Get-Servers 
{ 
    param ([Parameter(Mandatory=$true)][string]$SaveFile) 

    #Variables 
    [array]$MyDomains="DomainA.com","DomainB.com","DomainC.com","DomainD.com" 
    [array]$MySearchBase="dc=DomainA,dc=com","dc=DomainB,dc=com","dc=DomainC,dc=com","dc=DomainD,dc=com" 


    for($i=0; $i -lt $MyDomains.Count; $i++) 
    { 
     #I only want servers running Windows Server OS 
     $MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders | out-string 
     #Remove all whitespace and export to txt file 
     $MyServers.Trim() -replace (' ', '') >> $SaveFile 
    } 
} 

function CheckServerSoftware 
{ 
    param ([Parameter(Mandatory=$true)][string]$SaveFile) 

    Get-Content $SaveFile | ForEach-Object { 
     if($_ -match $regex) 
     { 
      $computer = $_.ToString() 
      Get-RemoteRegistryProgram -ComputerName $computer.Trim() $SoftwareName 
      Write-Output "" 
     } 
    } 
} 

#Path to where our exported server list is 
$SaveFile = "c:\scripts\servers.txt" 
$SoftwareName = "SysAid" 

#If the file already exists, remove it 
Remove-Item $SaveFile 

#Create the text file with servers 
Get-Servers $SaveFile 

#Import our server list and check software on each server 
CheckServerSoftware $SaveFile 
0

あなたのコードは、その最後の部分はout-stringある文字列

$MyServers = Get-ADComputer -Filter 'OperatingSystem -like "Windows*Server*"' -Properties Name -SearchBase $($MySearchBase[$i]) -Server $($MyDomains[$i]) | Format-Table Name -HideTableHeaders | out-string

にサーバー名を変換しています。フォーマットテーブルにパイプして文字列としてプッシュする代わりに、オブジェクトを保持し、各オブジェクトのプロパティを使用して各サーバーの名前を取得します。

+0

ありがとうございます。しかし、私がout-stringを削除した場合、それはうまく機能しますが、私はソフトウェア機能にその値を与えることができません。エラーメッセージが表示される "Microsoft.PowerShell.Commands.Internal.Format.FormatStartData " 2 "引数を指定して" OpenRemoteBaseKey "を呼び出す例外:"ネットワークパスが見つかりませんでした。 "ラインで :47文字:21 + $レジストリ= [Microsoft.Win32.RegistryKey] :: OpenRemoteBaseKey ... + CategoryInfo:NotSpecified:(:) []、MethodInvocationException + FullyQualifiedErrorId:IOExceptionが " – Koobah84

+0

私は元の投稿を更新してソフトウェア機能を組み込んだ。 上記のように調整して、このような関数を呼び出すと、Get-RemoteRegistryProgram -ComputerName $ MyServer – Koobah84

関連する問題