I'm a little stuck on the documentation for the Firewall cmdlets in Windows server. I am trying to copy the address lists for the remote and local ips from one rule to another. I can get the list using

Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter

Now I was trying to set this for another rule like this:

Set-NetFirewallAddressFilter -DisplayName "FTP Server (FTP Traffic-In)" | Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter

This is obviously wrong, as I immediately get an error saying that Set-NetFirewallAddressFilter does not have a parameter ´Displayname´

When I use Set-NetFirewallRule instead it does, but there I cannot use a complete object but only Local and Remote Addresses seperately. Could you help, please?


I have now tried running something like this:

Set-NetFirewallRule -DisplayName "Test" -RemoteAddress | 
    Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter | ft Remote

That doesn't work: Set-NetFirewallRule : The address is invalid. Addresses may be specified as IP addresses, ranges, or subnets.

Stuck again...

  • Have you tried using the Get-Help cmdlet? – BlueCompute Jul 13 '16 at 11:33
  • No, I didn't - I used the online help at technet though. I've just checked the cmdlet, and with the only difference being the readability on screen, the result is unfortunately the same - a bit confusing. Also I was certain I had seen an answer earlier which appears to have disapperead. That's now even more confusing, but I get used to being left in that state. – ExternalUse Jul 13 '16 at 20:01
  • This might be difficult to achieve with piping on a one-liner. Does it work if you do it over two lines, first putting the value in a variable and then using that to set the new rule? – Matt Jul 14 '16 at 0:13
  • Point was that both get-help and the online technet help tells you what parameters are valid for a given cmdlet. You can't just pick parameters from a similar cmdlet and hope they work for a different one – BlueCompute Jul 14 '16 at 11:06

What you need to do is:

  • Get the original rule by name
  • Get the address filter out of it
  • Get the new rule by name
  • Set the address filter in it

And yes, you can merge a lot of those into a one-liner, but for example I think this will do it:

$sourceRule = Get-NetFirewallRule -DisplayName "MSSQL"
$sourceIPs = $sourceRule | Get-NetFirewallAddressFilter

Set-NetFirewallRule -DisplayName "Test" -RemoteAddress $sourceIPs.RemoteAddress -LocalAddress $sourceIPs.LocalAddress

(and if you have the Windows Firewall with Advanced Security GUI open, refresh it).

but there I cannot use a complete object but only Local and Remote Addresses seperately

I can't see any way around that if it needs them separately. Splatting might make it possible, but that would be a lot more code for effectively the same result. If it really has to be one line (why?) you can do both together with something like:

Set-NetFirewallRule -DisplayName "Test" -RemoteAddress ($ip = Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter).RemoteAddress -LocalAddress $ip.LocalAddress

Your two pipelines both have some really misunderstood bits in them. The first one:

Set-NetFirewallAddressFilter -DisplayName "FTP Server (FTP Traffic-In)" | 
Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter
  • Tries to set an address filter by DisplayName - they don't have a display name, filters are tied to FirewallRules.
  • The Set- commandlets don't often return any output, but you pipe as if it would have
  • The piped imaginary output goes into Get-ing the original firewall rule, which is just going to do weird things. It might ignore any pipeline input, or might crash based on it. Either way...
  • The two Get- cmdlets would work together to get addresses, but they just output to the screen and would not change anything.

The second updated one:

Set-NetFirewallRule -DisplayName "Test" -RemoteAddress | 
    Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter | ft Remote
  • Is a Set- at the start and gets as far as the RemoteAddres parameter, but then switches (ouch!) to a pipeline, to pipe what ?? into Get-NetFirewallRule (same caveat as before)
  • then gets the addressfilter for the rule, and pipes to Format-Table(!) which is a display cmdlet for interactive console use only.

It's allllmost right - at a glance it has the look of a PowerShell one-liner, but it's really really broken.

  • You don't tend to pipeline output from Set- cmdlets.
  • You can't connect a pipeline into the middle of writing a parameter value
  • You oughtn't send data through Format-List or Format-Table, and plan to use the output as input to another cmdlet - they will happily add spaces, tabs, display names, throw data away, and generally mash things up to make it look nice on screen
  • You chain Get-s together but don't use the output.


But it's so close, it would look like:

Set-NetFirewallRule -DisplayName "Test" -RemoteAddress (Get-NetFirewallRule -DisplayName "MSSQL" | Get-NetFirewallAddressFilter).RemoteAddress

Encapsulating the Get- sub-pipeline in parens () so you can use the output of it, taking the .RemoteAddress property, and using that as the value for the -RemoteAddress parameter to Set-NetFirewallRule.

  • 1
    Thank you for this excellent answer. I especially appreciate the time you took to point out what I did when I thought I was doing something else, this is highly valuable not only for the task at hand but will help me greatly with Powershell itself! Again, many thanks! – ExternalUse Jul 14 '16 at 12:16

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.