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

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
}
}

Related

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

$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...

Restart machine using powershell script

I am running the below code but the restart is not working. My intention was to run restart command parallelly on all remote machines at once.
$YourFile = gc "machinelst.txt"
$username = "user1"
$password = "pass1"
$secpw = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object Management.Automation.PSCredential ($username, $secpw)
foreach ($computer in $YourFile)
{
Invoke-Command -ComputerName $computer -credential $cred -ErrorAction Stop -ScriptBlock { Restart-Computer -ComputerName $computer -Force } -AsJob
}
That looks like its the output from Get-Job - could you try Receive-Job $id (Receive-Job 80).
Should give you the actual exception.
This likely runs in parallel just like invoke-command does with an array of computernames:
restart-computer computer01,computer02,computer03,computer04,computer05
Or this. It takes a couple minutes for the winrm service to come back, but they all seem to reboot at the same time.
$c = get-credential
$list = 1..10 | % tostring computer00
restart-computer $list -wait -protocol wsman -cr $c
try this (you will can add -asjob if it's work) :
$username = "yourdomain\user1"
$password = ConvertTo-SecureString "pass1" -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
get-content "machinelst.txt" | %{
Restart-Computer -ComputerName $_ -Authentication default -Credential $cred
}
if you want use job, you can do it :
$listjob=#()
get-content "machinelst.txt" | %{
$listjob+=Restart-Computer -ComputerName $_ -Authentication default -Credential $cred -AsJob
}
$listjob | Wait-Job -Timeout 30
$listjob | %{
if ($_.State -eq 'Failed' )
{
Receive-Job -Job $_ -Keep
}
}

Invoke-Command does not kill process on remote machine

Before deployment, I'm trying to kill processes that lock files using PowerShell Invoke-Command
This is my code:
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PsCredential("Admin",$password)
$scriptBlock = {Get-Process | Where-Object { $_.MainWindowTitle -like 'MyApp*'} | Stop-Process}
Invoke-Command -computername Agent1 -Credential $credentials -scriptblock $scriptBlock
Unfortunately it does not do anything and no errors are thrown.
On the machine, this works fine:
Get-Process | Where-Object { $_.MainWindowTitle -like 'MyApp*'} | Stop-Process
As described above create a PS session object:
$ErrorActionPreference = "Stop"
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PsCredential("Admin",$password)
$scriptBlock = {
$process = Get-Process
$process | Where-Object { $_.MainWindowTitle -like 'MyApp*'} | Stop-Process}
$process
}
$session = New-PsSession -ComputerName "Agent1" -Credentials $credentials
$remoteProcess = Invoke-Command -Session $session -Credential $credentials -scriptblock $scriptBlock
$remoteProcess | format-table
Above code will also return you a list processes running on the remote host. Based on $remoteProcess you'll see if the process to kill was running or not. I also set the ErrorActionPreference to stop which forces above code to stop on the first error (in case of the session could not be created).
Hope that helps

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

Powershell command fails with "Invalid namespace" only when running as script, not in console

The following script fails on the last line with Get-WmiObject : Invalid namespace:
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ("domain\user", $password )
Write-Host "Entering PS Session..."
Enter-PSSession -Computer hyperVServer -Credential $cred
Start-Sleep -s 5
$server = "servername"
$query = "SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" + $server + "'"
$VM = get-wmiobject -query $query -namespace "root\virtualization" -computername "."
However, when I enter this one-by-one into the console, it runs without issue.
I've added the Start-Sleep due to some timing issues... the session takes a few seconds to actually open. Any ideas why that line would fail only when this is running as a script?
Enter-PSSession is intended only for interactive use. If you want to run commands on a remote system in a script (non-interactively), you'll need to use Invoke-Command instead. Please run Get-Help Invoke-Command -Full for more details.
Not sure why it works in one and not the other, but I assuming it's something to do with your remote session. Here's a list of commands that do not require a remote session, but rather just take a computer name. http://technet.microsoft.com/en-us/library/dd819505.aspx
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ("domain\user", $password )
$server = "servername"
$query = "SELECT * FROM Msvm_ComputerSystem WHERE ElementName=$server"
$VM = get-wmiobject -query $query -namespace "root\virtualization" -computername hyperVServer -credential $cred
Edited your query concat too.