Creating batch jobs in PowerShell - powershell

Imagine a DOS style .cmd file which is used to launch interdependent windowed applications in the right order.
Example:
1) Launch a server application by calling an exe with parameters.
2) Wait for the server to become initialized (or a fixed amount of time).
3) Launch client application by calling an exe with parameters.
What is the simplest way of accomplishing this kind of batch job in PowerShell?

Remember that PowerShell can access .Net objects. The Start-Sleep as suggested by Blair Conrad can be replaced by a call to WaitForInputIdle of the server process so you know when the server is ready before starting the client.
$sp = get-process server-application
$sp.WaitForInputIdle()
You could also use Process.Start to start the process and have it return the exact Process. Then you don't need the get-process.
$sp = [diagnostics.process]::start("server-application", "params")
$sp.WaitForInputIdle()
$cp = [diagnostics.process]::start("client-application", "params")

#Lars Truijens suggested
Remember that PowerShell can access
.Net objects. The Start-Sleep as
suggested by Blair Conrad can be
replaced by a call to WaitForInputIdle
of the server process so you know when
the server is ready before starting
the client.
This is more elegant than sleeping for a fixed (or supplied via parameter) amount of time. However,
WaitForInputIdle
applies only to processes with a user
interface and, therefore, a message
loop.
so this may not work, depending on the characteristics of launch-server-application. However, as Lars pointed out to me, the question referred to a windowed application (which I missed when I read the question), so his solution is probably best.

To wait 10 seconds between launching the applications, try
launch-server-application serverparam1 serverparam2 ...
Start-Sleep -s 10
launch-client-application clientparam1 clientparam2 clientparam3 ...
If you want to create a script and have the arguments passed in, create a file called runlinkedapps.ps1 (or whatever) with these contents:
launch-server-application $args[0] $args[1]
Start-Sleep -s 10
launch-client-application $args[2] $args[3] $args[4]
Or however you choose to distribute the server and client parameters on the line you use to run runlinkedapps.ps1. If you want, you could even pass in the delay here, instead of hardcoding 10.
Remember, your .ps1 file need to be on your Path, or you'll have to specify its location when you run it. (Oh, and I've assumed that launch-server-application and launch-client-application are on your Path - if not, you'll need to specify the full path to them as well.)

Related

Alternative to Thread. Sleep with different hardware

I am writing a autologin script in Powershell. With main purpose of doing autologon with keystrokes on remote clients in our environment after installation, with the desired AD and password entered.
Works fine on my i9. But most people using Tablets and Elitebooks so using
Thread Sleep
Works bad since i would need to have custom timing on Every hardware, or very high default numbers for lower end clients using my script
Is there any way adding an "wait for row above to completed" Before continuation to next.
I don't have enough on your current code to produce a more accurate answer but the idea, in all cases, remains the same.
You should periodically wake up the thread to check whether or not the machine is in the state you want it in and from there, you either go back to sleep or exit the loop and continue.
The delay is up to you but you want to find a sweet spot to have great performance and reactivity.
Example (based on your description)
$IsLoggedIn = $false
while (! $IsLoggedIn) {
$IsLoggedIn = 'Custom Logic returning $true if the user is logged in'
if ($IsLoggedIn) { break }
Start-Sleep -Milliseconds 100
}
You just need to figure out the thing you want to use as the check to validate the computer is in the correct state you need it in before proceeding further.

Powershell download page in 0 milliseconds

I have a strange problem with my script in powershell, I want to examine the average time of downloading page. I write script which fires frequently. But sometimes my script returns result 0, which means it downloads site in 0 ms. If i modified my script to save whole site to the file when the download time is about 0ms it doesn't saves anything. And I'm interesting if I do something wrong, or powershell function isn't too accurate to count such "small" times.
ps. other "good" results are about 4-9 ms.
Here is a part of my script which responds to count the download time:
$StartTime = Get-Date
$PageDownload = $Request.DownloadString("mypage.com")
$TimeTaken = ((Get-Date) - $StartTime).TotalMilliseconds
Get-Date should be as precise as the system clock is.
There could be web caching going on. Unfortunately, disabling caching for WebClient is not possible, from what I see elsewhere. The "do it right" method is to construct your own Http request with the TcpClient class, but that's also pretty complex.
One easy way to make sure you're not being cached is to put an arbitrary value as a GET request. It's a hack, but it is often enough to fool a cache. So, instead of:
"http://mypage.com"
You use:
"http://mypage.com?someUnusedValueName=$([System.Environment]::TickCount)"

Waiting for an process to quit in PowerShell

Is there a possibility to wait for an process to quit, without it needs to running?
I know there is the keyword WaitForExit, but to use this the process needs to run.
My second question is, if there is a possibility to use an else-Statement in an while loop.
Tried it already, but it always said that there isnt an function called else.
Do Until
Do {
Sleep 5
} Until (Get-Process iexplore);
Will wait until iexplore is found
While
While (Get-Process iexplore) {
Sleep 5
}
Will wait until iexplore is no longer running
Else after while
You cannot use an else statement after a while loop.
It needs to come after an if.
if there is a possibility to use an else-Statement in an while loop.
If you mean something like:
while (cond) {
} else {
}
?
Then NO. (how would the content of the else block be any different to code immediately following the while block?)
Is there a possibility to wait for an process to quit,
Yes. There are different ways of doing this, depending on the nature of the target process. Is it one created by the same script? Is the same session? A service? Or just an arbitrary process?
Does it seems to fits your needs (1st question) ? http://technet.microsoft.com/library/hh849813.aspx
You can use wait-process cmdlet.
Check link for details http://ss64.com/ps/wait-process.html
Example: wait-process -name notepad.exe

Run URL in Background as Service

I'm looking for a way to create a file that runs a specific URL in the background at a specific time. I'll run the service on a timer, and the user won't be logged in. Basically, the server restarts every day, and I want to run a service at 6AM that just goes to a URL (which will automatically complete some tasks). I was thinking batch file or even AHK..but is there a simple way to do this?
My comment:
You just want to open a URL that itself start some tasks? Tried iexplore.exe "your url" as a windows task?
Add:
If this don't work you can just write a small script in vbscript which you fire as task sheduler task.
This script just opens your url:
Dim l_lTimeoutResolve, l_lTimeoutConnect, l_lTimeoutSend, l_lTimeoutReceive, l_sUrl
l_lTimeoutResolve = 5000
l_lTimeoutConnect = 60000
l_lTimeoutSend = 10000
l_lTimeoutReceive = 10000
l_sUrl = "http://yoururl"
'Dim l_sRequestText : l_sRequestText = "stuff you want to send"
Dim l_oXML : Set l_oXML = CreateObject("MSXML2.ServerXMLHTTP")
l_oXML.setTimeouts l_lTimeoutResolve, l_lTimeoutConnect, l_lTimeoutSend, l_lTimeoutReceive
l_oXML.open "POST", l_sUrl, False
l_oXML.setRequestHeader "Content-Type", "text/xml"
' you can post data and als get a result then to write to a logfile e.g.
'l_oXML.send l_sRequestText
'l_sResponseText = l_oXML.responseText
Pro's prolly post that you better do this as powershell .NET script instead, but I never get used to that now. If you want todo coding in .NET instead (vbscript is a bit tricky to setup security on windows 2008 servers) then better write a simple .exe file in .NET that you just start.
Wrap it in a batch file and create a Windows scheduled tasks to execute it?
edit: massive assumption that you are running in windows... but you get the gist

perl: Launch process with system(), then check if its running under a specific display number

I have a locked down "kiosk" terminal server.
This terminal server has a perl script as its .Xsession, and launches a Tk interface. When that Tk interface is done, the perl script launches "process2" and lets the user interact with "process2" (which is a graphical application).
If a user tampers with "process2", and make it crash, the user might be able to access the underlying desktop, therefore I would want to check if "process2" is running, and if "process2" is not running on $display, I would want to just execute logout (which would logout the display the perl script is currently running as).
Since the system is running 10 instances of "process2" to 10 different users simultanuosly, I cant just check if "process2" is running on the system with "ps" or someting like that. I need to check if "process2" is running under that specific display $display.
Note that all 10 users log on as the same username in all sessions, so I cannot check all processes run by a specific user, that would return all 10 instances too.
Like:
system("process2 &");
while(1) {
sleep(1);
if (is_it_running("process2", $display) == false) {
system("logout &");
}
}
Its the function "is_it_running" that I need to get to know how it should look.
$display can either contain the raw display number, like this: ":1.0", or it can contain the display number parsed out, like this: "1".
If you use fork and exec instead of system("...&"), you can store the Process IDs of your child processes and more directly check their status. See also perlipc.
Why not just run process2 in the foreground? Then your perl script won't get control back until it's done executing, at which point it can exit:
system("process2");
system("logout");
Of course, if that's the entire script, maybe a bash script would make more sense.
I solved it after many attempts.
Did a piped open
$pidofcall = open(HANDLE, "process2|");
Then I did whatever I did need to do, and I made the server send a signal to me if it loses connection with process2. If I did need to bang out, I simply did a "goto killprocess;" Then I simply had:
killprocess:
kill(9,$pidofcall);
close(HANDLE);
$mw->destroy;
system("logout");