How to start a process on remote computer using powershell WMI? - powershell

We are upgrading our servers and need to stop our application before we perform update and then start it back again.
I was reading online about this and most of the links talk about remoting but some of the machines don't have PSRemoting enabled and therefore I need to stick to using wmi.
Would appreciate some pointers on this ?
To terminate the process I am using something like below:
$processes=Get-WmiObject -Class Win32_Process -ComputerName $Address -Filter "name='$ProcessName'"
foreach ($process in $processes)
{
$returnval = $process.terminate()
$processid = $process.handle
if($returnval.returnvalue -eq 0) {
write-host "The process $ProcessName `($processid`) terminated successfully"
}
else {
write-host "The process $ProcessName `($processid`) termination has some problems"
}
}

You don't say what OS and PS version(s) you are trying to deal with.
You are not saying what or if you are having issues with what you posted.
Even using only WMI, you still must have Windows WMI properly configured to do this as well as know Windows is not out of the boxed configured to let you what you are after without making all the proper WinRM, WMI and firewall manual configs.
It's far simpler just to enable PSRemoting via GPO.
Otherwise, you will need tp look toward maybe winrs.exe or MS SysInternals psexec.
winrs
Windows remote Management allows you to manage and execute programs remotely.
PsExec v2.2
Also back to my what OS and PowerShell version you are using. There is the
Invoke-Wmi​Method
Which can lead to stuff like this ---
Invoke-WmiMethod -ComputerName $TargetMachine -Namespace root\cimv2 -Class Win32_Process..."

Related

Use Powershell to install windows Patches

I already tried alot of tips on Stackoverflow, but nothing seems to work.
If I run this Code a Window Pops up.
The PowerShell Version is 2.0
My Code:
$PATH = "S:\User\Person\UPDATES\Update for Windows 7 for x64-based Systems (KB3134760)\AMD64-all-windows6.1-kb3134760-x64_d720851ef4b5a37c1c8bdd2e5bf4c77dcc625e8c.msu"
$SB = {Start-Process -FilePath 'c:\windows\system32\wusa.exe' -ArgumentList ('S:\User\Voss\UPDATES\Update for Windows 7 for x64-based Systems (KB3134760)\AMD64-all-windows6.1-kb3134760-x64_d720851ef4b5a37c1c8bdd2e5bf4c77dcc625e8c.msu','/quiet', '/promtrestart', "/log:S:\User\Voss\UPDATES\Update for Windows 7 for x64-based Systems (KB3134760)\Update.log") -Wait}
$computer = echo (Get-WmiObject -Class Win32_ComputerSystem -Property Name).Name
Invoke-Command -ScriptBlock $SB
First off, E.D. (hehe) is correct about your spelling error. A simple syntax error can break even the most otherwise elegant/complex scripts.
You're going to a lot of additional trouble to install patches from what I'm assuming is a (remote) mapped drive. If you're trying to do this on other machines, you'll want to use something like psexec or a scheduled task to kick off the install under the machines' credentials (NT Authority\System). If you're doing this on your machine and FOR your machine.
Picking your code apart:
$PATH = "S:\User\Person\UPDATES\Update for Windows 7 for x64-based Systems (KB3134760)\AMD64-all-windows6.1-kb3134760-x64_d720851ef4b5a37c1c8bdd2e5bf4c77dcc625e8c.msu"
$SB = {Start-Process -FilePath 'c:\windows\system32\wusa.exe' -ArgumentList ('S:\User\Voss\UPDATES\Update for Windows 7 for x64-based Systems (KB3134760)\AMD64-all-windows6.1-kb3134760-x64_d720851ef4b5a37c1c8bdd2e5bf4c77dcc625e8c.msu','/quiet', '/promtrestart', "/log:S:\User\Voss\UPDATES\Update for Windows 7 for x64-based Systems (KB3134760)\Update.log") -Wait}
$computer = echo (Get-WmiObject -Class Win32_ComputerSystem -Property Name).Name
Invoke-Command -ScriptBlock $SB
1) I don't really understand what you're doing with the $PATH variable as it isn't referenced anywhere else.
2) $SB doesn't 'REALLY' need to be delimited that way, but should work. Normally, I would just make it a single string and, when referencing other variables, utilize this syntax to get them to be evaluated first - $($PATH)
3) for $computer, you're kind of right. Lose the echo and you should be fine since you're just getting the name of the local machine ( $Env:ComputerName would work just as well and be more economical even if you're running the code on another machine, IMHO )
Addressing the use case where you might be running this code on another machine:
You seem to be assuming that you are logged on and your drive mapping is applicable. If you're accessing a network share, you'd want to make sure the remote machine has read permissions to the share so it could get to the file(s) in question and you'll also want to use the UNC path for simplicity's sake. This is a situation where psexec \ -S WUSA \UNC PATH\To\Update\File.msu would be best utilized.
Bottom line, if you'd communicate what your intent is a bit better, I might be better able to assist.

Change BIOS password through powershell

I want to build a script to change and/or set up BIOS password to HP workstations.
Script i run as follows:
C:\> $computers=Get-Content -Path c:\computers.txt
C:\> foreach ($computer in $computers) {
$passChange=Get-WmiObject -computername $computer -Namespace root/hp/instrumentedBIOS -Class HP_BIOSSettingInterface
$passChange.SetBIOSSetting('Setup Password','<utf-16/>MYNEWPASSWORD','<utf-16/>')
}
Now, the following happen:
If my BIOS has no password, the script works just fine!
If my BIOS has password already, script has Return: 6. I suppose there is
a different option for changing the BIOS password?If yes, any help
is appreciated!
If i run the script for my computer, it works.
If i run the script for another computer i get the following error:
The RPC server is unavailable. (Exception from HRESULT: 0x800706BA).
Is there a way to enable an option to enable the RPC for this feature and then disable it again?
Thank you in advance
According to HP's documentation HP Client Management Interface the WMI interface supports remote interfacing.
You need to ensure all remote computers you're attempting to connect to have the HP custom WMI Namespace.
You also need to ensure the account you're running under has administrative permissions on all of the remote computers.
You may also need to explicitly set the impersonation to 3 which is impersonate.
For more information: Connecting to WMI Remotely with PowerShell
Also ensure the firewall on the remote computers is either off or has exclusions for WMI

Determining when machine is in good state for Powershell Remoting?

Update - the original question claimed that I was able to successfully perform an Invoke-Command and then shortly after was unable to; I thought it was due to processes going on during login after a windows upgrade.
It turns out the PC was actually starting, running a quick batch/cmd file, and then restarting. This is what was leading to being able to do PS Remoting and then suddenly not. The restart was quick enough after first boot that I didn't realize it was happening. Sorry for the bad question.
For the curious, the machine was restarting because of a remnant of the Microsoft Deployment Toolkit in-place upgrade process. The way MDT completes its task-sequence post-upgrade is problematic for many reasons, and now I've got another to count.
Old details (no longer relevant, with incorrect assumption that machine was not restarting after first successful Invoke-Command):
I'm automating various things with VMs in Hyper-V using powershell and powershell remoting. I'll start up a VM and then want to run some commands on it via powershell.
I'm struggling with determining when I can safely start running the remote commands via things like Invoke-Command. I can't start immediately as I need to let the machine start up.
Right now I poll the VM with a one second sleep between calls until the following function returns $true:
function VMIsReady {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)][object]$VM
)
$heartbeat = $vm.Heartbeat
Write-Host "vm heartbeat is $heartbeat"
if (($heartbeat -eq 'OkApplicationsHealthy') -or ($heartbeat -eq 'OkApplicationsUnknown'))
{
try
{
Invoke-Command -VMName $vm.Name -Credential $(GetVMCredentials) {$env:computername} | out-null
}
catch [System.Management.Automation.RuntimeException]
{
Write-Host 'Caught expected automation runtime exception'
return $false
}
Write-Host 'remoting ready'
return $true
}
}
This usually works well; however, after a windows upgrade has happened, there are issues. I'll get Hyper-V remoting errors of various sorts even after VMIsReady returns $true.
These errors are happening while the VM is in the process of first user login after upgrade (Windows going through "Hi;We've got some updates for your PC;This might take several minutes-Don't turn off your PC). VMIsReady returns true right as this sequence starts - I imagine I probably should be waiting until the sequence is done, but I've no idea how to know when that is.
Is there a better way of determining when the machine is in a state where I can expect remoting to work without issue? Perhaps a way to tell when a user is fully logged on?
You can use Test-WSMan.
Of run a script on the invoke that will receive a response from the server.
[bool]$Response | Out-Null
try{
$Response = Invoke-Command -ComputerName Test-Computer -ScriptBlock {return $true}
}catch{
return $false
}
if ($Response -ne $true){
return $false
}else{
return $true
}

Get status of service on a remote server

I need to find the status of a service on a remote computer. Though I can use the following command:
Write-Host (Get-Service -ComputerName "remoteServerName" -Name "serviceName").Status
which would give me correct status of service. However I have PowerShell 1.0 installed on the server where i need to run this script. -ComputerName parameter doesn't work for PowerShell 1.0. Currently I'm not supposed to install higher version of PowerShell.
Any idea how to get the status of a service in PowerShell 1.0?
First and foremost (and I can't stress this point enough): If the operating system supports it you should upgrade to at least PowerShell v2.0. No exception. If the system doesn't support PowerShell 2 or newer it's already out of support and should have been replaced/upgraded months ago.
With that said, you can use either WMI (as suggested by #vonPryz):
Get-WmiObject -Computer 'remoteServerName' -Class Win32_Service -Filter "DisplayName='ServiceName'"
or sc.exe (as suggested by #Kayasax):
& sc.exe \\remoteServerName query 'ServiceName'
Of these two WMI is the more PoSh approach, as it doesn't require parsing text output.

Get Windows Last Reboot Timestamp?

I have a PC on remote connected by network, but it occasionally crashes or is restarted by remote users. After the restart, some services and applications have to be in running status. So I would like to find out the reboot as soon as possible. I think PS may be a good choice with some scripts so that I could make remote call to get the last reboot timestamp information.
Is there any way to get a remote Windows XP last reboot timestamp by using PowerShell 2.0(its remoting feature)?
You can do this via WMI:
$wmi = Get-WmiObject -Class Win32_OperatingSystem -Computer "RemoteMachine"
$wmi.ConvertToDateTime($wmi.LastBootUpTime)
For a remote computer:
$wmi = Get-WmiObject -Class Win32_OperatingSystem -Computer RemoteComputerName
$wmi.ConvertToDateTime($wmi.LastBootUpTime)
The uptime of the computer in seconds is available in the "System Up Time" performance counter. Though that's probably overkill.
Obviously, for services the easiest thing is to just set their start mode to "Automatic" but if you have other things that need to be running, the easiest way to do that is via the Windows task scheduler: you can set up a schedule that runs when the computer starts up.
FYI, if you are on the PowerShell Community Extensions 2.0 Beta, you can use Get-Uptime e.g.:
PS> Get-Uptime
Uptime LastBootUpTime
------ --------------
00:44:01.4401754 3/21/2010 12:07:17 AM