Unable to fetch IIS status from Remote server using Powershell - powershell

I am trying to fetch IIS status from remote server using powershell.
I have used command Get-Service but i don't recieve any output from this command.
Below is my code block.
$pass='pass'|ConvertTo-SecureString -AsPlainText -Force;
$Credentials = New-Object
System.Management.Automation.PsCredential("user",$pass);
$Service=invoke-command -computername "server" -credential $Credentials -
scriptblock {Get-Service|Where-Object Name -eq 'IISADMIN'}
if($Service.Status -eq 'Running')
{
write-host "IIS Running"
}
else
{
throw "IIS not running or Not installed"
}

I Checked your code and did not see any problem with it, Did you checked the service exists locally using Get-Service or Service Manager?
Anyway you don't have to use Invoke-Command for this, you can use the built in -ComputerName parameter of the Get-Service cmdlet,
And if you need to provide credentials, you can use WMI:
$Credential = New-Object System.Management.Automation.PsCredential($username, $encrypted)
$Service = Get-WmiObject -Class win32_service -ComputerName Server -Filter 'Name = "W3SVC"' -Credential $Credentials

Try using a WMI call instead, I have found it far more reliable when working with remote servers.
$Service = Get-WmiObject -Computername $computer -Credential $credentials Win32_service -ErrorAction Continue | Where {$_.Name -eq 'IISADMIN'}

Related

Disable Print Spooler Script [duplicate]

I came across this one liner that appears to work:
stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
Can anyone explain why, because I thought stop-service didn't work unless you either used remoting or it occurred on the local host.
The output of Get-Service is a System.ServiceProcess.ServiceController .NET class that can operate on remote computers. How it accomplishes that, I don't know - probably DCOM or WMI. Once you've gotten one of these from Get-Service, it can be passed into Stop-Service which most likely just calls the Stop() method on this object. That stops the service on the remote machine. In fact, you could probably do this as well:
(get-service -ComputerName remotePC -Name Spooler).Stop()
Thanks to everyone's contributions to this question, I've come up with the following script. Change the values for $SvcName and $SvrName to suit your needs. This script will start the remote service if it is stopped, or stop it if it is started. And it uses the cool .WaitForStatus method to wait while the service responds.
#Change this values to suit your needs:
$SvcName = 'Spooler'
$SvrName = 'remotePC'
#Initialize variables:
[string]$WaitForIt = ""
[string]$Verb = ""
[string]$Result = "FAILED"
$svc = (get-service -computername $SvrName -name $SvcName)
Write-host "$SvcName on $SvrName is $($svc.status)"
Switch ($svc.status) {
'Stopped' {
Write-host "Starting $SvcName..."
$Verb = "start"
$WaitForIt = 'Running'
$svc.Start()}
'Running' {
Write-host "Stopping $SvcName..."
$Verb = "stop"
$WaitForIt = 'Stopped'
$svc.Stop()}
Default {
Write-host "$SvcName is $($svc.status). Taking no action."}
}
if ($WaitForIt -ne "") {
Try { # For some reason, we cannot use -ErrorAction after the next statement:
$svc.WaitForStatus($WaitForIt,'00:02:00')
} Catch {
Write-host "After waiting for 2 minutes, $SvcName failed to $Verb."
}
$svc = (get-service -computername $SvrName -name $SvcName)
if ($svc.status -eq $WaitForIt) {$Result = 'SUCCESS'}
Write-host "$Result`: $SvcName on $SvrName is $($svc.status)"
}
Of course, the account you run this under will need the proper privileges to access the remote computer and start and stop services. And when executing this against older remote machines, you might first have to install WinRM 3.0 on the older machine.
Based on the built-in Powershell examples, this is what Microsoft suggests. Tested and verified:
To stop:
(Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StopService()
To start:
(Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StartService()
This worked for me, but I used it as start. powershell outputs,
waiting for service to finshing starting a few times then finishes and then a get-service on the remote server shows the service started.
**start**-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
Another option; use invoke-command:
cls
$cred = Get-Credential
$server = 'MyRemoteComputer'
$service = 'My Service Name'
invoke-command -Credential $cred -ComputerName $server -ScriptBlock {
param(
[Parameter(Mandatory=$True,Position=0)]
[string]$service
)
stop-service $service
} -ArgumentList $service
NB: to use this option you'll need PowerShell to be installed on the remote machine and for the firewall to allow requests through, and for the Windows Remote Management service to be running on the target machine. You can configure the firewall by running the following script directly on the target machine (one off task): Enable-PSRemoting -force.
You can also do (Get-Service -Name "what ever" - ComputerName RemoteHost).Status = "Stopped"
You could just run a foreach and have logging enabled.
The console will show if something goes wrong and you can look in the log.
That way, you can then handle the errors individually.
I think it works better this way than running a Test-Netconnection for the verification part because firewall rules can create the value false.
For this example you ned a csv file with column ServerName, Populate the column with servername.contoso.com
$ServerList = "$PSScriptRoot\Serverlist.csv"
$Transcriptlog = "$PSScriptRoot\Transcipt.txt"
Start-Transcript -Path $Transcriptlog -Force
Get-Date -Format "yyyy/MM/dd HH:mm"
Try
{ # Start Try
$ImportServerList = Import-Csv $ServerList -Encoding UTF8 | ForEach-Object { # Start Foreach
New-Object PsObject -Prop #{ # Start New-Object
ServerName = $_.ServerName } # End NewObject
Invoke-Command -ComputerName $_.ServerName -ErrorAction Continue -ScriptBlock { # Start ScriptBlock
# Disable Service PrintSpooler
Get-Service -Name Spooler | Stop-Service -Force
} # End ScriptBlock
} # End Foreach
} # End Try
Catch
{ # Start Catch
Write-Warning -Message "## ERROR## "
Write-Warning -Message "## Script could not start ## "
Write-Warning $Error[0]
} # End Catch
Stop-Transcript
stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
This fails because of your variables
-ComputerName remotePC needs to be a variable $remotePC or a string "remotePC"
-Name Spooler(same thing for spooler)
As far as I know, and I cant verify it now, you cannot stop remote services with the Stop-Service cmdlet or with .Net, it is not supported.
Yes it works, but it stopes the service on your local machine, not on the remote computer.
Now, if the above is correct, without remoting or wmi enabled, you could set a scheduled job on the remote system, using AT, that runs Stop-Service locally.

Formating List Problems in Powershell

I want to execute a few lines of code on every Server (160+).
For this I decided to get my Serverlist via Powercli and pass this list to Enter-PSSession.
...
Connect-VIServer -Server $VIServer -Credential $creds
$servers = Get-VM |select Name |where Name -Like "SV*"
...
foreach($server in $servers)
{
try{
Enter-PSSession -ComputerName $server -Credential $cred -ErrorAction Stop
Get-NetIPAddress |where AddressFamily -EQ 2 |where InterfaceAlias -Like "Ethernet" |select IPAddress
Exit-PSSession
}catch{
Write-Host "Error on $server"
}
}
the problem seems to be, that it takes an array as the ouput error is following
Error on #{Name=<$server>}
But I dont know how to handle this correctly
Use New-Pssession or Invoke-command for remoting. Enter-Pssession is interactive and the way you are doing it, the get-netipaddress is running on your local machine and not on your remote machine.
Use $servers.Name instead of $servers in your foreach loop.
foreach($server in $servers.Name) #This .name should fix your problem
{
try{
New-PSSession -ComputerName $server -Credential $cred -ErrorAction Stop -Name MySession
Invoke-Command -Session $MySession -ScriptBlock {Get-NetIPAddress |where AddressFamily -EQ 2 |where InterfaceAlias -Like "Ethernet" |select IPAddress}
Remove-PSSession
}catch{
Write-Host "Error on $server"
}
}

read a remote registry key with alternate credentials in powershell

I am using the following function to read remote registry keys in powershell but I now need to pass alternate credentials. How do I do that?
I already have my credentials stored in $cred using the get-credential command.
Param($computer)
$HKEY_Local_Machine = 2147483650
$reg = [WMIClass]"\\$computer\ROOT\DEFAULT:StdRegProv"
$Key = "SOFTWARE\Wow6432Node\Symantec\Symantec Endpoint Protection\CurrentVersion\SharedDefs"
$ValueName = "DEFWATCH_10"
$results = $reg.GetStringValue($HKEY_LOCAL_MACHINE, $Key, $ValueName)
write $results.sValue
If you can use psremoting i would suggest using Invoke-Command in conjunction with Get-Item as an alternative.
$value = Invoke-Command -Scriptblock {Get-Item "HKLM:\SOFTWARE\Wow6432Node\Symantec\Symantec Endpoint Protection\CurrentVersion\SharedDefs\DEFWATCH_10"} -Credentials $cred -Computername $computer
If you have to use WMI you could try something like this:
$wmi = Get-Wmiobject -list "StdRegProv" -namespace root\default -Computername $computer -Credential $cred
$value = $wmi.GetStringValue($HKEY_Local_Machine,$key,$valuename).svalue
This worked for me, I wanted to look for pending reboot needed on a system:
$HKLM = [UInt32] "0x80000002"
$WMI_Reg = Get-Wmiobject -list "StdRegProv" -namespace root\default -Computername $computer -Credential $Cred
$RegSubKeysCBS = $WMI_Reg.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\")
$CBSRebootPend = $RegSubKeysCBS.sNames -contains "RebootPending"

PowerShell Script to Stop a service on multiple remote machines

I am trying to disable a service running on 250+ PCs. I would like to have a PowerShell script I can execute on a random PC in the network and let it disable a service on every PC I specify in an txt file. It's always the same service. The script should also ask for the credential of the PC that it is trying to connect to.
This is a Script to set DNS on every PC in computer.txt. It asks me for the "administrator" password for every PC.
function Set-DNSWINS {
#Get NICS via WMI
$remoteuser = get-credential $_\administrator
$NICs = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Credential $remoteuser -ComputerName $_ -Filter "IPEnabled=TRUE"
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Credential $remoteuser -ComputerName $_ -Filter "IPEnabled=TRUE"
foreach($NIC in $NICs) {
$DNSServers = "192.168.3.12","192.168.0.77"
$NIC.SetDNSServerSearchOrder($DNSServers)
$NIC.SetDynamicDNSRegistration("TRUE")
#$NIC.SetWINSServer("12.345.67.890", "12.345.67.891")
}
}
function Get-FileName {
$computer = Read-Host "Dateiname mit Computernamen"
return $computer
}
Get-Content computer.txt | ForEach-Object {Set-DNSWINS}
You can stop a service from the commandline using
net stop "servicename"
or in PowerShell
Stop-Service "serviceName"
There are probably better ways to automate this across multiple machines than your script.
Can use Set-Service to disable a service and Invoke-Command to run it remotely. Note you need to run Enable-PSRemoting on the remote computer and configure WSMAN to allow connecting to the remote PC:
function MyFunction{
$remoteuser = get-credential $_\administrator
$service = "MyService"
Invoke-Command -computer $_ -credential $remoteuser -scriptblock {
Stop-Service $service
Set-Service $service -startuptype Disabled
}
}
function Get-FileName {
$computer = Read-Host "Dateiname mit Computernamen"
return $computer
}
Get-Content computer.txt | ForEach-Object {MyFunction}

Using Powershell to stop a service remotely without WMI or remoting

I came across this one liner that appears to work:
stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
Can anyone explain why, because I thought stop-service didn't work unless you either used remoting or it occurred on the local host.
The output of Get-Service is a System.ServiceProcess.ServiceController .NET class that can operate on remote computers. How it accomplishes that, I don't know - probably DCOM or WMI. Once you've gotten one of these from Get-Service, it can be passed into Stop-Service which most likely just calls the Stop() method on this object. That stops the service on the remote machine. In fact, you could probably do this as well:
(get-service -ComputerName remotePC -Name Spooler).Stop()
Thanks to everyone's contributions to this question, I've come up with the following script. Change the values for $SvcName and $SvrName to suit your needs. This script will start the remote service if it is stopped, or stop it if it is started. And it uses the cool .WaitForStatus method to wait while the service responds.
#Change this values to suit your needs:
$SvcName = 'Spooler'
$SvrName = 'remotePC'
#Initialize variables:
[string]$WaitForIt = ""
[string]$Verb = ""
[string]$Result = "FAILED"
$svc = (get-service -computername $SvrName -name $SvcName)
Write-host "$SvcName on $SvrName is $($svc.status)"
Switch ($svc.status) {
'Stopped' {
Write-host "Starting $SvcName..."
$Verb = "start"
$WaitForIt = 'Running'
$svc.Start()}
'Running' {
Write-host "Stopping $SvcName..."
$Verb = "stop"
$WaitForIt = 'Stopped'
$svc.Stop()}
Default {
Write-host "$SvcName is $($svc.status). Taking no action."}
}
if ($WaitForIt -ne "") {
Try { # For some reason, we cannot use -ErrorAction after the next statement:
$svc.WaitForStatus($WaitForIt,'00:02:00')
} Catch {
Write-host "After waiting for 2 minutes, $SvcName failed to $Verb."
}
$svc = (get-service -computername $SvrName -name $SvcName)
if ($svc.status -eq $WaitForIt) {$Result = 'SUCCESS'}
Write-host "$Result`: $SvcName on $SvrName is $($svc.status)"
}
Of course, the account you run this under will need the proper privileges to access the remote computer and start and stop services. And when executing this against older remote machines, you might first have to install WinRM 3.0 on the older machine.
Based on the built-in Powershell examples, this is what Microsoft suggests. Tested and verified:
To stop:
(Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StopService()
To start:
(Get-WmiObject Win32_Service -filter "name='IPEventWatcher'" -ComputerName Server01).StartService()
This worked for me, but I used it as start. powershell outputs,
waiting for service to finshing starting a few times then finishes and then a get-service on the remote server shows the service started.
**start**-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
Another option; use invoke-command:
cls
$cred = Get-Credential
$server = 'MyRemoteComputer'
$service = 'My Service Name'
invoke-command -Credential $cred -ComputerName $server -ScriptBlock {
param(
[Parameter(Mandatory=$True,Position=0)]
[string]$service
)
stop-service $service
} -ArgumentList $service
NB: to use this option you'll need PowerShell to be installed on the remote machine and for the firewall to allow requests through, and for the Windows Remote Management service to be running on the target machine. You can configure the firewall by running the following script directly on the target machine (one off task): Enable-PSRemoting -force.
You can also do (Get-Service -Name "what ever" - ComputerName RemoteHost).Status = "Stopped"
You could just run a foreach and have logging enabled.
The console will show if something goes wrong and you can look in the log.
That way, you can then handle the errors individually.
I think it works better this way than running a Test-Netconnection for the verification part because firewall rules can create the value false.
For this example you ned a csv file with column ServerName, Populate the column with servername.contoso.com
$ServerList = "$PSScriptRoot\Serverlist.csv"
$Transcriptlog = "$PSScriptRoot\Transcipt.txt"
Start-Transcript -Path $Transcriptlog -Force
Get-Date -Format "yyyy/MM/dd HH:mm"
Try
{ # Start Try
$ImportServerList = Import-Csv $ServerList -Encoding UTF8 | ForEach-Object { # Start Foreach
New-Object PsObject -Prop #{ # Start New-Object
ServerName = $_.ServerName } # End NewObject
Invoke-Command -ComputerName $_.ServerName -ErrorAction Continue -ScriptBlock { # Start ScriptBlock
# Disable Service PrintSpooler
Get-Service -Name Spooler | Stop-Service -Force
} # End ScriptBlock
} # End Foreach
} # End Try
Catch
{ # Start Catch
Write-Warning -Message "## ERROR## "
Write-Warning -Message "## Script could not start ## "
Write-Warning $Error[0]
} # End Catch
Stop-Transcript
stop-service -inputobject $(get-service -ComputerName remotePC -Name Spooler)
This fails because of your variables
-ComputerName remotePC needs to be a variable $remotePC or a string "remotePC"
-Name Spooler(same thing for spooler)
As far as I know, and I cant verify it now, you cannot stop remote services with the Stop-Service cmdlet or with .Net, it is not supported.
Yes it works, but it stopes the service on your local machine, not on the remote computer.
Now, if the above is correct, without remoting or wmi enabled, you could set a scheduled job on the remote system, using AT, that runs Stop-Service locally.