Get-Content with wait parameter doesn't update in Powershell - powershell

I'm trying to monitor a file using Get-Content $path -wait in Windows Powershell V3.0. Sometimes when I execute this command line in Powershell it will function as expected. But sometimes it will only execute (or at least it seems like) get-content but without the -wait parameter. Even though the file get's updated it won't be shown in Powershell. If I cancel the command and rerun it it will show the updated file content.
What do I need to do?
EDIT: It seems to update blocks after a while. But it's not real-time really.

Not allowed to comment (don't have a 50 reputation), so have to give an Answer....
Less for Windows (http://gnuwin32.sourceforge.net/packages/less.htm) with the +F or Shift-F option (http://www.commandlinefu.com/commands/view/1024/make-less-behave-like-tail-f.) showed updated file content where PowerShell "get-content $path -wait" did not.

Related

2goarray works in cmd but not powershell

I am trying to use 2goarray to write a .ico file to a go file so that I can use it in systray.
My problem is that this works in cmd:
TYPE icon.ico | 2goarray Data icon > icon.go
But running the equivalent command in powershell does not:
Get-Content .\icon.ico | 2goarray Data icon | Out-File -FilePath .\icon.go -Encoding UTF8
When I say it doesn't work, I don't mean an error occurs, I mean that the array produced by 2goarray is not correct, it contains data that systray doesn't recognize as an icon.
For reference, here is the working icon.go, here is the broken/corrupted one produced by powershell, and here is the icon I am using.
I suspect it has something to do with the way that powershell passes things as objects, but I'm not sure?
Your challenge is to pipe binary data in PowerShell, which is not that straight forward. I tested your example with this command and I get the "working" icon.go:
Start-Process 2goarray -ArgumentList "Data icon" -RedirectStandardInput .\icon.ico -RedirectStandardOutput .\icon.go
But this solution seems to be quite slow compared to cmd. From PowerShell you can also always call cmd if you want to, which works surprisingly faster for your example:
Start-Process cmd -ArgumentList "/c TYPE icon.ico | 2goarray Data icon > icon.go"
Often, it is a bad design to call cmd from PowerShell, because PowerShell can nearly do everything that cmd can do, and often more, but for your example, this seems to be the better solution.

Invoking long NAnt process from PowerShell form Jenkins (using Pipelines)

I've been working on wrapping up the usage of some old NAnt scripts behind a Jenkins job. The Jenkins job itself is using the pipelines feature, a groovy DSL script, one of the steps is a PowerShell block, and it calls some a function that invokes NAnt, after working out lots of parameters to be parsed in.
I did have this working at some point just fine, but something has broken at some stage. The PowerShell function is called, and it triggers NAnt, and for the nearly an hour that it takes to complete, you get the output, as it happens, showing up in Jenkins.
This was done using something like Invoke-Expression "& $NAntExe $NAntFile $Target $ParameterString" | Write-Host, where $ParameterString is all the -D:Key=Value parameters.
I believe I had added the | Write-Host as without it, you only get the output at the very end, but we wanted to be able to see the progress as it's happening.
As I said, something has changed somewhere, and we were no longer getting any output from NAnt. I eventually found that removing the | Write-Host would restore the logs, but as I expected, we now have to wait for NAnt to finish before we see any logs.
What is the 'correct' way to invoke NAnt here to get the output as I desire? I want to see the output as it happens.
I've tried various ways of invoking NAnt, with no luck. Seems I'm having to settle for either "I get all the output in one go at the end" or "no output". I suspect this is not a PowerShell issue as such, but that's based on nothing but gut feeling.
Seems I can mostly recreate the symptoms I see in Jenkins. If I invoke NAnt through a fresh PowerShell session I get the same problem, I'm running something akin the following, which as far as I can tell would be the same as how the Jenkins plugin invokes PowerShell:
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command 'Invoke-FunctionThatCallsNAnt'
Within my Invoke-FunctionThatCallsNAnt, I had initially, as I said above, just directly called NAnt and got no logging. I then update my function to pipe the output to Write-Host or I can remove the -NonInteractive flag and I will get the output from NAnt in real time. However, when I go to Jenkins, this does not resolve the problem, I end up with getting no output at all.
I'm not sure why it wouldn't stream. You should be able to write the command these ways:
& $NAntExe $NAntFile $Target $ParameterString
Or with whatever the nant command is.
$env:path += ';c:\program files\nant' # add to path if needed
nant.exe $NAntFile $Target $ParameterString
If it's not in the path, and the folder doesn't have spaces, you can put the whole path to it as well.
c:\nant\nant.exe $NAntFile $Target $ParameterString
EDIT:
Here's a way to run something in a path with spaces:
C:\Program` Files\Internet` Explorer\iexplore.exe
EDIT2:
It looks like you have to unblock the nant zip after downloading it: How do I resolve configuration errors with Nant 0.91?
Or unblock all the files after the fact:
get-childitem -recurse c:\nant-92 |
get-item -stream zone.identifier -erroraction silentlycontinue |
select -expand filename | get-item | unblock-file

How to run powershell script on computer start-up

I am trying to run a PowerShell script Daily.ps1 on start-up, however, due to administrator settings (I cannot run as admin, that is not an option), I cannot run it through the Task Scheduler. For example, this is the contents of Daily.ps1:
if (1 -eq 1) {
"Hello there!"
}
So I tried to have a batch script Daily.cmd run on start up (through the start-up folder), which runs, but I cannot get it run the Daily.ps1, and I get a message saying running scripts is disabled. (Both files are in the same directory)
powershell C:\Users\Simon\Desktop\Daily.ps1
File C:\Users\Simon\Desktop\Daily.ps1 cannot be loaded because running scripts is disabled on this system
I then tried using this line of code from a trick I learned to bypass running scripts directly:
powershell cat Daily.ps1 | powershell invoke-expression
This works but only for one liners. So I added the -raw flag for
cat, which works when in powershell, but not in CMD. For some reason, Daily.ps1's text is still stored as an array of strings. (apologies for formatting)
cmdlet Invoke-Expression at command pipeline position 1
Supply values for the following parameters:
Command: if (1 -eq 1) {
invoke-expression : At line:1 char:14
if (1 -eq 1) {
Missing closing '}' in statement block or type definition.
At line:1 char:1
invoke-expression ~~~~~~~~~~~~~~~~~
So I tried to add this to Daily.cmd:
powershell
cat -raw Daily.ps1 | powershell-invoke-expression
However, the rest of the script doesn't get executed at all once I enter PowerShell.
I don't know to get Daily.ps1 to run through a batch command. Is there a way I missed, or is one of the ways I tried faulty (without admin rights)?
Edit: To clarify, ExecutionPolicy is set to Restricted, and that cannot be changed. Additionally, I can run PowerShell scripts fine through right clicking the file and running with PS.
Create a scheduled task to run at computer startup. Put powershell.exe in the field "program/script" and -File "C:\path\to\your.ps1" in the field "arguments" (you may want to avoid placing the script in a user profile). Set the task to run whether the user is logged on or not.
I found an answer!
After trying many different methods, I came across this line of code that allows you to run PS scripts if ExecutionProperty is set to restricted:
start powershell "cat -raw C:\Users\Simon\Desktop\Daily.ps1 | invoke-expression"
This runs powershell and uses the trick of piping the results of cat -raw [file.ps1] to invoke-expression. This is useful workaround if ExecutionProperty is set to restricted.
Then you can save this line to a .cmd or .bat file and use either Task Scheduler (more customizability) or put it in the startup folder.
P.S. for everyone who kept saying change the ExecutionProperty to something other than restricted. I clearly stated multiple times that I cannot do that(not admin), nor will the Sys Admin do that, nor will it ever happen(must stay restricted) :)

How do I get a Powershell process that was opened by another Powershell process?

I am running multiple PowerShell scripts at once. I would like to be able to wait on certain ones to finish before opening new scripts. Basically, I was thinking if I could find the command line option that ran it something like "powershell.exe -Path "<script dir>" that would do it.
I tried doing a Get-Process | gm to find any parameters that I could call to get that information and I didn't see any (doesn't mean they aren't there) I tried looking through Task Manager to see if I could view something through the gui that I could link to but that didn't help either.
I hope I can get something like
Start-Process -FilePath ".\<script>.ps1" -ArgumentList "<args>"
do
{
sleep 10
}
until ((Get-Process -ProcessName "PowerShell" | where "<paramater>" -EQ ".\<script>")
I need to wait until that process is done but I don't want to put a wait at the end of the Start-Process because after that Start-Process kicks off I need some other items to go to while my .\ is running. I just need it to wait before another section of script kicks off.
Have a look at the "Job" cmdlets https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_jobs?view=powershell-6
And the $PID automatic variable, this will give the process ID of the current PowerShell session.

Running executables in Powershell with complex arguments

I am working on converting an old massive batch file logging script to Powershell. Creating the data has not been a major issue, but I am having an issue with the final step. The final step in the old batch file converts an ugly CSV into a more pretty and easy-on-the-eyes CSV. This is done using an old AWK script and a gawk command. I am content leaving that step in place, but I want it to be executed from within the Powershell script.
The command looks something like this:
<gawk.exe> -f <path>\PrepareReport.awk <original.csv> >> <final.csv>
I have tried different ways of calling gawk and the arguments. Invoke-Expression, Invoke-Command, etc. Nothing seems to work to run this command properly. Any insight or ideas would be appreciated.
Thanks!
EDIT: Following all the comments, I have found the & is the option that works to make this happen. The Start-Process cmdlet causes a fatal error. One weird thing is still happening though. For some reason the resulting CSV file does not display normally in Excel. Even though the resulting file seems to be perfectly normal, Excel won't display it using the appropriate comma breaks. Any thoughts?
You could always use Start-Process.
Start-Process -NoNewWindow -Wait -PassThru -FilePath <gawk.exe> -ArgumentList "-f <path>\PrepareReport.awk <original.csv> >> <final.csv>"
It's a little wordy, but very customisable and very flexible.