Run a jar file from powershell - powershell

I want to run a jar file from powershell. Till now I have been able to find this:
Start-Process -FilePath java -ArgumentList '-jar Upload_Download.jar FilePickupPath= $pickuppath FileDownloadPath= $download' -PassThru -RedirectStandardError E:\stderr.txt
Some how this is not working. Any suggestions?

Powershell has multiple string quotation characters that behave different ways. The double quote " allows evaluations within the string whilst the single quote ' doesn't.
As a practical example:
$foo=42
write-host "The foo: $foo"
# Prints The foo: 42
write-host 'The foo: $foo'
# Prints The foo: $foo
The command uses single quote like so, (backtick is used to split the code into screen friendly format)
Start-Process -FilePath java `
-ArgumentList '-jar Upload_Download.jar FilePickupPath= $pickuppath fileDownloadPath= $download' `
-PassThru -RedirectStandardError E:\stderr.txt
This will pass literally $pickuppath and $download. The intention is likely to pass $pickuppath and $download's values.
In order to resolve the issue, use double quotes.

Passing the arguments is often a problem so I use an array,
also avoid long lines by using parameter splatting.
if(-not $env:JAVA_HOME)
{
Write-Error "JAVA_HOME not set"
break
}
$params = #{
FilePath = [string]::Format("{0}\bin\java.exe",$env:JAVA_HOME)
WorkingDirectory = "D:\SDL\Web\live\discovery\config\"
ArgumentList = #("-jar", "discovery-registration.jar", "update")
RedirectStandardError = "c:\temp\JavaError.txt"
PassThru = $true
Wait = $true
}
$p = Start-Process #params
if($p.ExitCode -eq 0)
{
Write-Output "Discovery Registration complete"
}
else
{
Write-Output "Discovery Registration failed"
}

My problem was a little different because there are two jre versions and one jdk installed and powershell was always picking up jre based java executable and failing with the message
C:\Program Files\Java\jre1.8.0_73 is not a valid JDK Java Home.
Although jdk was installed and JAVA_HOME variable was set and out of variable displays the jdk path correctly.
> $env:JAVA_HOME
C:\Program Files\Java\jdk1.8.0_73
I stored the jdk java executable path in a variable, navigated to the directory containing jar file for Web logic server and invoked the installation program using following code.
$java="C:\Program Files\Java\jdk1.8.0_73\bin\java"
Start-Process -FilePath $java -ArgumentList '-jar fmw_12.2.1.3.0_infrastructure_generic.jar'
The installation program opened after few seconds. I have omitted -RedirectStandardErro switch to keep the command small and simple although i did use it to catch any error in the first place.
I tried using variable $fmw to store the jar file fmw_12.2.1.3.0_infrastructure_generic.jar but it did not work. Unsuccessful code is as follows
$fmw="fmw_12.2.1.3.0_infrastructure_generic.jar"
Start-Process -FilePath $java -ArgumentList '-jar $fmw'
I hope this would help someone and somebody might provide me a better and clean method to call jar files in powershell.

When you run the command after defining the $java variable, make sure to put the full path of the jar in double quotes inside the single quotes. This is to fix the error that occurs when the path of the file has a space in it.
The other option is to cd into the folder with the jar and run the command that way, as suggested in the above answer. This also works and is helpful with simple paths.
Also when defining the java variable, try putting the path to the executable instead of just the folder. This prevents execution conflicts if paths are similar.

Related

MSDEPLOY powershell script parameters does not work

I am trying to deploy a site (basically a zip file) from my machine to a remote machine. I was testing the same before I implement the actual remote deployment and I was working to the msdeploy command line code using powershell.
Later I will configure this code in C# language and execute it that will automate the deployment.
Right now , I am facing the error called
$msdeploy = "C:\\Program Files\\IIS\\Microsoft Web Deploy V3\\msdeploy.exe"
$package = "C:\Deploy\Test\Test.zip"
$compname = "test_vm02"
$appname = "Default Web Site/Test"
$appvalue = "Test\"
$md = $("`"{0}`" -verb:sync -source:package=`"{1}`" -dest=auto,ComputerName=`"{2}`" -setParam=name=`"{3}`",value=`"{4}`" -allowUntrusted" -f $msdeploy, $package, $compname, $appname, $appvalue)
cmd.exe /C $md
This gives error saying that source does not support the parameter 'Default Web Site/Test'.Must be one of ()
I also replaced the default web site to IIS Web Application Name which in this case also did not work and threw the same error.
Any help is much appreciated!!
PowerShell's handling of quotes in arguments passed to external programs is fundamentally broken, but things get more complicated if there's another level of quoting involved, as in your indirect call to msdeploy.exe via cmd.exe.
There is usually no reason to call external programs via cmd /c; instead, call them directly from PowerShell, which, if the program name is quoted or given via a variable, requires prepending the command line with &, the call operator:
Note: The line-ending ` chars. are line continuations, used for readability only; ignore the broken syntax highlighting.
$package = 'C:\Deploy\Test\Test.zip'
$compname = 'test_vm02'
$appname = 'Default Web Site/Test'
# !! If a value ends in '\' you must *double* the '\' if the value
# !! ends up just before a " in the ultimate command line.
$appvalue = 'Test\\'
& "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" `
-verb:sync `
-source:package=`"$package`" `
`-dest=auto,ComputerName=`"$compname`" `
`-setParam=name=`"$appname`",value=`"$appValue`" `
-allowUntrusted
Note the need to `-escape the - before the -dest and -setParam options, which is a workaround for the bug described in this GitHub issue.
Leaving the parameter names (e.g. -source:package) otherwise unquoted and enclosing their arguments in explicit, embedded quotes (`") ensures that the whole token is passed through looking something like -source:package="C:\Deploy\Test\Test.zip", which some programs, notably msiexec.exe and possibly also msdeploy.exe, require.
Caveat: If PowerShell's broken (re)quoting of arguments passed to external programs (see this answer) should ever get fixed (see this GitHub issue), this technique will break.
If you just used -source:package=$package and the value of $package contained embedded spaces, PowerShell would double-quote the whole token behind the scenes and pass something like
"-source:package=C:\Deploy 1\Test\Test.zip"
Programs such as msiexec.exe and msdeploy.exe should recognize this quoting style too, but unfortunately don't.

Powershell Quotes Use asisstance

Need some expert help from you guru's out there (after 3 days of trying on my own lol). Here the portion of my script that's failing:
$yy=(get-date).Year
Invoke-Command -ComputerName *ipaddress* -Credential $moveitcred {
move-item -path "C:\iCApps\Dev\LetterGenerator\Letters\FTS\EDMS\*.txt" -destination "C:\Moveitft\Dev\Letters\Outbound" -force
Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList "a -y C:\Moveitft\Dev\Letters\archive\Letters$yy_.zip C:\Moveitft\Dev\Letters\Outbound\*.*"
}
The move works fine. AND the zip works fine, except when I want to include the the year varible ($yy) in the argument list. Powershell doesn't want to populate the variable to adjust the file name. Either it bombs out citing a $null, or the job completes with just a blank where the $yy should be.
If i run just $yy from the prompt, it does return the correct year value, so I'm guessing it an improper use of quotes. But after 3 days of googling and trying various combinations on my own, I'm throwing in the towel. Any help/guidance would be so GREATLY appreciated :)
Change Letters$yy_.zip to either
Letters$($yy)_.zip
or
Letters${yy}_.zip.
Both of them work.
See: PowerShell subexpression and PowerShell variable names.
The problem is not about quoting is about variable scope. Inside the scriptblock you are executing, powershell knows nothing about the $yy var. So you need to tell it where to obtain the value. You could do that using the argumentList parameter. I see that you already are doing that but you are doing it wrong (move-item doesn't support that parameter). Look the following examples to grasp the concept, I think with that you will solve your problem:
# this is fine and simple
$yy="Hello scriptblocks!"
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $yy" } -ArgumentList $yy
# this is incorrect
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $yyCarefulWithThisText" } -ArgumentList $yy
# this shows how you could resolve the variable when you want to put text around
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $($yy)CarefulWithThisText" } -ArgumentList $yy
# output1: whatever you want to run that use the an external var. Hello scriptblocks!
# output2: whatever you want to run that use the an external var.
# output3: whatever you want to run that use the an external var. Hello scriptblocks!CarefulWithThisText
Tried the above, thank you! I think this might boil down to powershell version. I'm trying to execute this on a server running powershell v2.0, against another 2012 Server.
I've shortened down the code to just the line in question (so I can "F8" it to test the results) Here it is:
Invoke-Command -ComputerName ipaddress -Credential $moveitcred {
Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -argumentlist "a -y C:\Moveitft\Dev\Letters\archive\Letters${yy}.zip C:\Moveitft\Dev\Letters\Outbound*.*"
}
Both of your suggestions "work", in that the command processes, however its still not reading the variable correctly. Here's what I get as a resultant .zip
The reason I'm thinking its powershell, is becuase if I copy/paste the same command into powershell v4.0 on my own production machine, you can instantly see by the color coding that the "$yy" is being considered a variable because it turns red - and then the code works ok on from my PS4.0 machine.
On the PSv2.0 server i'm trying to get this to run from, that same line for "-argumentlist" appears all maroon/brown - including the $yy portion. So its kind of a hint whether it will work or not for me.

Spaces cause split in path with PowerShell

I'm having an issue with powershell when invoking an exe at a path containing spaces.
PS C:\Windows Services> invoke-expression "C:\Windows Services\MyService.exe"
The term 'C:\Windows' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
It seems to be splitting on the space between 'Windows' and 'Services'. Any idea how to get around this problem?
Would this do what you want?:
& "C:\Windows Services\MyService.exe"
Use &, the call operator, to invoke commands whose names or paths are stored in quoted strings and/or are referenced via variables, as in the accepted answer. Invoke-Expression is not only the wrong tool to use in this particular case, it should generally be avoided.
You can escape the space by using single quotations and a backtick before the space:
$path = 'C:\Windows Services\MyService.exe'
$path -replace ' ', '` '
invoke-expression $path
Not sure if someone still needs it... I needed to invoke msbuild in powershell and following worked fine:
$MSBuild = "${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe"
& $MSBuild $PathToSolution /p:OutDir=$OutDirVar /t:Rebuild /p:Configuration=Release
"&'C:\Windows Services\MyService.exe'" | Invoke-Expression
via https://www.vistax64.com/powershell/52905-invoke-expression-exe-has-spaces-its-path.html
For any file path with space, simply put them in double quotations will work in Windows Powershell. For example, if you want to go to Program Files directory, instead of use
PS C:\> cd Program Files
which will induce error, simply use the following will solve the problem:
PS C:\> cd "Program Files"
This worked for me:
$scanresults = Invoke-Expression "& 'C:\Program Files (x86)\Nmap\nmap.exe' -vv -sn 192.168.1.1-150 --open"
Using Powershell on Windows10 in 2018, what worked for me was simply to replace double quotes " by simple quotes '. Adding the backtick before the space, as suggested in an answer, broke the path.
What worked for me (I needed the path to create a MySQL dump), was to place the directory in between 6 double quotes like so:
$path = """C:\Path\To\File"""
Can use the . dot operator.
. "C:\Users\user\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd"
or the Start-Process command
Start-Process -PSPath "C:\Users\user\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd"
or using ProcessStartInfo and Process
$ProcessInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$ProcessInfo.FileName = 'C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe'
if($Admin){ $ProcessInfo.Verb = 'runas' }
$ProcessInfo.UseShellExecute = $false
$CommandParameters = '-noexit -noprofile -command Set-Location -LiteralPath c:\; $host.ui.RawUI.WindowTitle = ''[{0}] PS''; Set-PSReadlineOption -HistorySaveStyle SaveNothing;' -f $Cred.UserName
$ProcessInfo.Arguments = $CommandParameters
$ProcessInfo.Domain = ($Cred.UserName -split '\\')[0]
$ProcessInfo.UserName = ($Cred.UserName -split '\\')[1]
$ProcessInfo.Password = $Cred.Password
$ProcessObject = New-Object -TypeName System.Diagnostics.Process
$ProcessObject.StartInfo = $ProcessInfo
$ProcessObject.Start() | Out-Null
There's a hack I've used since the Invoke-Expression works fine for me.
You could set the current location to the path with spaces, invoke the expression, get back to your previous location and continue:
$currLocation = Get-Location
Set-Location = "C:\Windows Services\"
Invoke-Expression ".\MyService.exe"
Set-Location $currLocation
This will only work if the exe doesn't have any spaces in its name.
Hope this helps
Please use this simple one liner:
Invoke-Expression "C:\'Program Files (x86)\Microsoft Office\root\Office16'\EXCEL.EXE"
Try this, simple and without much change:
invoke-expression "'C:\Windows Services\MyService.exe'"
using single quotations at the beginning and end of the path.
Due to several PowerShell quoting rules that are used for passing arguments to native commands which also have specific experimental Features in PowerShell, quoting might get very confusing. Therefore the solution in some cases might be simply to don't go down the rabbit hole:
Avoid quoting file paths with spaces by using the 8.3 filenames
$FSO = New-Object -ComObject Scripting.FileSystemObject
$FSO.getfile('C:\Windows Services\MyService.exe').ShortPath
C:\WINDOW~1\MYSERV~1.EXE
Just put ${yourpathtofile/folder}
PowerShell does not count spaces; to tell PowerShell to consider the whole path including spaces, add your path in between ${ & }.
Simply put the path in double quotes in front of cd, Like this:
cd "C:\Users\MyComputer\Documents\Visual Studio 2019\Projects"
enter the root C drive by entering command
C:
type cd and then press Tab key, it will toggle through all available locations and press enter when you have reached the desired one
cd {press tab}

Passing environment variables to a process in PowerShell 2.0 when the variable is changed multiple times

I'm having some issue when it comes to passing the corresponding environment variables to a process. Below you can see part of my code so that you can understand what I'm trying to do.
I have two EXE files that I need to run. The processes run some updates based on the location of the Environment variable %MainFiles%. When I run the code it seems the EXE files do not recognize the change. However, when i look under the Computer properties I do see that the variables are changed correctly.
Does anyone know how could I force the process to recognize the change?
Thanks
while ($i -lt $Size) {
if ($TempEnv[$i] -eq "Done"){
$ExitCode="Completed"
return
} else {
$Temp = $TempEnv[$i]
Write-Host ("Starting Update for " + $Temp) -foregroundcolor "Green"
[System.Environment]::SetEnvironmentVariable("MainFiles", "$Temp","Machine")
[System.Environment]::GetEnvironmentVariable("MainFiles","Machine")
Copy-Item $CopyInstallData -destination $Temp
$process = Start-Process XMLUpgrade.exe -WorkingDirectory "C:\Program Files\Dtm" -wait
$process = Start-Process Update.exe -WorkingDirectory "C:\Program Files\Dtm" -wait
.
.
.
This line makes the env var change permanent:
[System.Environment]::SetEnvironmentVariable("MainFiles", "$Temp","Machine")
Unfortunately PowerShell has already launched before you set this. Its env block is snapshotted at launch time. That environment is what the two spawned processes inherit.
To get the two processes to launch with the correct environment variable value do this first:
$env:MainFiles = $Temp

Use variable for filepath parameter of Start-Process

I'd like run a .exe which could be in a number of locations.
$runpath = "$servicepackfolder\SQLServer2008SP1-KB968369-IA64-ENU.exe"
Start-Process -FilePath $runpath -arg "/x:.\$buildfolder\PCU"
Or this way, specifying the WorkingDirectory:
Start-Process 'SQLServer2008SP1-KB968369-IA64-ENU.exe' -WorkingDirectory $servicepackfolder -arg "/x:.\$buildfolder\PCU"
But it seems the variables are not being interpreted as strings.
Start-Process : This command cannot be
executed due to the error: The system
cannot find the file specified.
I am in the correct directory and if I take the output from the $runpath variable and substitute it for the variable in the Start-Process call, I get the expected behavior.
Will this work, or am I stuck hardcoding these paths. Trying to automate the slipstream build process for SQL 2008.
I can duplicate the behavior you see if I add -NoNewWindow but if I don't specify that parameter it works as expected for my test case:
start-process sizeof.exe -WorkingDirectory C:\temp -ArgumentList 1
The new window flashes up and goes away but I can see it is running the specified exe from my temp dir.
Better late than never, but I've found a workaround for this when having the same issue, not sure if it is classed as a bug or not -
Powershell doesn't always handle un-escaped backslashes or quotes in the strings that are stored in a variable / created by string processing all that well for -FilePath, so for your line:
$runpath = "$servicepackfolder\SQLServer2008SP1-KB968369-IA64-ENU.exe"
Try the following (or equivalent) before using $runpath:
$cleanpath = $runpath.replace("\","\\").replace('"',"")
The .replace("\","\\").replace('"',"") escapes the slashes and eliminates the quotes that the string handling and passing introduce, which seems to clear this issue (for some cases).
Bit late for you I imagine but hopefully this helps other people googling for this one.