How I can pass multiple array in value in PowerShell function - powershell

Below function I want to pass multiple value in array. When I'm passing more than one value I am getting an error.
function CheckProcess([String[]]$sEnterComputerNameHere, [String[]]$sEnterProccessNameHere) {
#Write-Host " $sEnterComputerNameHere hello"
#($sEnterComputerNameHere) | ForEach-Object {
# Calling Aarray
#($sEnterProccessNameHere) | ForEach-Object {
if (Get-Process -ComputerName $sEnterComputerNameHere | where {$_.ProcessName -eq $sEnterProccessNameHere}) {
Write-Output "$_ is running"
} else {
Write-Output "$_ is not running"
}
}
}
}
$script:sEnterProccessNameHere = #("VPNUI") # Pass the process agreement here
$script:sEnterComputerNameHere = #("hostname") # Pass the process agreement here
CheckProcess $sEnterComputerNameHere $sEnterProccessNameHere

Give it a try with this one:
Function CheckProcess([String[]]$sEnterComputerNameHere,[String[]]$sEnterProccessNameHere)
{ #Write-host " $sEnterComputerNameHere"
#($sEnterComputerNameHere) | Foreach-Object {
$computer = $_
Write-Host $computer
#($sEnterProccessNameHere) | Foreach-Object {
$process = $_
Write-Host $process
try{
$x = get-process -computername $computer #Save all processes in a variable
If ($x.ProcessName -contains $process) #use contains instead of equals
{
Write-Output "$process is running"
}
else
{
Write-Output "$process is not running"
}
}
catch
{
Write-Host "Computer $computer not found" -ForegroundColor Yellow
}
}
}
}
$script:sEnterProccessNameHere = #("VPNUI","Notepad++","SMSS")
$script:sEnterComputerNameHere = #("remotecomputer1","remotecomputer2")
CheckProcess -sEnterComputerNameHere $sEnterComputerNameHere -sEnterProccessNameHere $sEnterProccessNameHere
In general, it would be great if you write the error you get in your question. That helps others to help you.
If I work with arrays and | Foreach, I always write the $_in a new variable. That helps if I have another | Foreach (like you had) to know for sure, with which object I'm working with..
EDIT: I changed the script, so it uses "-contains" instead of "-eq" and I added a try/catch block, so if the other computer is not found, it gives you a message.. It works on my network
EDIT2: Do you have access to the other computers? If you run get-process -computername "name of remote computer" do you get the processes?

Related

how to fix the error Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction

I have a function which requires the user to enter Y or N to delete a file and I'm trying to run this whole function as a start-job function. My code is:
$JobFunction2 = {
function init {
try {
$output = terraform init
$path = Get-Item -Path ".\"
$in = $output | Select-String "Terraform has been successfully initialized!"
if ($in) {
Write-Host -ForegroundColor GREEN 'Initialization successfull'
}
else {
Write-Host -ForegroundColor YELLOW 'Intiialization failed Please enter Y to delete the .terraform folder'
$fail = del $path/.terraform -Force
$output = terraform init
return $fail, $output
}
}
catch {
Write-Warning "Error Occurred while Initializing the folder and the path is: $path"
}
}
}
Start-Job -InitializationScript $JobFunction2 -ScriptBlock { init } | Wait-Job | Receive-Job
When I'm running the start-job it shows "Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction". But if I'm calling only the function name 'init' without starting a job it works perfectly. Is there any way I could prompt the user to input Y or No so that the function could work in start-job?
Not sure what is setting your job's State to Blocked, but if the question is: Is there any way I could prompt the user to input Y or N so that the function could work in Start-Job?
The answer is yes, below you can see an example of how it can be implemented, note that I'm using a while loop instead of Wait-Job.
According to the documentation, the cmdlet has a -Sate parameter that takes a <JobState> argument but I couldn't get it to work. Even tried:
Wait-Job -Any -Force -State Blocked
And got the same error as you, so here is the brute force solution you can use:
function init {
'Initializing Function {0}' -f $MyInvocation.MyCommand.Name
do
{
$choice = Read-Host 'Waiting for user input. Continue? [Y/N]'
if($choice -notmatch '^y|n$')
{
'Invalid input.'
}
}
until ($choice -match '^y|n$')
if($choice -eq 'y')
{
'Continue script...'
}
else
{
'Abort script...'
}
}
$funcDef = [scriptblock]::Create("function init { $function:init }")
$job = Start-Job -InitializationScript $funcDef -ScriptBlock { init }
$desiredState = 'Stopped', 'Completed', 'Failed'
while($job.State -notin $desiredState)
{
if($job.State -eq 'Blocked')
{
Receive-Job $job
}
Start-Sleep -Milliseconds 500
}
$job | Receive-Job -Wait -AutoRemoveJob
$fail = Remove-Item $path/.terraform -Force -Recurse -Confirm:$false
this helped me to solve my issue

Try Catch - How to Catch error but continue?

I've got this script, which loops through a foreach loop for each computer, and for each computer it loops through each NIC. Currently the Catch block is not running. What I want to do is catch the error (usually because get-wmi is not able to connect to a machine), do something (add some information to a PSCustomObject), but then continue to the next iteration. How do I catch an error but also continue the foreach loop?
param (
[Alias('Hostname')]
[string[]]$ComputerName = #('pc1','pc2'),
$OldDNSIP = '7.7.7.7',
$NewDNSIP = #('9.9.9.9','8.8.8.8')
)
$FailedArray = #()
$DHCPArray = #()
Foreach ($Computer in $ComputerName){
$NICList = Get-WmiObject Win32_NetworkAdapterConfiguration -computername $Computer | where{$_.IPEnabled -eq "TRUE"}
Foreach($NIC in $NICList){
If($NIC.DHCPEnabled -eq $false){
Try{
$DNSIPs = $NIC.DNSServerSearchOrder
if($DNSIPs -contains $OldDNSIP){
$NewDNS = $DNSIPs | foreach {$_ -replace $OldDNSIP,$NewDNSIP[0]}
$null = $NIC.SetDNSServerSearchOrder($NewDNS)
}
else{
write-host " - Old DNS server IP not found... ignoring"
}
}
Catch{
write-host " - Something went wrong... logging to a CSV for review later" -ForegroundColor Red
$FailedArray += [PSCustomObject]#{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description}
}
}
ElseIf($NIC.DHCPEnabled -eq $true){
write-host " - DHCP is enabled. Adding this IP, Hostname, Nic Index and DHCP Server to a CSV for reviewing."
#add pscomputer, nic id, refernece and dhcp server to DHCPNICArray
$DHCPArray += [PSCustomObject]#{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description
'DHCPEnabled' =$nic.dhcpenabled
'DHCPServer' = $nic.dhcpserver}
}
}
}
$DHCPArray | export-csv c:\temp\dhcp.csv -NoTypeInformation
$FailedArray | export-csv c:\temp\failed.csv -NoTypeInformation
If the WMI errors are due to a connection fail, they will occur before any of the nics are processed. If you want to catch them, and then continue with the next computer, you have to move the try-catch up to the level of that loop. If you also want to catch nic-specific errors, you need a 2nd try-catch at that level.
Also, consider using -ErrorAction Stop parameter, or specify $ErrorActionPreference = 'Stop', to make sure all errors are terminating (that means, jump right to the catch block).
Here's an example, with comments for explanation:
$ErrorActionPreference = 'Stop'
foreach ($Computer in $ComputerName) {
# add a try-catch per computer,
# to catch WMI errors
# and then continue with the next computer afterwards
try {
# if errors occur here,
# execution will jump right to the catch block the bottom
$NICList = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computer -ErrorAction Stop | where {
$_.IPEnabled -eq "TRUE"
}
foreach ($NIC in $NICList) {
# add a try-catch per NIC,
# to catch errors with this specific NIC and then
# continue with the next nic
try {
if ($NIC.DHCPEnabled -eq $false){
$DNSIPs = $NIC.DNSServerSearchOrder
if ($DNSIPs -contains $OldDNSIP) {
$NewDNS = $DNSIPs | foreach {$_ -replace $OldDNSIP,$NewDNSIP[0]}
$null = $NIC.SetDNSServerSearchOrder($NewDNS)
}
else {
write-host " - Old DNS server IP not found... ignoring"
}
}
elseif ($NIC.DHCPEnabled -eq $true){
write-host " - DHCP is enabled. Adding this IP, Hostname, Nic Index and DHCP Server to a CSV for reviewing."
$DHCPArray += [PSCustomObject]#{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description
'DHCPEnabled' =$nic.dhcpenabled
'DHCPServer' = $nic.dhcpserver
}
}
}
catch {
write-host " - Configuring a NIC went wrong... logging to a CSV for review later" -ForegroundColor Red
# add nic-specific entry
$FailedArray += [PSCustomObject]#{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description
}
}
# continue with next nic...
} # foreach nic
}
catch {
write-host " - Something else went wrong... logging to a CSV for review later" -ForegroundColor Red
# add entry for current computer
# (we don't know about nics, because wmi failed)
$FailedArray += [PSCustomObject]#{
'Computer' = $Computer
}
}
# continue with next computer...
} # foreach computer

Citrix Application list with assigned groups

The following script gives me the list I want but I need to save the output to a file:
asnp citrix*
$apps = Get-BrokerApplication -MaxRecordCount 10000 -AdminAddress khonemdc75ddc01;
$apps | ForEach-Object {
$array = $_.AssociatedDesktopGroupUids
foreach ($element in $array) {
$policy = Get-BrokerAccessPolicyRule –DesktopGroupUid $element -AllowedConnections NotViaAG
write-host "Application: " $_.ApplicationName
if ($_.AssociatedUserNames)
{
write-host "Users configured using Visibility:" $_.AssociatedUserNames
write-host '--------------------'
}
else
{
write-host "Users with access inherited from DG:"
$policy.IncludedUsers;
write-host '--------------------'
}
}
}
If you use the Write-Hostcmdlet, you won't be able to pipe the output to a file - just write the string to the pipeline. To save the output, you can use the Out-File cmdlet:
asnp citrix*
$apps = Get-BrokerApplication -MaxRecordCount 10000 -AdminAddress khonemdc75ddc01;
$apps | ForEach-Object {
$array = $_.AssociatedDesktopGroupUids
foreach ($element in $array) {
$policy = Get-BrokerAccessPolicyRule –DesktopGroupUid $element -AllowedConnections NotViaAG
"Application: $_.ApplicationName"
if ($_.AssociatedUserNames)
{
"Users configured using Visibility: $_.AssociatedUserNames"
'--------------------'
}
else
{
"Users with access inherited from DG: $policy.IncludedUsers;"
'--------------------'
}
}
} | Out-File -FilePath 'your_file.txt'
Use write-ouput instead out write-host and at the end just pipe it at the end > c:\test.txt

Powershell NSlookup on DC's Forward and Reverse

$topDC1="10.254.90.17"
$topDC2="10.225.224.17"
$topDC3="10.110.33.32"
$topDC4="10.88.100.10"
$DomainName="office.adroot.company.net"
TRY{
$hostname = [System.Net.DNS]::GetHostByName($topDC1).HostName.toupper()
$ipaddress = [System.Net.Dns]::GetHostAddresses($DomainName) | select IPAddressToString -ExpandProperty IPAddressToString
# I want the below to loop foreach ip in the object, ns it against all 4 topDC's, then output each result :(
$NS1 = nslookup $ipaddress[0] $topDC1
Write-host $NS1
}
Catch{
write-host "error"
}
Here is my dirty code so far (just to keep it simple)
I am trying to automate this:
NSLOOKUP office.adroot.company.net
put the results into an object
for each ip in results, do an NSLOOKUP against our top level DC's.
find which DC's haven't been cleaned up after decommission (still in dns)
$DCList="10.254.90.17","10.225.224.17","10.110.33.32","10.88.100.10"
$DomainName="office.adroot.blorg.net","pcd.blorg.ca","blorg.ca","percom.adroot.blorg.net", "blorg.blorg.net","ibg.blorg.net","sacmcm.adroot.blorg.net","sysdev.adroot.blorg.net","adroot.blorg.net"
TRY{
foreach ($DomainNameItem in $DomainName){
Write-Host ""
Write-Host ""
Write-Host "Looking UP result"$DomainNameItem -foreground yellow
Write-Host ""
$hostname = [System.Net.DNS]::GetHostByName($DCListItem).HostName.toupper()
$ipaddress = [System.Net.Dns]::GetHostAddresses($DomainNameItem).IPAddressToString
foreach ($ip in $ipaddress){
Write-Host ""
Write-Host "Looking UP result"$ip -foreground green
foreach ($topdns in $DCList){
$RESULTS = nslookup $ip $topdns
Write-host $RESULTS
}
}
}
}
Catch{
write-host "error"
}
Write-Host ""
Write-Host ""
pause
Got it! This will save me tonnes of work determining if a DNS cleanup is necessary. Thanks guys, I'm learning just how great Powershell can be :)
Try this:
$topDomainControllers = #("10.254.90.17", "10.225.224.17", "10.110.33.32", "10.88.100.10")
$DomainName="office.adroot.company.net"
try {
$hostname = [System.Net.Dns]::GetHostByName($topDC1).HostName.ToUpper()
$ipAddresses = [System.Net.Dns]::GetHostAddresses($DomainName) |
select -ExpandProperty IPAddressToString
foreach ($ipAddress in $ipAddresses) {
$nslookupResult = nslookup $ipAddress
$foundIp = $nslookupResult[1] -match "^\D*(\d+\.\d+\.\d+\.\d+)$"
if ($foundIp -eq $false) {
continue
}
$domainController = $Matches[1]
if ($topDomainControllers.Contains($domainController)) {
Write-Output -Verbose "Found domain controller match for $domainController"
break
} else {
Write-Output -Verbose "No match found for domain controller $domainController"
}
}
} catch {
Write-Output "An error has occured: $_"
}

powershell Foreach-Object usage

I have script:
$servers = "server01", "s02", "s03"
foreach ($server in $servers) {
$server = (New-Object System.Net.NetworkInformation.Ping).send($servers)
if ($server.Status -eq "Success") {
Write-Host "$server is OK"
}
}
Error message:
An exception occured during a Ping request.
I need to ping each server in $servers array and display status. I think, that Foreach statement is not properly used, but I'm unable to find out where is the problem. Thank you for your advice
You should not be modifying the value of $server within the foreach loop. Declare a new variable (e.g. $result). Also, Ping.Send takes the individual server name, not an array of server names as an argument. The following code should work.
Finally, you will need to trap the PingException that will be thrown if the host is unreachable, or your script will print out a big red error along with the expected results.
$servers = "server1", "server2"
foreach ($server in $servers) {
& {
trap [System.Net.NetworkInformation.PingException] { continue; }
$result = (New-Object System.Net.NetworkInformation.Ping).send($server)
if ($result.Status -eq "Success") {
Write-Host "$server is OK"
}
else {
Write-Host "$server is NOT OK"
}
}
}