I've been working on transitioning a tool I'm creating for work from a traditional WPF, to a WPF that utilizes runspaces. The learning curve was a bit steep, at first, but I'm starting to get the hang of it.
I'm having some trouble getting certain powershell command results to pass through to the runspace.
The most recent issue:
I have a working powershell script that will do the following
Resolve the IP of a computer name
$resolve = resolve-dnsname $computername | select IPAddress
$IP = $resolve -replace ".*-" -replace ".{1}$"
$GetIP will show me the IPV4 address in the console
Perform nbtstat on the IP and grab the first
$NBT = IF($IP -ne "") {nbtstat -a $IP}
foreach ($line in $NBT) {
if($line -match '^\s**([^<\s]+)\s*<00>\s*UNIQUE')
{
$NBTName = $Matches[1]
break
}}
Return TRUE if the name associated with the IP address does not match the $computername or FALSE if they do match.
$BadDNS = IF($computername -ne $NBTName -and $IP -notmatch ""){"TRUE"} ELSE {"FALSE"}
This works well in a standard powershell environment. However, I cannot get this to work in my WPF form with runspaces. I have gotten so far as discovering the issue I'm running into is the IPV4 address will not populate correctly. When I run this command and output the $IP variable to a textbox, I'm getting something similar to the following
fe80:xxxx:xxxx:xxxx:xxxx %19 192.168.1.1
The resulting IP will of course fail any checks. I've tried multiple methods of pulling the IPV4 address over to the WPF GUI with varying results. None of which were acceptable.
For example:
$IP = test-netconnection -computername $computername
$IP.RemoteAddress.IPAddressToString
Which, again, gives me the IPV4 address in my ISE console. However the results are unusable in the WPF, for some reason.
Does anyone have any idea of how to get this information into my GUI?
Thank you in advance!
Related
So im pretty new to powershell and i have multiple questions on how to write scripts using it but right now my main issue is that i want to be able to ping all of the computers on my network and take the names of the computers that ping back and put them into an array so that i can push updates to the computers that are on the network just using one array containing the current computers on the network. here is what i am working with right now.
foreach ($c in $204computernames)
{if(test-connection -computername $c.name -count 1 -quiet)
{write-host $c.name
}
}
currently this string of code runs a foreach loop so that $c(the computers) run against $204computernames(the known computers on the network)then it tests the positive connections through the if statement and finally at the end it outputs the names of the computers that are on the network. Now the problem im understanding from this is when i use a foreach loop that it will run against all of the known computers and as each computer is put through the loop it is replaced by the preceding one, but i want each and every one that comes back on the network to be stored in an array. Is there a way that i can do this with the current format or is there a certain way that i can tweak what i have so that i can get the output i want?
The idiomatic solution to "how do I filter a list against a condition and save the results" would be to pipe the input to Where-Object:
$onlineComputers = $204computernames |Where-Object { Test-Connection $_.name -Count 1 -Quiet }
I'm back!
Anyway, I'm running an exchange script to find emails that contain a specific list of keywords for a specific set of users, defined as users and terms in the script below, and it works. However after about an hour or so of running, it's consuming obnoxious amounts of memory, 12 - 14 GB. and running very slowly.
It does flux between 3 GB and 14 GB, so I don't know if this is simply normal, expected behavior or if its' something wrong with my script. I am aware that I'm using a sorta(?) depreciated commandlet in the search-mailbox function, but I'm only searching about 300 users and 21 terms, so I don't think I need to use the new-mailboxsearch commandlet.
Script for Reference
$users = Get-Content x:\xxx\xxx\users.txt
$terms = Get-Content x:\xxx\xxx\Terms.txt
ForEach ($term in $Terms) {
ForEach ($line in $users) {
$Results = Search-Mailbox -Identity $line -SearchQuery $term -TargetMailbox SearchResults2 -TargetFolder $term -LogLevel Full | Select Identity,TargetFolder,ResultItemsCount
Add-Content -Path x:\xxx\xxx\outputfile.txt -Value "$($term);$($line);$($Results.TargetFolder);$($Results.ResultItemsCount)"
}
}
Anyway, any help is, as always, greatly appreciated.
Thanks!
Does foreach-object fair better?
$terms | ForEach { $term = $_
$users | ForEach { $line = $_
..
}
}
The problem wasn’t with the script itself, it was the environment we were running it in.
For some reason running the script inside of the integrated scripting environment Powershell ISE, was causing the script to suck up crazy amounts of memory, eventually halting the system. By simply launching it outside of the ISE we were able to get the script to behave normally:
Thanks to everyone who replied!
I tried to find ip addresses assigned to vms in an esxi server? either from terminal or vSphere Client.
If you have installed VMware Tools in the VMs, then you can use the following one-liner to get the IP Address from command line:
for i in `vim-cmd vmsvc/getallvms | grep -v Vmid | awk '{print $1}'`; do vim-cmd vmsvc/get.guest $i | grep -i 'ipaddress = "'; done
For non-shell, you have tons of powercli snippets, but you still need VMware tools.
Check the last box on the following link for a couple options: https://kb.vmware.com/kb/2012964
Depending on which version of ESXi you're using, you should be able to right click within the GUI and add a column for IP address.
Note: in order for the IP addresses of guests to be presented up through the ESXi host, VMware Tools will need to be installed and running.
v = Get-View -Viewtype VirtualMachine -Property name, guest.ipaddress
$report = #()
foreach($vm in $v)
{
$list = '' | select name, ipaddress
$list.name = $vm.name
$list.ipaddress = $vm.guest.ipaddress
$report += $list
}
$report | export-csv c:\temp\listallnamesandipaddresses.csv
This is my first post, I've been a long time reader of various post.
What I have to do is disable a large number of services in a large number of VM's. I have 6-7 different enviornments to do this in I created 2 text files//paths which I gave the variables $vmList and $serviceList.
When I run these through the different environments using (EXTERNAL IP) addresses it works in for only 1 environment. When I try to run this with (INTERNAL IP) addresses I get the same identical exception thrown which is that it cannot find the set service (defragsvc) on the machine and then exits the loops. However when I log into these machines they are definitely there but not started. I am definitely lost as to why this works in 1 environment (confirmed on the machines) but fails in the others any help would be appreciated
$vmList =gc C:\PowerCli\Services\Staging_1_Defrag_Kill.txt
$serviceList =gc C:\PowerCli\Services\ServicesKill.txt
ForEach ($vm in $vmList){
ForEach ($service in $serviceList){
write-host $vm
Stop-service -inputobject(Get-Service -Name $service -ComputerName $vm)-force -confirm:$false -EA SilentlyContinue
Set-Service -ComputerName $vm -Name $service -EA Stop -Startmode Disabled
Write-Host "$vm : Successfully disabled the service $service" -ErrorAction SilentlyContinue
}
}
Hah, I figured it out,
As it turns out, I couldnt connect to the service control manager, it was a permissions error not a problem with the script. Lessons learned
please help. I have a the following function.
PROCESS {
$ServersArray = #('localhost')
foreach ($serverArray in $ServersArray) {
try {
if ($WebConfig.SelectedIndex -gt -1) {
Write-Host -ForegroundColor Cyan "Applying Maintenance on $ServerArray"
$everything_ok = $true
Invoke-Command $serverArray -ScriptBlock {
$filePath = "D:\\Inetpub\\MyHL3Ordering\\Configuration\\MyHL" + "\\" + $WebConfig.SelectedItem
(Get-Content $filePath) | ForEach-Object {
$_ -replace 'allowDO="true"','allowDO="false"'
} | Set-Content $filePath -Encoding UTF8;
} -ErrorAction 'Stop'
}
so basically I would like to concatenate the path with the combobox selected item. for example. if the selected item is web_da-DK.config , the path should be
'D:\Inetpub\MyHL3Ordering\Configuration\MyHL\web_da-DK.config' but it is not working.
error is:
Cannot find part of the path 'D:\Inetpub\MyHL3Ordering\Configuration\MyHL\' it doesnt seem to concatenate the value of combobox selectedItem to the path.
Please let me know what am I doing wrong.
The problem is that you are trying to use a variable from a scope in which is does not exist. You can read more about scopes if you run the following command:
Get-Help about_scopes
Since you are using PowerShell v3 you can use the Using scope modifier. From the help on about_scopes:
The Using scope modifier
Using is a special scope modifier that identifies a local
variable in a remote command. By default, variables in remote
commands are assumed to be defined in the remote session.
The Using scope modifier is introduced in Windows PowerShell 3.0.
For more information, see about_Remote_Variables.
It further suggest reading the about_Remote_Variables, which states:
USING LOCAL VARIABLES
You can also use local variables in remote commands, but you must
indicate that the variable is defined in the local session.
Beginning in Windows PowerShell 3.0, you can use the Using scope
modifier to identify a local variable in a remote command.
The syntax of Using is as follows:
The syntax is:
$Using:<VariableName>
In order to take an example of this, we could make a sample first which tries to use the local variable immediately, like the following:
$serverArray = "localhost"
$filename = "somefile.txt"
Invoke-Command -ComputerName $ServerArray -ScriptBlock {
$concatenated = [System.IO.Path]::Combine("C:\rootpath", $filename)
Write-Host $concatenated
}
This will yield the following output:
C:\rootpath
If we change the script to use the Using scope modifier to indicate that we want to use a local variable from the remote scope, we get code like the following:
$serverArray = "localhost"
$filename = "somefile.txt"
Invoke-Command -ComputerName $ServerArray -ScriptBlock {
$concatenated = [System.IO.Path]::Combine("C:\rootpath", $Using:filename)
Write-Host $concatenated
}
This will yield the output which we want, that is:
C:\rootpath\somefile.txt
So what you need to do is to either pass it as an argument to the Invoke-Command function, using the -ArgumentList parameter, or (since you are using PowerShell v3) indicate that your variable is a local variable and use the Using scope modifier like the examples above.