I can assure you that `Get-Content -Wait` does refresh every second, and shows you changes when the file changes on the disk. I'm not sure what `tail -f` is doing differently, but based on your description I'm just about certain that this issue is not with PowerShell but with write caching. I can't rule out the possibility that log4net is doing the caching, but I strongly suspect that OS-level caching is the culprit, for two reasons:
1. The documentation for log4j/log4net says that it flushes the buffer after every append operation by default, and I presume that if you had explicitly configured it not to flush after every append, you'd be aware of that.
2. I know for a fact that refreshing Windows Explorer triggers a write buffer flush if any files in the directory have changed. That's because it actually reads the file contents, not just the metadata, in order to provide extended information such as thumbnails and previews, and the read operation causes the write buffer to flush. So, if you're seeing the delayed updates every time you refresh the logfile's directory in Windows Explorer, that points strongly in this direction.
Try this: Open Device Manager, expand the **Disk Drives** node, open the Properties of the disk on which the logfile is stored, switch to the **Policies** tab, and uncheck **Enable write caching on the device**. I think you'll find that `Get-Content -Wait` will now show you the changes as they happen.
As for why `tail -f` is showing you the changes immediately as it is, I can only speculate. Maybe you're using it to monitor a logfile on a different drive, or perhaps Cygwin requests frequent flushes while you're running `tail -f`, to address this very issue.
----------
<!-- language-all: lang-powershell -->
**UPDATE:**
Duncan commented below that it is an issue with PowerShell, and posted an answer contending that `Get-Content -Wait` doesn't output new results until the file is closed, contrary to the documentation.
However, based on information already established and further testing, I've confirmed conclusively that it does *not* wait for the file to be closed, but outputs new data added to the file as soon as it's written to disk, and that the issue the OP is seeing is almost definitely due to write buffering.
To prove this, let the facts be submitted to a candid world:
- I created an Excel spreadsheet, and ran `Get-Content -Wait` against the .xlsx file. When I entered new data into the spreadsheet, the `Get-Content -Wait` did not produce new output, which is expected while the new information is only in RAM and not on disk. However, whenever I saved the spreadsheet after adding data, new output was produced immediately.
Excel does *not* close the file when you save it. The file remains open until you close the Window from Excel, or exit Excel. You can verify this by trying to delete, rename, or otherwise modify the .xlsx file after you've saved it, while the window is still open in Excel.
- The OP stated that he gets new output when he refreshes the folder in Windows Explorer. Refreshing the folder listing does not close the file. It *does* flush the write buffer if any of the files have changed. That's because it has to read the file's attributes, and this operation flushes the write buffer. I'll try to find some references for this, but as I noted above, I know for a fact that this is true.
- I verified this behavior by running the following modified version of Duncan's test, which runs for 1,000 iterations instead of 50, and displays progress at the console so that you can track exactly how the output in your `Get-Content -Wait` window relates to the data that the pipeline has added to the file:
1..1000 | %{"${_}: Write $(Get-Date -Format "hh:mm:ss")"; Write-Host -NoNewline "$_..."; Start-Sleep 1} > .\gcwtest.txt
While this was running, I ran `Get-Content -Wait .\gcwtest.txt` in another window, and opened the directory in Windows Explorer. I found that if I refresh, more output is produced any time the file size in KB changes, and *sometimes* but not always even if nothing visible has changed. (More on the implications of that inconsistency later...)
- Using the same test, I opened a third PowerShell window, and observed that all of the following trigger an immediate update in the `Get-Content -Wait` listing:
- Listing the file's contents with plain old `Get-Content .\gcwtest.txt`
- Reading any of the file's attributes. However, for attributes that don't change, only the first read triggers an update.
For example, `(gi .\gcwtest.txt).lastwritetime` triggers more output multiple times. On the other hand, `(gi .\gcwtest.txt).mode` or `(gi .\gcwtest.txt).directory` trigger more output the first time each, but not if you repeat them. Also note the following:
**&raquo;&nbsp;&nbsp;** This behavior is not 100% consistent. Sometimes, reading **Mode** or **Directory** doesn't trigger more output the first time, but it does if you repeat the operation. All subsequent repetitions after the first one that triggers updated output have no effect.
**&raquo;&nbsp;&nbsp;** If you repeat the test, reading attributes that are the same does not trigger output, *unless* you delete the .txt file before running the pipeline again. In fact, sometimes even `(gi .\gcwtest.txt).lastwritetime` doesn't trigger more output if you repeat the test without deleting **gcwtest.txt**.
**&raquo;&nbsp;&nbsp;** If you issue `(gi .\gcwtest.txt).lastwritetime` multiple times in one second, only the first one triggers output, i.e. only when the result has changed.
- Opening the file in a text editor. If you use an editor that keeps the file handle open (notepad does not), you'll see that closing the file without saving does not cause `Get-Content -Wait` to output the lines added by the pipeline since you opened the file in the editor.
- Tab-completing the file's name
</ul></ul>
- After you try any of the tests above a few times, you many find that `Get-Content -Wait` outputs more lines periodically for the remainder of the pipeline's execution, even if you don't do anything. Not one line at a time, but in batches.
- The inconsistency in behavior itself points to buffer flushing, which occurs according to variable criteria that are hard to predict, as opposed to closing, which occurs under clear-cut and consistent circumstances.
</ul>
**Conclusion:** `Get-Content -Wait` works exactly as advertised. New content is displayed as soon as it's *physically* written to the file on disk<sup>*</sup>.
It should be noted that my suggestion to disable write caching on the drive did *not* for the test above, i.e. it did not result in `Get-Content -Wait displaying new lines as soon as they're added to the text file by the pipeline, so perhaps the buffering responsible for the output latency is occurring on a filesystem or OS level as opposed to the disk's write cache. However, write buffering is clearly the explanation for the behavior observed in the OP's question.
<sub>* I'm not going to get into this in detail, since it's out of the scope of the question, but `Get-Content -Wait` does behave oddly if you add content to the file not at the end. It displays data from the end of the file equal in size to the amount of data added. The newly displayed data generally repeats data that was previously displayed, and may or may not include any of the new data, depending on whether the size of the new data exceeds the size of the data that follows it.</sub>