Using PowerShell to verify that a specific service exists from a .txt list of server names - function

I am trying to verify that a specific service exists from a .txt list of server names and then output to a file. In this case I need to also add credentials so I need to use the Invoke-Command. What am I doing wrong here?
clear
start-transcript -path .\Log.txt
$servers = Get-Content .\Resources\Lab.txt
$cred = get-credential domain\Username
$name = Read-Host -Prompt 'Input your service name'
function Getinfo() {foreach($server in $servers)
{
Get-Service | Where-Object { $_.Name -eq $name}-and {$_.Status -eq "Running"}| Format-Table -AutoSize
}
}
Invoke-Command -credential $cred -ComputerName $servers -ScriptBlock ${function:Getinfo}
Stop-Transcript

I think you mean this?
$servers = Get-Content .\Resources\Lab.txt
$cred = Get-Credential domain\Username
$name = Read-Host -Prompt 'Input your service name'
Invoke-Command -Credential $cred -ComputerName $servers -ScriptBlock {
param($name)
Get-Service | Where-Object { $_.Name -eq $name -and $_.Status -eq "Running"}
} -ArgumentList $name | Format-Table -AutoSize

Related

Trying to use remote variable in If-Condition within ScriptBlock using PowerShell

I am trying to use below code to remove the groups from Active Directory. I am maintaining an input file for the list of servers. the input file is in the local machine and trying to use the content of the file inside the ScriptBlock using ($Using:variablename) after taking a remote session.
I am getting the content[file content] of the variable inside the ScriptBlock which is defined outside the ScriptBlock. The issue is the if condition [if($serverlist -ne $null)] is satisfying even if the variable is empty. The code is entering into if block even if the variable $serverlist is null, instead it has to take else block.
Could you please help me on this.
$adserver = Read-Host -Prompt "Please enter AD server details"
$adserver
$askcredential = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password.", "", "NetBiosUserName")
$credential = New-Object System.Management.Automation.PsCredential($askcredential.UserName,$askcredential.Password)
$session = New-PSSession -ComputerName "$adserver" -Credential $credential
#$command = (Get-ADForest).domains
$addomain = Read-Host -Prompt "Please enter the Domain"
$servers = Get-Content "D:\Bhargavi\Windows-Decommission\$addomain\servers.txt"
#Invoke-Command -ComputerName $adserver -Authentication Default -Credential $credential -ScriptBlock {
Invoke-Command -Session $session -ScriptBlock {
#$addomain = Read-Host -Prompt "Please enter the Domain"
#$servers = Get-Content "D:\Bhargavi\Windows-Decommission\$addomain\servers.txt"
#Param($domainname,$serverlist)
$serverlist = $Using:servers
$domainname = $Using:addomain
Write-Host "the list is $serverlist"
Write-Host "the domain is $domainname"
if($serverlist -ne $null)
{
Write-Host "Found the data in the input file. Proceeding to remove the groups."
foreach ($server in $serverlist)
{
write-host "Server Name is: $server"
$mgserver = "MG-$server"
$mggroup = Get-ADGroup -Filter { Name -like $mgserver }
$mggroup
if($mggroup -ne $null)
{
Get-ADGroup -Filter { Name -like $mgserver } #| Remove-ADGroup -Confirm:$False
$mggroupconfirm = Get-ADGroup -Filter { Name -like $mgserver }
if($mggroupconfirm -eq $null)
{
Write-Host "$mgserver is removed from $domainname"
#Set-Content -Path "D:\Bhargavi\Windows-Decommission\$domainname\servers.txt" -Value (get-content -Path "D:\Bhargavi\Windows-Decommission\$domainname\servers.txt" | Select-String -Pattern "$server" -NotMatch)
}
else
{
Write-Host "$mgserver is not removed. Please try again."
}
}
else{Write-Host "There is no group called $mgserver in $domainname domain "}
}
}
else
{
DO
{
$val = Read-Host -Prompt "Do you want to enter servername ? Enter yes or no"
if($val -eq "yes")
{
$entermgserver = Read-Host -Prompt "Please enter the server name"
$entermgserver
$mgserver = "MG-$entermgserver"
$mgserver
$mggroup = Get-ADGroup -Filter { Name -like $mgserver }
$mggroup
if($mggroup -ne $null)
{
#Write-Host "$mggroup is not null"
Get-ADGroup -Filter { Name -like $mgserver } #| Remove-ADGroup -Confirm:$False
$mggroupconfirm = Get-ADGroup -Filter { Name -like $mgserver }
if($mggroupconfirm -eq $null)
{
Write-Host "$mgserver is removed"
}
else
{
Write-Host "$mgserver is not removed. Please try again."
}
}
else{Write-Host "The is no group called $mgserver in $domainname domain"}
}
}until ($val -eq "no")
}
} ### End Script Block
Clear-Content "D:\Bhargavi\Windows-Decommission\$addomain\servers.txt"
Remove-PSSession -Session $session

Need to add If (Test-Connection) cmdlet

Is it possible to add the If (Test-Connection) cmdlet to this script? I want to ping the host first
the run the script if the host its on.
`enter code here`
$sb = { write-host "$env:computername"
Get-ChildItem HKLM:\SOFTWARE\McAfee\AVSolution\DS\ -Recurse | ForEach-Object {
Get-ItemProperty $_.pspath
}
}
$Results = Invoke-Command -ScriptBlock $sb -ComputerName (Get-Content -Path 'C:\computers.txt')
#Show output to screen
Write-Output $Results
$Results | Export-Csv -Path 'C:\computers.CSV' -NoTypeInformation -Append

How to pass multiple domain and local user accounts into a function

I have a script that I have been trying to massage and I want to take a loop that was copied multiple times for each user and I want to turn it into a function.
I have figured out to pass multiple local users to the script and I have been able to pass one domain user to the script and have it work successfully.
But I want to be able to create a list of users and their domains (some have none)
and pipe that into the function automatically. I know I could just keep writing out the function with each username and password but If I can avoid that, that would be great
Function Launch-cfm {
Param (
[Parameter(Mandatory=$true, Position=0)]
[string] $username,
[Parameter(Mandatory=$false, Position=1)]
[string] $domain
)
if ($domain -eq $tue) {
Stop-Process -name "autohotkey" -Force -ErrorAction SilentlyContinue
&$OutFile
$user = "$username"
$user_sam = ($members | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}) -contains $user
if ($user_sam -eq $true) {
$user = "$username"
$account = $user
$PassFile = $CredPath+$user+,"_Password.txt"
$keyFile = $CredPath+$user+,".key"
$key = Get-content $keyFile
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $account, (Get-Content $PassFile | ConvertTo-SecureString -Key $key)
Write-Host "info to user about scripts actions."
C:
Start-Process -FilePath $mmcPath -ArgumentList $mscPath -Credential $cred;pause
} else { Write-Host "$user does not exist on this server!!!! Moving on...!
"}
} else {
Stop-Process -name "autohotkey" -Force -ErrorAction SilentlyContinue
&$OutFile
$user = "$username"
$user_sam2 = ($members | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}) -contains $user
if ($user_sam2 -eq $true) {
$account = $domain+,"\"+$user
$PassFile = $CredPath+$user+,"_Password.txt"
$keyFile = $CredPath+$user+,".key"
$key = Get-content $keyFile
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $account, (Get-Content $PassFile | ConvertTo-SecureString -Key $key)
Write-Host "info to user about scripts actions"
Start-Process -FilePath $mmcPath -ArgumentList $mscPath -Credential $cred;pause
} else { Write-Host "$user does not exist on this server!!!! Moving on...!
"}
}
}
$use = "User1","user2"
$dom = "domain1",""
launch-cfm -username $use -domain $dom
any suggestion would be great. or to know if what I am asking is even possible.
Thanks.
What I think you are looking for is a never ending parameter. Give this a try.
Input: Launch-cfm -usernames "Drew","Cleadus","Stack" -domain "SuperDomain1337"
Function Launch-cfm {
Param (
[Parameter(Mandatory=$true)]
[string[]] $usernames,
[Parameter(Mandatory=$false)]
[string] $domain
)
Foreach($user in $usernames){
Do-Magic
}
}
Reasoning:
I am not a fan of positional parameters, throw them where they feel right in the moment.
Using [string[]] instead of [string] means that it will put all values passed to it into an array for later use within the function. This current configuration allows for MULTIPLE users but only ONE domain. You can change that but would need to iterate over each domain and user at a time, unless specified within the script some how.
EG.
Foreach($dom -in $domain){
Foreach($user in $usernames){
Do-Magic
} Else {
Do-LessImpressiveMagic
}
}

try-catch bypassing a step

I have a script that tests connection to a list of servers, and if contactable, gets the status of a service, and puts the results into three variables, $Computer, $Ping (True/False), and $Service (Running or Stopped).
The output is in a hashtable but I can only get to show the servers that ARE contactable, and not the ones that cannot be contactable.
I have placed a try/catch in the $Ping block, as well as -ErrorAction Stop, so that it doesn't attempt to run the $Service script, and instead go to the next $Computer in the array. I think I am trying to do two things at once that are conflicting each other:
add the variables to the #Splat and
don't process any further.
There are actually many more remote registry queries in my script, which will be irrelevant if the $Computer cannot be contactable, but I have shortened it for this post.
Function Get-Ping {
$Servers = (gc "c:\temp\test.txt")
foreach ($Computer in $Servers) {
Write-Host
Write-Host "---------------------------------"
Write-Host "QUERYING $Computer"
Write-Host
Write-Host "Performing ping test..."
try {
$Ping = Test-Connection $Computer -Count 1 -ErrorAction Stop
} catch {
Write-Warning "Cannot Ping $Computer"
Write-Host "Trying next computer..."
Write-Host
continue
}
if ($Ping) {$Ping="$True"}
Write-Host $Computer "can be pinged"
$svcRRStopped = $false
if ($Computer -ne $env:COMPUTERNAME) {
Write-Host "Check RemoteRegistry status..."
}
$svcRR = Get-Service -ComputerName $Computer -Include RemoteRegistry
$SelectSplat = #{
Property = (
'Computer',
'Ping',
'Service'
)}
New-Object -TypeName PSObject -Property #{
Computer=$Computer
Ping=$Ping
Service=$svcRR.status
} | Select-Object #SelectSplat
}
}
$results = Get-Ping
$tableFragment = $results | Select 'Computer','Ping','Service'
$tableFragment
Don't make things more complicated than they need to be.
function Get-Ping {
Get-Content 'C:\temp\test.txt' | ForEach-Object {
$isAvailable = [bool](Test-Connection $_ -Count 1 -EA SilentlyContinue)
if ($isAvailable) {
$rreg = Get-Service -Computer $_ -Name RemoteRegistry |
Select-Object -Expand Status
} else {
$rreg = 'n/a'
}
New-Object -Type PSObject -Property #{
Computer = $_
Ping = $isAvailable
Service = $rreg
}
}
}
Get-Ping
You can simply use the -Quiet Parameter:
Test-Connection $_ -Count 1 -Quiet

Powershell Export to CSV with three coumns

function getServerInfo
{
$serverList = Get-Content -Path "C:\Users\username\Desktop\list.txt"
$cred = Get-Credential -Credential "username"
foreach($server in $serverList)
{
$osVersion = gwmi win32_operatingSystem -ComputerName $server -ErrorAction SilentlyContinue
if($osVersion -eq $null)
{
$osVersion = "cannot find osversion"
}
$psv = Invoke-Command -ComputerName $server -ScriptBlock {$PSVersionTable.PSVersion.Major} -ErrorAction Ignore
if($psv -eq $null)
{
$psv2 = Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock {$PSVersionTable.PSVersion.Major} -ErrorAction Ignore
Write "$server has $($osVersion.Caption)and PSVersion is $psv2"
}
else{
Write "$server has $($osVersion.Caption)and PSVersion is $psv"
}
}
}
I am trying to create a csv file with 3 columns.
First column will have $server, second column will have $osVersion and third will have $psv. Please help. thank you!
Rather than using the foreach loop, consider using the ForEach-Object cmdlet so that the results can be piped to other commands. Inside of the ForEach-Object script block, you can calculate the 3 values you need, and then its easy to create CSV string using string interpolation. The results can then be piped to the appropriate output file.
Get-Content -Path C:\Users\username\Desktop\list.txt | ForEach-Object {
$Server = $_
$OSVersion = gwmi Win32_OperatingSystem -ComputerName $Server -ErrorAction SilentlyContinue
$PSVersion = Invoke-Command -ComputerName $Server -ScriptBlock { $PSVersionTable.PSVersion.Major }
"$Server,$OSVersion,$PSVersion"
} | Out-File outputFilename.csv
To export to a CSV using the Export-CSV cmdlet, PowerShell expects an array of objects with the same set of properties to output. For your case you can do that fairly simply as such:
$cred = Get-Credential -Credential "username"
$AllServers=foreach($server in $serverList)
{
[PSCustomObject]#{
'Server' = $Server
'osVersion' = gwmi win32_operatingSystem -ComputerName $server -ErrorAction SilentlyContinue | Select -Expand Caption
'psv' = Invoke-Command -ComputerName $server -ScriptBlock {$PSVersionTable.PSVersion.Major} -ErrorAction Ignore -Credential $cred
}
}
$AllServers | Export-Csv c:\path\to\output.csv -notype