How to condense PowerShell script to fit on a single line - windows

Quick question. I am trying to write the following PowerShell script, but I would like it to fit on a single line:
$app = New-Object -comobject Excel.Application
$wb1 = $app.Workbooks.Open("C:\xampp\upload_files\Launchpad.xlsm")
$app.Run("Refresh")
$wb1.Close($false)
$app.Quit()
The pseudo-code would look something like this:
$app = New-Object -comobject Excel.Application AND $wb1 = $app.Workbooks.Open AND "C:\xampp\upload_files\Launchpad.xlsm") AND $app.Run("Refresh") AND $wb1.Close($false) AND $app.Quit()
The reason I want to fit on a line is because I would like to insert the arguments directly in the 'arguments' box of Windows Task Scheduler. The reason for this is that for some reason scripts have been disabled (e.g. I cannot call a .ps1 file...)
I know this will still work, as I already have a "one liner" PS script running. What would the syntax look like??
Kind regards,
G.

Powershell statements can be separated with semicolons:
$app = New-Object -COM 'Excel.Application'; $wb1 = $app.Workbooks.Open("..."); ...
The PowerShell executable takes a -Command parameter that allows you to specify a command string for execution in PowerShell:
powershell.exe -Command "stmnt1; stmnt2; ..."
To run this via Task Scheduler you'd put powershell.exe into the "program" field and -Command "stmnt1; stmnt2; ..." into the "arguments" field of the task.
However, as #alroc said: you should verify why script execution has been restricted. If it's just the default setting you can simply change it by running Set-ExecutionPolicy RemoteSigned or override it by adding -ExecutionPolicy ByPass to a PowerShell command line. However, if the setting is enforced by policy changing/bypassing the setting will fail, and you could get into quite some trouble for violating company policies.

Here is a solution that you might use if the script is not that easy to convert, but you are on Windows running at least PowerShell V5.
It converts the code into Base64 and uses PowerShell.exe with the parameter -encodedCommand to pass the encodedCommand as string.
$command = Get-Content .\YourPowerShellFileContainingTheCode.ps1 -raw
# Get-Content may require "-encoding utf8" or other encodings depending on your file
$encodedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($command))
Write-Output "Text for application:"
Write-Output "PowerShell.exe" ""
Write-Output "Text for argurments:"
Write-Output "-encodedCommand $encodedCommand"
It would look like this, but with a much larger command:
Text for application:
PowerShell.exe
Text for argurments:
-encodedCommand SABvACAASABvACAASABvACwAIABzAHQAYQBjAGsAbwB2AGUAcgBmAGwAbwB3AA==

Related

Use PowerShell to create a shortcut to launch a PowerShell script

I have a need to create a shortcut on a Windows 2019 Server for the Eclipse application so that it runs a PowerShell script instead of opening Eclipse. The script runs a few commands first and then opens the Eclipse application. When I edit an existing shortcut for Eclipse, I can modify the target to be:
"powershell.exe -ExecutionPolicy bypass C:\temp\eclipse-fix.ps1 -WindowStyle Hidden"
This works fine when completed manually. However, when I try to do the same with a PowerShell script, to automate the process, I get an error.
Contents of the script:
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("C:\Users\Administrator\Desktop\Eclipse.lnk")
$Shortcut.TargetPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy bypass C:\cfn\temp\eclipse-fix.ps1 -WindowStyle Hidden"
$Shortcut.IconLocation = "%SystemDrive%\eclipse\eclipse.exe"
$Shortcut.Save()
Error Returned:
PS C:\Users\Administrator> $WshShell = New-Object -comObject WScript.Shell
PS C:\Users\Administrator> $Shortcut = $WshShell.CreateShortcut("C:\Users\Administrator\Desktop\Eclipse.lnk")
PS C:\Users\Administrator> $Shortcut.TargetPath = "powershell.exe -File C:\cfn\temp\eclipse-fix.ps1"
Value does not fall within the expected range.
At line:1 char:1
+ $Shortcut.TargetPath = "powershell.exe -File C:\cfn\temp\eclipse-fix. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
PS C:\Users\Administrator> $Shortcut.IconLocation="%SystemDrive%\eclipse\eclipse.exe, 0"
PS C:\Users\Administrator> $Shortcut.Save()
Result:
The icon is created but has no value for target.
Does anyone know what I am missing to get this to work? Is there another option to use that I may not be aware of?
Thanks.
You need to specify the Arguments separate from the TargetPath
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("C:\Users\Administrator\Desktop\Eclipse.lnk")
$Shortcut.TargetPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$Shortcut.Arguments = "-ExecutionPolicy bypass C:\cfn\temp\eclipse-fix.ps1 -WindowStyle Hidden"
$Shortcut.IconLocation = "%SystemDrive%\eclipse\eclipse.exe"
$Shortcut.Save()
You can also use just powershell.exe in place of the full path. Either will work.
Here is a script I wrote that will create a shortcut to itself on the desktop that is executable (Can run by double clicking) when run.
I did this to take the step-by-step process out of colleagues having to create their own shortcuts of my powershell automation scripts.
Because our shared drive at work is a different location for everybody, I use the "Get-location" command which gets the pwd, then trim it and parse it for use within the shortcut's argument field.
In order to have the arguments contain double quotes, you have to use the escape character ` preceding another set of quotes, this will allow for the script to send quotes to the arguments field. It will not work without this. '" '"
Make sure that when you are running the script you are not running it from the powershell IDE, or the file paths will be wrong. You need to save the script in your target source path and the nrun it from there by either right ckicling it and running it as a powershell script or creating an executable shortcut for it. Let me know if you need instructions on how to create an executable powershell shortcut.
Hope this helps!
#Grap the pwd
$location = Get-Location | Select Path | ft -HideTableHeaders | Out-String;
#Trim the pwd variable of any extra spaces and unwanted characters
$location = $location.Trim();
$locations = $location.replace(' ' , '');
$locations = $locations.replace("`n","");
#Make the source file location my path to powershell.exe
$SourceFileLocation = "`"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe`"";
# Declare where I want to place the shortcut, I placed it on the desktop of whomever is running the script with the dynamic $env:USERNAME which takes the username of whomever is running the script - You can name the shortcut anything you want at the end as long as it ends with .LNK
$ShortcutLocation = “C:\Users\$env:USERNAME\OneDrive\Desktop\PopupSortcut.lnk”;
#Create a now com
$WScriptShell = New-Object -ComObject WScript.Shell;
#create shortcut and provide the location parameter as an argument
$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation);
#set the target path
$Shortcut.TargetPath = $SourceFileLocation;
#Add arguments that will bypass the execution policy as well as provide a path to the source powershell script (make sure that the entire argument has double quotes around it and that the internal quotes have escape characters (`) behind them, these are not apostrophes but back ticks, located on the same key as the tilde (~) key on the keyboard
$Shortcut.Arguments = “-ExecutionPolicy Bypass -file `"$locations"+"Pop-up.ps1`"”;
#Save the Shortcut
$Shortcut.Save();
########################### This is the meat of our script Performing an Operation #######################
$wshell = New-Object -ComObject Wscript.Shell;
$wshell.Popup("Operation Completed",0,"Done",0x1);

How to execute Windows command (Get-Content) from PowerShell in Windows Server

My server is Windows Server. I would like to replicate the Unix tail command in Windows Server.
Unix Server: tail -f test.txt
PowerShell: Get-Content test.txt
How to execute in Windows Server?
Below command is not working:
powershell -File "Get-Content test.txt"
Error message:
Unable to execute program 'powershell -File "\"Get-Content...
Any idea?
Get-Content is not a file; it is a cmdlet. The -file parameter to Powershell.exe instructs Powershell to read the file supplied and execute the commands in it, as a script.
You can pass commands directly to Powershell by using the -command parameter; the parameter can be a quoted string, which is interpreted as a Powershell command. You would therefore want to use
powershell -command "Get-Content test.txt"
in the simplest case.
Note that Powershell.exe must be in your system path; if it is not, you would need to supply the full path to powershell, e.g.,
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -command "Get-Content text.txt"
This question is very similar - perhaps essentially identical - to Unix tail equivalent command in Windows Powershell; I would recommend reading that question and its answers as well.
Additionally, exploring the help for Get-Content will provide useful information.
Working fine after setting full path of powershell.exe and without any quotes
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command Get-Content test.txt
Within a powershell window :
Get-Content test.txt
command returns :
hello world.
i'm inside test.txt.
bye.

Powershell in a batch file running as a service issue

disclosure
I'm a PHP/Linux developer that is having to get use to working in a Windows environment, so I very well my be missing something fundamental in the question. I've researched the heck out of this and can't seem to pinpoint a solution. Thanks for your help in advanced.
I have a batch file that calls a powershell script that doesn't work correctly when it is started by the window's task scheduler, but works perfectly when it is launched by hand.
Below is the Powershell script that the batch file is launching...
$WatchFolder = '\\networkshare\foldername'
$Filter = '*.csv'
$fsw = New-Object IO.FileSystemWatcher $WatchFolder, $Filter -Property #{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters] 'LastWrite'}
Register-ObjectEvent $fsw Changed -SourceIdentifier SAS_Poll_FileChanged -Action {
$WatchFolder = '\\networkshare\foldername'
$OutputFolder_one = '\\networkshare\outputFolder_One'
$OutputFolder_two = '\\networkshare\outputFolder_Two'
$name = $Event.SourceEventArgs.Name
$lock_file = $WatchFolder + '\.' + $name + '.lock'
$test = (Test-Path "$lock_file")
if ( $test ){
return
} else {
Set-ExecutionPolicy -Scope CurrentUser Bypass
Out-File -FilePath "$lock_file"
Start-Process powershell -ArgumentList ".\General\PollingProcess-alone.ps1 $WatchFolder $MainFrameFolder $SASFolder $name $lock_file" -NoNewWindow
}
}
I know the issue occurs at the following line...
Start-Process powershell -ArgumentList ".\General\PollingProcess-alone.ps1 $WatchFolder $MainFrameFolder $SASFolder $name $lock_file" -NoNewWindow
I know this b/c when the event is triggered ( when the script is launched via the task scheduler ), the lock file is created and then the process hangs.
I therefore think that the issue has something to do with path of second powershell script I'm calling, but I don't know how to fix it. I've tried using the full path of the second script, but haven't been able to make it work.
Just to give you some more context of the script, it is sort of important the the event process spins up a new powershell script b/c I need these scripts to run concurrently.
Pretty sure the problem is with your argument list, right now you are passing a single string with everything contained within it, change that to an array and things should work properly.
so convert
".\General\PollingProcess-alone.ps1 $WatchFolder $MainFrameFolder $SASFolder $name $lock_file"
to
".\General\PollingProcess-alone.ps1",$WatchFolder,$WatchFolder,etc..
give that a shot and let us know if it works for you, also want to say that your code is impressive for being relatively new to PowerShell so kudos lol.

Start a detached background process in PowerShell

I have a Java program which I would like to launch as a background process from a PowerShell script, similar to the way a daemon runs on Linux. The PowerShell script needs to do a couple of things:
Run the program as a separate and detached process in the background, meaning the parent window can be closed and the process keeps running.
Redirect the program's standard output and standard error to files.
Save the PID of the background process to a file so it can be terminated later by another script.
I have a shell script on Linux which starts the program like so:
$ java -jar MyProgram.jar >console.out 2>console.err &
I'm hoping to replicate the same behavior on Windows using a PowerShell script. I have tried using Start-Process with various combinations of options, as well as creating System.Diagnostics.ProcessStartInfo and System.Diagnostics.Process objects, but so far I am not having any luck. PowerShell starts the program as a background process, but the program abruptly terminates when the DOS window which started the PowerShell session is closed. I would like it to start in the background and be independent of the command window which started it.
The output redirection has also been troublesome, as it seems that the output and error streams can only be redirected in the process is being run in the same window (e.g., using -NoNewWindow).
Is this sort of thing possible in PowerShell?
Use jobs for this:
Start-Job -ScriptBlock {
& java -jar MyProgram.jar >console.out 2>console.err
}
Another option would be Start-Process:
Start-Process java -ArgumentList '-jar', 'MyProgram.jar' `
-RedirectStandardOutput '.\console.out' -RedirectStandardError '.\console.err'
Consider using the task scheduler for this. Define a task and set it without any triggers. That will allow you to simply "Run" (manually trigger) the task.
You can set up and/or trigger scheduled tasks using the ScheduledTasks powershell module, or you can use the GUI.
This is an old post but since I have it working fine thought it might help to share. Its the call to 'java' instead of 'javaw' that is likely your issue. Ran it out myself using my JEdit java program through powershell to launch it.
#Requires -Version 3.0
$MyDriveRoot = (Get-Location).Drive.Root
$JEditDir = $($mydriveroot + "jEdit") ;# Should be C:\jEdit or wherever you want. JEdit is a sub-directory.
$jEdit = $($JEditDir + "\jedit.jar" )
$jEditSettings = $($JEditDir + "\settings")
$JEditLogs = $($JEditDir + "\logs")
Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$JEditSettings"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
Which you can turn into a little function and then an alias to make it easy to launch in Powershell.
If ( ( Test-Path $jedit) ) {
Function Start-JEdit() {
Start-Process -FilePath javaw -ArgumentList ( '-jar',"$jEdit", '-settings="$($mydriveroot + "jEdit\settings")"' ) -RedirectStandardOutput "$JEditLogs\console.out" -RedirectStandardError "$JEditLogs\console.err"
}
New-Alias -Name jedit -Force Start-JEdit -Description "Start JEdit programmers text editor"
}
Try this with PowerShell:
Start-Process cmd -Args /c,"java -jar MyProgram.jar" `
-WindowStyle Hidden -RSI console.out -RSE console.err
OR
Start-Process cmd -Args /c,"java -jar MyProgram.jar >console.out 2>console.err" `
-WindowStyle Hidden
This will start a detached cmd window that is hidden, and will redirect the std streams accordingly.
Old question, but since I had the same goal, I used answer from #use to acheive it.
So here is my code :)
$NAME_TASK = "myTask"
$NAME_TASKPATH = "\myPath\"
if ($args[0] -eq "-task") {
# Code to be run "detached" here...
Unregister-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Confirm:$False
Exit
}
$Task = (Get-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -ErrorAction 'SilentlyContinue')
if ($Task) {
Write-Host "ERR: Task already in progress"
Exit 1
}
$A = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy bypass -NoProfile -Command ""$PSCommandPath -task $args"""
Register-ScheduledTask -TaskName $NAME_TASK -TaskPath $NAME_TASKPATH -Action $A | Start-ScheduledTask
The solution is to combine Start-Process with nohup:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-7.3#example-9-create-a-detached-process-on-linux
(Note: This is NOT for Windows.)

1734: The array bounds are invalid

I have a script in which I need to run one command as an administrator. When I ran this command the script errors with a 1734 error.
My script is very basic:
runas /user:Administrator "myexec.exe \"param with spaces\" otherparam -Djava.ext.dirs=%JAVA_EXT_DIRS%"
The problem comes from the variable JAVA_EXT_DIRS which is kind of huge.
This is an old question, but I've ran into the same problem on Windows 10 with the runas command now. It turns out there's a maximum length for the program parameter, which has to be below 995 characters.
For example, this command still works:
runas /user:someuser /savecreds "cmd.exe 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
The program parameter here has 994 characters, and it should open a new command prompt. But if you add one more 1 within that parameter, the execution will fail with a 1734: The array bounds are invalid. error.
And if you increase the the program parameter even further to 1026 characters, the error changes to -2147024809: The parameter is incorrect..
The regular limit for command line parameters seems to be much much larger (I've read something about 8191 characters here on SO), so this seems to be a problem with runas.exe itself.
Edit:
I even ran into a similar problem when I tried to use a PowerShell script with the -Credential flag like this:
$username = "username"
$password = "password"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential $username, $securePassword
$argument = $args[0]
Start-Process -FilePath "C:\path\to\my.exe" -Credential $credentials -ArgumentList "-arg $argument"
So it's probably a problem with the underlying Windows mechanics and not runas.exe itself.
The value of %JAVA_EXT_DIRS% may contain spaces too. You better put it in double quotes:
runas /user:Administrator "myexec.exe \"param with spaces\" otherparam -Djava.ext.dirs=\"%JAVA_EXT_DIRS%\""

Resources