Unable to run Get-WmiObject on machine connected via Direct Connect VPN - powershell

$adminaccount = "DOMAIN\USERNAME"
$PASSWORD = ConvertTo-SecureString "PASSWORD" -AsPlainText -Force
$UNPASSWORD = New-Object System.Management.Automation.PsCredential $adminaccount, $PASSWORD
$Machines = Get-Content -Path "C:\Temp\production computers.txt"
$Result = Foreach ($Machine in $Machines){
New-Object -TypeName PSObject -Property #{
$hardware = Get-WmiObject Win32_ComputerSystem -ComputerName $Machine -Credential $UNPASSWORD
$os = Get-WmiObject Win32_OperatingSystem -ComputerName $Machine -Credential $UNPASSWORD
Computer = $Machine
Manufacturer = $hardware.Manufacturer
Model = $hardware.Model
OS = $os.Caption
}| Select-Object Computer,Manufacturer,Model,OS
}
$Result | Export-Csv -Path "C:\Temp\pcsinventory.csv" -NoTypeInformation
Trying to run the above to gather information from a list of machines, got two issues: Firstly I can get information back from machines connected to the network directly but the machines we have on Direct Connect VPNs get an "unable to contact RPC Server" error from the Get-WmiObjectcommand ; Secondly the results I do get seem to all come out as the same, when I know they're different, so somethings going wrong there.

Try using CIM cmdlets instead of legacy Get-WMIObject. In this case, Get-CimInstance can be a direct substitute.
I'm guessing there's a firewall issue given the different network paths. `Get-WMIObject is deprecated in Windows PowerShell and removed from PowerShell Core.
Straight forward example:
$adminaccount = "DOMAIN\USERNAME"
$PASSWORD = ConvertTo-SecureString "PASSWORD" -AsPlainText -Force
$UNPASSWORD = New-Object System.Management.Automation.PsCredential $adminaccount, $PASSWORD
$hwProps = 'manufacturer','Model'
$Machines = Get-Content -Path "C:\Temp\production computers.txt"
$Result = Foreach ($Machine in $Machines){
$hw = Get-CimInstance Win32_ComputerSystem -ComputerName $Machine -Property $hwProps -Credential $UNPASSWORD
$os = Get-CimInstance Win32_OperatingSystem -ComputerName $Machine -Credential $UNPASSWORD
[PSCustomObject]#{
Computer = $Machine
Manufacturer = $hw.Manufacturer
Model = $hw.Model
OS = $os.Caption
}
}
$Result | Export-Csv -Path "C:\Temp\pcsinventory.csv" -NoTypeInformation
I changed a little syntax, using the newer [PSCustomObject] casting. I also moved the I WMI queries out of the custom object declaration. They don't need to be there, and by doing so you don't need the Select-Object command. This is because now the only properties in the object are the ones you would have selected anyway.
Even if Cim doesn't solve the problem it's really the way to go. Take a look at Introduction to CIM CMdlets which will give you a good start...
Update to use Credentials with CIM:
$adminaccount = "DOMAIN\USERNAME"
$PASSWORD = ConvertTo-SecureString "PASSWORD" -AsPlainText -Force
$UNPASSWORD = New-Object System.Management.Automation.PsCredential $adminaccount, $PASSWORD
$hwProps = 'manufacturer','Model'
$Machines = Get-Content -Path "C:\Temp\production computers.txt"
$Result = Foreach ($Machine in $Machines){
$CimSession = New-CimSession -ComputerName $Machine -Credential $UNPASSWORD
$hw = Get-CimInstance Win32_ComputerSystem -CimSession $CimSession -Property $hwProps
$os = Get-CimInstance Win32_OperatingSystem -CimSession $CimSession
[PSCustomObject]#{
Computer = $Machine
Manufacturer = $hw.Manufacturer
Model = $hw.Model
OS = $os.Caption
}
}
$Result | Export-Csv -Path "C:\Temp\pcsinventory.csv" -NoTypeInformation
Update above uses New-CimSession with the -Credential parameter. Then it specs the-CimSession $CimSession instead of -ComputerName.... The credentials were overlooked in my initial example. Note: Using a CIM session is actually more efficient than repeating commands with -ComputerName.... The latter creates a CIM session under the hood, so each iteration creates and tears down a session, by reusing a session you do that fewer times...

Related

Powershell invoke-command $input

I have a trouble.. Can someone help me?
Here is my Code :
$A = '123'
$servers = 'computer1'
$Properties = [ordered]#{A = $A
servers = $servers
}
$MyObject = New-Object -TypeName PSObject -Property $Properties
$MyObjec
...
$result = Invoke-Command -ComputerName Machine -UseSSL -InDisconnectedSession -ScriptBlock {
$MyObject.A
$MyObject.servers
$env:computername
}`
–InputObject $MyObjec -port 5986 -ConfigurationName myEndpoint -SessionOption #{OutputBufferingMode="Drop"} -Credential $credential | Receive-PSSession
$result
Question:
Why the $result doesn't show anything about $MyObject?
It only show $MyObjec (not in the invoke-command) and $env:computername (in the invoke-command)
How can I fix it?
P.S this is really what I want to make,
I want to get into multiple machine which in 6 different AD in the same time, but they should use different username,
and I need $A in the remote machine to deal another thing.
$A = '123'
$servers = 'computer1'
$Properties = [ordered]#{A = $A
servers = $servers
}
$MyObject = New-Object -TypeName PSObject -Property $Properties
$MyObjec
...
#Add
$servers#{'Machine1','Machine2','Machine3'}
Foreach ($servers in $servers) {
Star-Job {
$username = $servers+'account'
$password = $password
$credential = ....($username,$password)
$result = Invoke-Command -ComputerName $servers -UseSSL -InDisconnectedSession -ScriptBlock {
$MyObject.A
$MyObject.servers
$env:computername
}`
–InputObject $MyObjec -port 5986 -ConfigurationName myEndpoint -SessionOption #{OutputBufferingMode="Drop"} -Credential $credential | Receive-PSSession
$result
}
}
I will try -Argument-List and param{}
Beacase I try Start-Job with -Argument-List and $Using, there have an error.
Thank u for your reply!
Because the part within -Scriptblock { ... } gets executed on the remote system and has therefore no access to the variables on the local system (different scope).
You can change that by passing the variables to the remote system using the -Argument-List parameter like this:
Invoke-Command -ComputerName Machine -ArgumentList $MyObject -ScriptBlock {
param($MyObject)
$MyObject.A
}
Or use $using: to get access to the locally defined variables like that:
Invoke-Command -ComputerName Machine -ScriptBlock {
$using:MyObject.A
}

Kill Process On List Of remote Workgroup Servers

I have a list of 5 Servers and for specific reasons they are not on the domain. The credentials among them are the same.
I am trying to remotely kill any instance of a process on the machines. For this website I have change the process to notepad.exe
I am having issues trying to determine how to successfully connect to these boxes.
I am running
$StartCheck = Get-WmiObject Win32_Process -Computer $Servers |
Where-Object { $ProcessNames -contains $_.Name }
$StartCheck | FT * -a;$StartCheck | FT * -a | out-file -FilePath $logfile -Append
and Here.
(Get-WmiObject Win32_Process -Computer $Servers |
Where-Object { $ProcessNames -contains $_.Name }).Terminate() | out-null
I am faced with the following error
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
At C:\Users\first.last\Desktop\Kill All Traffic Managers.PS1:67 char:13
+ $EndCheck = Get-WmiObject Win32_Process -Computer $Servers |
+
What is the easiest way to enter the credentials?
Add this to your script and change usernname and P#ssw0rd
$account = "username"
$PASSWORD = ConvertTo-SecureString P#ssw0rd -AsPlainText -Force
$UNPASSWORD = New-Object System.Management.Automation.PsCredential $account, $PASSWORD
Also change your
Get-WmiObject Win32_Process -Computer $Servers`
for
Get-WmiObject Win32_Process -Computer $Servers -Credential $UNPASSWORD

Enter PSSession with Variable for ComputerName

I am trying to enter a PSSession using -Computername $Server which was previously defined, but I can't seem to get this to work.
I have tried single, double, and no quotes around the variable at all. What am I doing wrong?
$Servers = Import-Csv "C:\Users\username\Desktop\DNS.csv"
$secpass = ConvertTo-SecureString 'mypassword' -AsPlainText -Force
$myCred = New-Object System.Management.Automation.PSCredential("username", $secpass)
foreach ($Object in $Servers) {
$Server = $Object.Name
Enter-PSSession -ComputerName "$Server" -Credential $myCred
sl HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters
Invoke-Command -ScriptBlock {Get-Item -Path HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters}
Exit-PSSession
}
We use enter pssession for creating an interactive session with the remote computer.
In your case, you do not need to have an interaction with the remote system. You just need to fetch the details from the remote systems which are present in the csv file.
So, Instead of this:
foreach($Object in $Servers) {
$Server = $Object.Name
Enter-PSSession -ComputerName "$Server" -Credential $myCred
sl HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters
Invoke-Command -ScriptBlock {Get-Item -Path HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters}
Exit-PSSession
}
Do This:
foreach($Object in $Servers)
{
$Server = $Object.Name
Invoke-Command -ComputerName $Server -ScriptBlock {Get-Item -Path HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters} -Credential $myCred
}
Note: I believe you have enabled PSRemoting and have edited trusted hosts.
The ComputerName param of Invoke-Command will accept an array of servers so you can do away with the foreach loop entirely and simplify your code to:
$Servers = Import-Csv "C:\Users\username\Desktop\DNS.csv" | Select-Object -ExpandProperty Name
$secpass = ConvertTo-SecureString 'mypassword' -AsPlainText -Force
$myCred = New-Object System.Management.Automation.PSCredential("username", $secpass)
Invoke-Command -ComputerName $Servers -ScriptBlock {Get-Item -Path HKLM:\SYSTEM\CurrentControlSet\Services\NetBT\Parameters} -Credential $myCred

get-process product version remote computer

If I locally do this I get all the information:
get-process | select-object name,fileversion,company
However, if I do it on a remote computer I only get the process name and all the other fields are blank. Does anyone know why or how to get the same information. I am using a domain admin credential so I should have access to that information.
get-process -computername xcomp123 | select-object name,fileversion,company
You can try this solution:
$Computername = 'Remotehost'
$Session = New-CimSession -ComputerName $Computername
$process = Get-CimInstance -ClassName Win32_Process -CimSession $Session
$col = New-Object System.Collections.ArrayList
foreach ($n in $process){
$exePath = $null
$ExeInfo = $null
$exePath = $n.ExecutablePath -Replace '\\','\\'
$ExeInfo = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = '$exePath'" -ErrorAction SilentlyContinue
[void]$col.add([PSCustomObject]#{
Name = $n.name
FileVersion = $ExeInfo.Version
Company = $ExeInfo.Manufacturer
PSComputername = $n.PSComputername
})
}
Remove-Cimsession $session
$col
Update:
I reduced the code to check for one process only. I assert the referencefile having the same name, as the process on the client computers. You might change that for your needs.
You can specify multiple computers at $computername, so you do not have to run the code over and over again.
#region Reference file
$RefFile = Get-item "\\x123\c$\program files\prog\winagent\file.exe"
#endregion
#region remote file
[string[]]$Computername = 'Remotehost1', 'Remotehost2'
$Processname = $RefFile.Name
foreach ($n in $Computername) {
$Session = New-CimSession -ComputerName $n
$process = Get-CimInstance -ClassName Win32_Process -CimSession $Session -Filter "name = '$Processname'"
$exePath = $process.ExecutablePath -Replace '\\', '\\'
$ExeInfo = Get-CimInstance -ClassName Cim_DataFile -Filter "Name = '$exePath'" -ErrorAction SilentlyContinue
[PSCustomObject]#{
Name = $Processname
FileVersion = $ExeInfo.Version
Company = $ExeInfo.Manufacturer
PSComputername = $n
}
Remove-Cimsession $session
}
#endregion

Getting Remote Process Information with Powershell (w/o remoting)

We have a bunch of PC that are not part of the domain (and cannot be added). They do not have PS installed and we'd prefer not to have to install it.
I want to use Powershell from a server to get the memory usage of 2 process every hour. Unfortunately get-process doesn't seem to support a -credential parameter. I did get win32_process (as shown below), but it returns a ton of info (no idea how I'd just get VMsize for two processes).
$Pass = ConvertTo-SecureString -string "SECRET" -AsPlainText –Force
$User = "USER"
$Cred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $User, $Pass
gwmi win32_process -computername PCName -Credential $Cred
Is there a way to do this without installing PS or putting PC's in domain?
You can use the Filter parameter to limit the processes you get info on e.g.:
Get-WmiObject -cn $c win32_process -Filter "Name='PowerShell.exe'" | ft Name, PrivatePageCount
Figured it out. This gets size of VM and Working set for the apps listed in $Processnames on the Computers listed in $HostNames. It checks if the computer is alive first
$Pass = ConvertTo-SecureString -string "SECRET" -AsPlainText –Force
$User = "User"
$Cred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $User, $Pass
$ProcessNames = #('App1.exe', 'App2.exe')
$HostList =#('Computer1','Computer2')
foreach ($CurrHost in $HostList)
{
# check if it's alive
if((Test-Connection -Cn $CurrHost -BufferSize 16 -Count 1 -ea 0 -quiet))
{
gwmi win32_process -computername $CurrHost -Credential $Cred |
Where-Object {$ProcessNames -contains $_.Name } |
Select-Object CSName, Name, WorkingSetSize, VirtualSize #|
#Format-Table -AutoSize
}
}