Link to home
Start Free TrialLog in
Avatar of CuriousMAUser
CuriousMAUser

asked on

What needs to exist in a PowerShell script to assure Get-WMIObject works?

Hello Expert,

My goal is to export the desktop computer names from active directory, place the output into a text file and loop the names through the script to determine the administrator accounts on over 700 desktops.  When I tested the script I received an error:

"Get-WmiObject: The RPC is unavailable
     $AllLocalAccounts = Get-WmiObject -Class ...
   + CategoryInfo: Invalid Operation: (:) ... "

What is the script missing the 'AllLocalAccounts' variable? What is the best syntax?
Set-StrictMode -Version Latest
Set-ExecutionPolicy remotesigned -Force
import-module activedirectory

Get-ADComputer -Filter '*' -SearchBase "OU=Computers,DC=company,DC=com" -Properties Name | Select Name |  Out-File C:\Scripts\DesktopAccounts.txt


Param
(
	[Parameter(Position=0,Mandatory=$false)]
	[ValidateNotNullorEmpty()]
	[Alias('cn')][String[]]$ComputerName=(get-content c:\Scripts\DesktopAccounts.txt),
	[Parameter(Position=1,Mandatory=$false)]
	[Alias('un')][String[]]$AccountName,
	[Parameter(Position=2,Mandatory=$false)]
	[Alias('cred')][System.Management.Automation.PsCredential]$Credential
)
	
$Obj = @()

Foreach ($Computer in $ComputerName)
{
	If($Credential)
	{
		$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
		-Filter "LocalAccount='$True'" -ComputerName $Computer -Credential $Credential -ErrorAction Stop
	}
	else
	{
		$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
		-Filter "LocalAccount='$True'" -ComputerName $Computer -ErrorAction Stop
	}
	
	Foreach($LocalAccount in $AllLocalAccounts)
	{
		
        Set-ExecutionPolicy remotesigned -Force
        Import-Module activedirectory

        Set-StrictMode -Version Latest

        $Object = New-Object -TypeName PSObject
		
		$Object|Add-Member -MemberType NoteProperty -Name "User Name" -Value $LocalAccount.Name
		$Object|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $LocalAccount.FullName
		$Object|Add-Member -MemberType NoteProperty -Name "Logon Account Caption" -Value $LocalAccount.Caption
      	$Object|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $LocalAccount.Disabled
		$Object|Add-Member -MemberType NoteProperty -Name "Status" -Value $LocalAccount.Status
		$Object|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $LocalAccount.LockOut
		$Object|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $LocalAccount.PasswordChangeable
		$Object|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $LocalAccount.PasswordExpires
		$Object|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $LocalAccount.PasswordRequired
		$Object|Add-Member -MemberType NoteProperty -Name "Domain" -Value $LocalAccount.Domain
		$Object|Add-Member -MemberType NoteProperty -Name "Description" -Value $LocalAccount.Description
		
		$Obj+=$Object
	}
	
	If($AccountName)
	{
		Foreach($Account in $AccountName)
		{
		    $Obj| Where-Object{$psitem.Name -like "$Account"} 
		}
	}
	else
	{
		    $Obj | Export-csv c:\Scripts\DesktopAccounts.csv
	}
}

Open in new window

Avatar of Qlemo
Qlemo
Flag of Germany image

The issue is that you do not check for reachability of the remote machines. Get-WMIObject times out and throws that error at you.
Get-WmiObject: The RPC is unavailable
WMI uses the RPC service to get the information you are querying. You can receive the above message for the following reasons...
- computer is not pingable
- computer is powered off
- firewall on computer
- RPC service is stopped/disabled.

Will.
I've changed that part, inserting a ping and doing nothing if no success.
But note that in your line 68 you will write to a single CSV file, and do that in a loop - this will always replace the file, and not append info!
Set-StrictMode -Version Latest
Set-ExecutionPolicy remotesigned -Force
import-module activedirectory

Get-ADComputer -Filter '*' -SearchBase "OU=Computers,DC=company,DC=com" -Properties Name | Select Name |  Out-File C:\Scripts\DesktopAccounts.txt


Param
(
  [Parameter(Position=0,Mandatory=$false)]
  [ValidateNotNullorEmpty()]
  [Alias('cn')][String[]]$ComputerName=(get-content c:\Scripts\DesktopAccounts.txt),
  [Parameter(Position=1,Mandatory=$false)]
  [Alias('un')][String[]]$AccountName,
  [Parameter(Position=2,Mandatory=$false)]
  [Alias('cred')][System.Management.Automation.PsCredential]$Credential
)
  
$Obj = @()

Foreach ($Computer in $ComputerName)
{
  if (Test-Connection $Computer -Count 1 -TimeToLive 5 -Quiet)
  {
    If($Credential)
    {
      $AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
      -Filter "LocalAccount='$True'" -ComputerName $Computer -Credential $Credential -ErrorAction Stop
    }
    else
    {
      $AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
      -Filter "LocalAccount='$True'" -ComputerName $Computer -ErrorAction Stop
    }
    
    Foreach($LocalAccount in $AllLocalAccounts)
    {
      
          Set-ExecutionPolicy remotesigned -Force
          Import-Module activedirectory

          Set-StrictMode -Version Latest

          $Object = New-Object -TypeName PSObject
      
      $Object|Add-Member -MemberType NoteProperty -Name "User Name" -Value $LocalAccount.Name
      $Object|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $LocalAccount.FullName
      $Object|Add-Member -MemberType NoteProperty -Name "Logon Account Caption" -Value $LocalAccount.Caption
          $Object|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $LocalAccount.Disabled
      $Object|Add-Member -MemberType NoteProperty -Name "Status" -Value $LocalAccount.Status
      $Object|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $LocalAccount.LockOut
      $Object|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $LocalAccount.PasswordChangeable
      $Object|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $LocalAccount.PasswordExpires
      $Object|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $LocalAccount.PasswordRequired
      $Object|Add-Member -MemberType NoteProperty -Name "Domain" -Value $LocalAccount.Domain
      $Object|Add-Member -MemberType NoteProperty -Name "Description" -Value $LocalAccount.Description
      
      $Obj+=$Object
    }
    
    If($AccountName)
    {
      Foreach($Account in $AccountName)
      {
          $Obj| Where-Object{$psitem.Name -like "$Account"} 
      }
    }
    else
    {
          $Obj | Export-csv c:\Scripts\DesktopAccounts.csv
    }
  }
}

Open in new window

Personally all I would do is use -ErrorAction SilentContinue or Ignore.

Will.
Avatar of CuriousMAUser
CuriousMAUser

ASKER

Hi,

For some reason the script still doesn't work. Are the parameters right?
Error message - Test-Connection: Cannot validate argument for parameter 'ComputerName' , The argument is null or empty ...

Within the DesktopAccounts.txt file there is only one pingable computer name.

Thank you.
*********************************
Set-StrictMode -Version Latest
Set-ExecutionPolicy remotesigned -Force
import-module activedirectory

Get-ADComputer -Filter '*' -SearchBase "OU=Computers,DC=company,DC=com" -Properties Name | Select Name |  Out-File C:\Scripts\DesktopAccounts.txt

Param
(
  [Parameter(Position=0,Mandatory=$false)]
  [ValidateNotNullorEmpty()]
  [Alias('cn')][String[]]$ComputerName=(Get-Content -path c:\Scripts\DesktopAccounts.txt),
  [Parameter(Position=1,Mandatory=$false)]
  [Alias('un')][String[]]$AccountName,
  [Parameter(Position=2,Mandatory=$false)]
  [Alias('cred')][System.Management.Automation.PsCredential]$Credential
)      

$Obj = @()

Foreach($Computer in $ComputerName)
{
  if (Test-Connection $Computer -Count 1 -TimeToLive 5 -Quiet)
   {
      If($Credential)
      {
            $AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
            -Filter "LocalAccount='$True'" -ComputerName $Computer -Credential $Credential -ErrorAction Stop
      }
      else
      {
            $AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
            -Filter "LocalAccount='$True'" -ComputerName $Computer -ErrorAction Stop
      }
      
      Foreach($LocalAccount in $AllLocalAccounts)
      {
            
        Set-ExecutionPolicy remotesigned -Force
        Import-Module activedirectory

        Set-StrictMode -Version Latest

        $Object = New-Object -TypeName PSObject
            
            $Object|Add-Member -MemberType NoteProperty -Name "User Name" -Value $LocalAccount.Name
            $Object|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $LocalAccount.FullName
            $Object|Add-Member -MemberType NoteProperty -Name "Logon Account Caption" -Value $LocalAccount.Caption
            $Object|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $LocalAccount.Disabled
            $Object|Add-Member -MemberType NoteProperty -Name "Status" -Value $LocalAccount.Status
            $Object|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $LocalAccount.LockOut
            $Object|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $LocalAccount.PasswordChangeable
            $Object|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $LocalAccount.PasswordExpires
            $Object|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $LocalAccount.PasswordRequired
            $Object|Add-Member -MemberType NoteProperty -Name "Domain" -Value $LocalAccount.Domain
            $Object|Add-Member -MemberType NoteProperty -Name "Description" -Value $LocalAccount.Description
            
            $Obj+=$Object
      }
      
      If($AccountName)
      {
            Foreach($Account in $AccountName)
            {
                $Obj| Where-Object{$psitem.Name -like "$Account"}
            }
      }
      else
      {
                $Obj | Export-csv c:\Scripts\SleepMedDesktopGroupMembers.csv -Append -NoTypeInformation
      }
  }
}
You have empty lines in your file for sure, and that is because you create it the wrong way. You should use this:
Get-ADComputer -Filter '*' -SearchBase "OU=Computers,DC=company,DC=com" -Properties Name | Select -Expand Name |  Out-File C:\Scripts\DesktopAccounts.txt

Open in new window

otherwise the property name ("Name"), additional spacing and some equal signs will appear in the file.

And the code is really bad style, mixing writing into files and into the pipeline, having superfluous code, running a command before PARAM, using cumbersome commands, using fixed file names, etc. pp.
Do you really need the different ways the "command" can be called, according to PARAM definition? If not, the script could be simplified much.
Hi QLemo,

Would you please create the simplified version so I may compare?

Thank you kindly,
CuriousMAUser
ASKER CERTIFIED SOLUTION
Avatar of Qlemo
Qlemo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you! I'm still troubleshooting.
Hi QLemo,

With the script below I'm trying to loop through over 700 computer names and extract their user account details to determine how many 'Administrators' have local access. This script loops once. Does the script need to use ForEach logic?

Set-StrictMode -Version Latest
Set-ExecutionPolicy remotesigned -Force
import-module activedirectory

Get-ADComputer -Filter '*' -SearchBase "OU=Computers - SleepMed,DC=sleepmed,DC=md" -Properties Name | % {
  $PC = $_.Name}

  if (Test-Connection $PC -Count 1 -TimeToLive 5 -Quiet)
  {
    Get-WmiObject Win32_UserAccount -ComputerName $PC -Filter "LocalAccount='True'" | % {
      New-Object PsObject -Property @{
                 "User Name"             = $_.Name
                 "Full Name"             = $_.FullName
                 "Logon Account Caption" = $_.Caption
                 "Disabled"              = $_.Disabled
                 "Status"                = $_.Status
                 "LockOut"               = $_.LockOut
                 "Password Changeable"   = $_.PasswordChangeable
                 "Password Expires"      = $_.PasswordExpires
                 "Password Required"     = $_.PasswordRequired
                 "Domain"                = $_.Domain
                 "Description"           = $_.Description
      } | Export-csv -path c:\Scripts\DesktopGroupMembers.csv -NoTypeInformation
    }
}
No, the loop is already there. Everything found by the Get-ADComputer will get process.
Excellent. Thank you so much.