Powershell script only works in ISE - shell

DESCRIPTION
So I have this script, where I login to remote machine using OpenSSH in powershell script. It creates the session and executes ~Run_Project.sh and logs to the log file in the linux machine > ~/project_log&.
function StartSSHsessionAndRunProject
{
try
{
ssh.exe -i ~/id_rsa-private remoteLinuxMachine#admin '~/Run_Project.sh > ~/project_log&'
if ($?)
{
Write-Host "SSH session has been created...`n" -ForegroundColor Green
}
else
{
throw $error[0].Exception
}
}
}
EXPECTATION
As you can see I have '&' symbol at the end of the > ~/project_log& command. It supposed to return to the if statement.
PROBLEM:
This script works fine and as expected in Powershell ISE. However, when I debug or run this powershell script in another tool like Visual Studio Code, Run As Admin in Powershell command DOESN'T work. Anything before this function works fine, the script just pauses and looks like it freezes in ssh.exe line. However, it actually runs the project and the project log says it has started. Any ideas?

Related

Starting a background process on Windows through an SSH connection that doesn't get stopped when SSH disconnects

I have a java application that I'm trying to deploy to a Windows server via SSH (via Jenkins). I wrote a powershell script to start the process in the background using start-process and javaw:
$SSL_KEYSTORE_PASSWORD = $args[0]
Write-Output "Running war in the background"
Start-Process javaw -ArgumentList "-jar", `
"e:\app\app.war", `
$("-Dserver.ssl.key-store-password=" + $SSL_KEYSTORE_PASSWORD), `
"-Dserver.tomcat.basedir=e:\app" `
-RedirectStandardOutput "e:\app\output\stdout.txt" `
-RedirectStandardError "e:\app\output\stderr.txt"
Write-Output "Starting javaw instance"
When I run the script from the server, it works perfectly: the process runs in the background indefinitely and all the output goes to the right place. But, when I attempt to run it via SSH from jenkins, the java application will start up properly, but as soon as the powershell script ends, the process gets killed. Initially, I thought it was jenkins killing the process, but I did some debugging and figured out that it's getting killed as soon as it exits the powershell script, so I think it's related to SSH. This is the line in the jenkinsfile that's attempting to start up the process:
sh 'ssh -o StrictHostKeyChecking=no $ssh_target powershell e:\\app\\startup $SSL_KEYSTORE_PASSWORD'
I would like to start the process using a powershell script like this, because once I get this working, I'd like to add some other stuff into the powershell script to make sure it started up properly, and I don't want to clutter up the jenkinsfile even more than it already is.

powershell running as windows service giving incomplete output

I want to run a powershell script as windows service. The script is pretty huge and takes a while to run.
I am redirecting the output of this script as text using start-stop transcript in powershell script. When the script is ran through windows service output is not complete. Its giving me half the output.
I have created service using :
"C:\path\to\instsrv.exe" myservice "C:\path\to\srvany.exe" then giving
C:\path\to\powershell.exe -noprofile -File "C:\path\to\myscript.ps1" in Application in registry.
While running script through powershell console, transcript redirects full output to a file but not through service.
Any help will be much appreciated.

How to make powershell tell me about missing DLLs?

I use powershell as shell in Windows. When I'm trying to launch some application who's dll dependencies are missing in PATH environment variable, then nothing happens, powershell just silently returns with new command prompt.
Is there a way to make powershell fail louder, telling me what exactly is missing, like default cmd shell does?
I was having this same problem. PowerShell was setting $LASTEXITCODE code to -1073741515 (0xC0000142, 3221225794) but no output explaining what was actually wrong. When running it via cmd.exe I would get popup with something like:
The code execution cannot proceed because some.dll was not found. Reinstalling the program may fix this problem.
cygwin bash outputs errors relating to dll not found to stderr and if you run the the same via bash from PowerShell then you can see the error:
> & 'C:\tools\cygwin\bin\bash.exe' '-c' '"C:/Users/xxx/dir/main.exe"'
C:/Users/xxx/dir/main.exe: error while loading shared libraries: another.dll: cannot open shared object file: No such file or directory
This works with git bash also:
> & 'C:\Program Files\Git\bin\bash.exe' '-c' '"C:/Users/xxx/dir/main.exe"'
C:/Users/xxx/dir/main.exe: error while loading shared libraries: another.dll: cannot open shared object file: No such file or directory
Quite a hack but better than nothing.
You could echo the %ERROR% variable, which stores errors until the PowerShell window is closed.
Update: In PowerShell, you could use the Get-Error command, or look at the $Error variable.
Another way would be to use Dependancy walker, if you can use a command line option, then you should be able to use this in PowerShell.
I am afraid there is no way to get that info... But try to read
An Introduction to Error Handling in PowerShell http://blogs.msdn.com/b/kebab/archive/2013/06/09/an-introduction-to-error-handling-in-powershell.aspx
or
PowerShell Tutorial – Try Catch Finally and error handling in PowerShell
http://www.vexasoft.com/blogs/powershell/7255220-powershell-tutorial-try-catch-finally-and-error-handling-in-powershell
Try
{
$AuthorizedUsers = Get-Content \\ FileServer\HRShare\UserList.txt -ErrorAction Stop
}
Catch [System.OutOfMemoryException]
{
Restart-Computer localhost
}
Catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Send-MailMessage -From ExpensesBot#MyCompany.Com -To WinAdmin#MyCompany.Com -Subject "HR File Read Failed!" -SmtpServer EXCH01.AD.MyCompany.Com -Body "We failed to read file $FailedItem. The error message was $ErrorMessage"
Break
}
Finally
{
$Time=Get-Date
"This script made a read attempt at $Time" | out-file c:\logs\ExpensesScript.log -append
}

Powershell Tracing and Control-M

I seem to have run into a problem/bug when trying to capture tracing output when running a Powershell script from Control-M.
The output file shows the headers and footers of the start-trace and stop-trace commands, but it does not show anything else I try to capture. Specifically, if my script issues a write-host command somewhere, then that information is not captured in the output (trace) file.
Here is a super simple script that illustraes my problem:
start-transcript -path "C:\Powershell\transcript.log"
write-host "test message"
#do stuff...
stop-transcript
Here is an example of my current output when running the script through Control-M:
**********************
Windows PowerShell Transcript Start
Start time: 20140212002005
Username : mydomain\SYSTEM
Machine : myserver (Microsoft Windows NT 6.1.7601 Service Pack 1)
**********************
**********************
Windows PowerShell Transcript End
End time: 20140212002008
**********************
Note that my test message does not show up! This only happens when I run the script via Control-M. When I run my script manually, my "test message" does show up in the transcript output.
My first suspicion was file permissions, but those look good to me. The Control-M agent uses system level access, so it should have all the permissions it needs anyway. If it were a file permission issue, I don't believe i would even get the header/footer messages.
I'm on PS v2.0. My server is running 2008r2.
Any thoughts appreciated...
Write-Host writes to to the console window, which is not what's being "watched" by Control-M. Try Write-Output instead. Write-Host is usually not what you want for producing output.
See http://windowsitpro.com/blog/what-do-not-do-powershell-part-1 and http://powershell.com/cs/blogs/donjones/archive/2012/04/06/2012-scripting-games-commentary-stop-using-write-host.aspx

Is there a way to make powershell wait for an install to finish?

I have a list of Windows packages that I'm installing via powershell using the following command:
& mypatch.exe /passive /norestart
mypatch.exe is being passed from a list and it doesn't wait for the prior install to finish - it just keeps going. It builds up a huge window of installs that are pending installation. Also, I can't use $LASTEXITCODE to determine if the install succeeded or failed.
Is there anyway to make the installs wait before starting the next?
Start-Process <path to exe> -Wait
JesnG is correct in using start-process,
however as the question showed passing arguments, the line should be:
Start-Process "mypatch.exe" -argumentlist "/passive /norestart" -wait
The OP also mentioned determining if the install succeeded or failed. I find that using a "try, catch throw" to pick up on error states works well in this scenario
try {
Start-Process "mypatch.exe" -argumentlist "/passive /norestart" -wait
} catch {
# Catch will pick up any non zero error code returned
# You can do anything you like in this block to deal with the error, examples below:
# $_ returns the error details
# This will just write the error
Write-Host "mypatch.exe returned the following error $_"
# If you want to pass the error upwards as a system error and abort your powershell script or function
Throw "Aborted mypatch.exe returned $_"
}
Sure, write a one line batch script that runs the installer. The batch script will wait for the installer to finish before returning. Call the script from PowerShell which will in turn wait for the batch script to finish.
If you have access to how mypatch is written, you could have that create some random file when it completes that PowerShell can check for its existence in a while loop and just sleeps while the file doesn't exist.
If you don't, you could also have that batch script create a dummy file when the installer completes.
Yet another way, though probably the worst of all of these is to just hard-code a sleep timer (start-sleep) once you call the installer.
EDIT just saw JensG's answer. Didn't know about that one. Nice

Resources