I am trying to get all the list of KB installed on multiple servers and get the last reboot time of the system. My requirement is to get the result in csv or text format with column name "Hostname" , "KB Name" , "installed by" , "installed on" and "Last reboot". I have to execute 2 script to get this done and then i have to format it and i dont want other columns which i am receiving from code 1 only limited column are required.. Can some please help me to get the same format which i reuired?
Output required in below format :
"Source" "Description" "HotFixID" "InstalledBy" "InstalledOn" "Last Reboot"
Please find below 2 code.
FYI : I am new to powershell.
Code 1: This will list all KB installed patch.
$computers = Get-Content -path "C:\Users\joy\Desktop\Machine_List.txt"
$patches = Get-Content -path "C:\Users\joy\Desktop\KB_List.txt"
foreach ($computer in $computers){
foreach ($patch in $patches){
Get-HotFix -id $patch -ComputerName $computer | -OutVariable results -ErrorAction SilentlyContinue
if ($results -ne $null) {
$results | Out-File C:\Users\joy\Desktop\report1.txt -Append -Force
}
else {
Add-content "$Patch is not Present in $computer" -path "C:\Users\joy\Desktop\report2.txt"
}
}
Code 2: This will get the last reboot of the system.
$machines = Get-Content C:\Users\joy\Desktop\Machine_List.txt
$report = #()
$object = #()
foreach($machine in $machines)
{
$machine
$object = gwmi win32_operatingsystem -ComputerName $machine | select csname, #{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}
$report += $object
}
$report | Export-csv C:\Users\joy\Desktop\Reboot.csv
$computers = Get-Content C:\Users\XXXXXXXX\Desktop\Machine_List.txt
$patchlist = Get-Content C:\Users\XXXXXXXX\Desktop\KB_List.txt
foreach($computer in $computers)
{
Get-HotFix -ComputerName $computer -Id $patchlist | select
InstalledOn,InstalledBy,Description,HotFixID,__SERVER | Format-Table | Out-File
C:\Users\XXXXXXXX\Desktop\report1.txt
#Get-CimInstance -ClassName Win32_Operatingsystem | select csname, lastbootuptime |
Format-Table |Out-File C:\Users\XXXXXXXX\Desktop\report1.txt
gwmi win32_operatingsystem -ComputerName $computer | select csname,
#{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}} | Out-
File C:\Users\XXXXXXXX\Desktop\report1.txt -Append
}
Try this, This will allow you to get information what you are looking for. But this script only get installed patches information from the remote machines, If you want add one more loop to print the patches which are installed on another text file.
I wrote a PowerShell script to change the login user for a service on my remote VMs. It works when I execute it. However, when I send it to my coworkers, the script appears that it ran without errors and they checked it still listed as "local account'.
$account = Read-Host "Please admin account Name"
$password = Read-Host -AsSecureString "Please enter your password"
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
$service = Read-Host "Enter service name"
$computers = Get-Content -Path ".\servers.txt"
foreach ($computer in $computers) {
$svc = gwmi Win32_Service -ComputerName $computer -Filter "name='$service'"
$svc.StopService()
$svc.Change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
$svc.StartService()
}
Write-Host $service "is now running as" $account
Read-Host
I would move this block
foreach ($computer in $computers) {
$svc = gwmi Win32_Service -ComputerName $computer -Filter "name='$service'"
$svc.StopService()
$svc.Change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
$svc.StartService()
}
into a invoke-command block. Cmd-lets using the -Computer parameter implement the remote actions in a proprietary way, while invoke-command uses WSMAN (-> more standardized way).
Try this:
foreach ($computer in $computers) {
# $computer can be either an IP-address or a FQDN e.g. computer.mydomain
invoke-command -computer $computer -credential (get-credential) -scripblock {
$svc = gwmi Win32_Service -ComputerName $computer -Filter "name='$service'"
$svc.StopService()
$svc.Change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
$svc.StartService()
}
}
With that proposal all actions are performed on the remote machine. In contrary to the first attempt. The first attempt "fetches" the remote objects to you local machine (objects are converted), than you locally perform some actions on the converted object (-> changed properties are send back to the remote).
If your computer is not in the same domain as the remote ones, you've to add your remote targets to your local trusted host list. This link describes how to update your trusted hosts list.
You should also check if Powershell remoting is active on your targets, also described in this link. If your target OS is WIN Server 2012 R2 Powershell remoting is active per default.
Is there a way in saving my credentials so it will not keep asking every loop? Like, isolating it outside the foreach loop. I tried removing -credentials and add it outside but it gives me an error of unauthorized access. I can't seem to figure it out. Sorry if this question seem to be stupid, I'm new to Powershell.
Import-Module ActiveDirectory
$ServerList = Get-Content "C:\servers.txt"
foreach($ServerName in $ServerList){
"$ServerName"
"=========="
Get-WmiObject -Class Win32_UserAccount -Computer $ServerName -Filter "LocalAccount='True'" -credential CORPORATE\usmenm03adm| Select Name
" "
}
You can define the credential outside the loop.
I edited your script like below
Import-Module ActiveDirectory
$ServerList = Get-Content "C:\servers.txt"
$cred=Get-Credential
foreach($ServerName in $ServerList){
"$ServerName"
"=========="
Get-WmiObject -Class Win32_UserAccount -Computer $ServerName -Filter "LocalAccount='True'" -credential $cred | Select Name
" "
}
Yes, read the credentials once with Get-Credential and store in a variable:
Import-Module ActiveDirectory
$ServerList = Get-Content "C:\servers.txt"
$MyCredential = Get-Credential -UserName "CORPORATE\usmenm03adm" -Message "Enter WMI credentials"
foreach ($ServerName in $ServerList) {
"$ServerName"
"=========="
Get-WmiObject -Class Win32_UserAccount -Computer $ServerName -Filter "LocalAccount='True'" -Credential $MyCredential | Select-Object Name
" "
}
Does anyone have a Powershell script to change the credentials used by a Windows service?
Bit easier - use WMI.
$service = gwmi win32_service -computer [computername] -filter "name='whatever'"
$service.change($null,$null,$null,$null,$null,$null,$null,"P#ssw0rd")
Change the service name appropriately in the filter; set the remote computer name appropriately.
I wrote a function for PowerShell that changes the username, password, and restarts a service on a remote computer (you can use localhost if you want to change the local server). I've used this for monthly service account password resets on hundreds of servers.
You can find a copy of the original at http://www.send4help.net/change-remote-windows-service-credentials-password-powershel-495
It also waits until the service is fully stopped to try to start it again, unlike one of the other answers.
Function Set-ServiceAcctCreds([string]$strCompName,[string]$strServiceName,[string]$newAcct,[string]$newPass){
$filter = 'Name=' + "'" + $strServiceName + "'" + ''
$service = Get-WMIObject -ComputerName $strCompName -namespace "root\cimv2" -class Win32_Service -Filter $filter
$service.Change($null,$null,$null,$null,$null,$null,$newAcct,$newPass)
$service.StopService()
while ($service.Started){
sleep 2
$service = Get-WMIObject -ComputerName $strCompName -namespace "root\cimv2" -class Win32_Service -Filter $filter
}
$service.StartService()
}
The PowerShell 6 version of Set-Service now has the -Credential parameter.
Here is an example:
$creds = Get-Credential
Set-Service -DisplayName "Remote Registry" -Credential $creds
At this point, it is only available via download via GitHub.
Enjoy!
I created a text file "changeserviceaccount.ps1" containing the following script:
$account="domain\user"
$password="passsword"
$service="name='servicename'"
$svc=gwmi win32_service -filter $service
$svc.StopService()
$svc.change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
$svc.StartService()
I used this as part of by post-build command line during the development of a windows service:
Visual Studio: Project properties\Build Events
Pre-build event command line:
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe" myservice.exe /u
Post-build event command line:
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe" myservice.exe
powershell -command - < c:\psscripts\changeserviceaccount.ps1
A slight variation on the other scripts here, is below. This one will set credentials for any/all services running under a given login account. It will only attempt to restart the service if it was already running, so that we don't accidentally start a service that was stopped for a reason. The script has to be run from and elevated shell (if the script starts telling you about ReturnValue = 2, you're probably running it un-elevated). Some usage examples are:
all services running as the currently logged in user, on the local host:
.\set-servicecredentials.ps1 -password p#ssw0rd
all services running as user: somedomain\someuser on host somehost.somedomain:
.\set-servicecredentials.ps1 somehost.somedomain somedomain\someuser p#ssw0rd
Set-ServiceCredentials.ps1:
param (
[alias('computer', 'c')]
[string] $computerName = $env:COMPUTERNAME,
[alias('username', 'u')]
[string] $serviceUsername = "$env:USERDOMAIN\$env:USERNAME",
[alias('password', 'p')]
[parameter(mandatory=$true)]
[string] $servicePassword
)
Invoke-Command -ComputerName $computerName -Script {
param(
[string] $computerName,
[string] $serviceUsername,
[string] $servicePassword
)
Get-WmiObject -ComputerName $computerName -Namespace root\cimv2 -Class Win32_Service | Where-Object { $_.StartName -eq $serviceUsername } | ForEach-Object {
Write-Host ("Setting credentials for service: {0} (username: {1}), on host: {2}." -f $_.Name, $serviceUsername, $computerName)
$change = $_.Change($null, $null, $null, $null, $null, $null, $serviceUsername, $servicePassword).ReturnValue
if ($change -eq 0) {
Write-Host ("Service Change() request accepted.")
if ($_.Started) {
$serviceName = $_.Name
Write-Host ("Restarting service: {0}, on host: {1}, to implement credential change." -f $serviceName, $computerName)
$stop = ($_.StopService()).ReturnValue
if ($stop -eq 0) {
Write-Host -NoNewline ("StopService() request accepted. Awaiting 'stopped' status.")
while ((Get-WmiObject -ComputerName $computerName -Namespace root\cimv2 -Class Win32_Service -Filter "Name='$serviceName'").Started) {
Start-Sleep -s 2
Write-Host -NoNewline "."
}
Write-Host "."
$start = $_.StartService().ReturnValue
if ($start -eq 0) {
Write-Host ("StartService() request accepted.")
} else {
Write-Host ("Failed to start service. ReturnValue was '{0}'. See: http://msdn.microsoft.com/en-us/library/aa393660(v=vs.85).aspx" -f $start) -ForegroundColor "red"
}
} else {
Write-Host ("Failed to stop service. ReturnValue was '{0}'. See: http://msdn.microsoft.com/en-us/library/aa393673(v=vs.85).aspx" -f $stop) -ForegroundColor "red"
}
}
} else {
Write-Host ("Failed to change service credentials. ReturnValue was '{0}'. See: http://msdn.microsoft.com/en-us/library/aa384901(v=vs.85).aspx" -f $change) -ForegroundColor "red"
}
}
} -Credential "$env:USERDOMAIN\$env:USERNAME" -ArgumentList $computerName, $serviceUsername, $servicePassword
Considering that whithin this class:
$class=[WMICLASS]'\\.\root\Microsoft\SqlServer\ComputerManagement:SqlService'
there's a method named setserviceaccount(), may be this script will do what you want:
# Copyright Buck Woody, 2007
# All scripts provided AS-IS. No functionality is guaranteed in any way.
# Change Service Account name and password using PowerShell and WMI
$class = Get-WmiObject -computername "SQLVM03-QF59YPW" -namespace
root\Microsoft\SqlServer\ComputerManagement -class SqlService
#This remmed out part shows the services - I'll just go after number 6 (SQL
#Server Agent in my case):
# foreach ($classname in $class) {write-host $classname.DisplayName}
# $class[6].DisplayName
stop-service -displayName $class[6].DisplayName
# Note: I recommend you make these parameters, so that you don't store
# passwords. At your own risk here!
$class[6].SetServiceAccount("account", "password")
start-service -displayName $class[6].DisplayName
Just making #alastairs's comment more visible: the 6th parameter must be $false instead of $null when you use domain accounts:
$service = Get-WMIObject -class Win32_Service -filter "name='serviceName'"
$service.change($null, $null, $null, $null, $null, $false, "DOMAIN\account", "mypassword")
Without that it was working for 4/5 of the services I tried to change, but some refused to be changed (error 21).
$svc = Get-WmiObject win32_service -filter "name='serviceName'"
the position of username and password can change so try this line to find the right place$svc.GetMethodParameters("change")
$svc.change($null,$null,$null,$null,$null,$null,$null,$null,$null,"admin-username","admin-password")
What I cannot find in the default PS stack, I find it implemented in Carbon:
http://get-carbon.org/help/Install-Service.html
http://get-carbon.org/help/Carbon_Service.html (Carbon 2.0 only)
The given answers do the job.
Although, there is another important detail; in order to change the credentials and run the service successfully, you first have to grant that user account permissions to 'Log on as a Service'.
To grant that privilege to a user, use the Powershell script provided here by just providing the username of the account and then run the other commands to update the credentials for a service as mentioned in the other answers, i.e.,
$svc=gwmi win32_service -filter 'Service Name'
$svc.change($null,$null,$null,$null,$null,$null,'.\username','password',$null,$null,$null)
Sc config example. First allowing modify access to a certain target folder, then using the locked down "local service" account. I would use set-service -credential, if I had PS 6 or above everywhere.
icacls c:\users\myuser\appdata\roaming\fahclient /grant "local service:(OI)(CI)(M)"
sc config "FAHClient" obj="NT AUTHORITY\LocalService"