Run a VBScript or PowerShell script?

When I try to set the --run-script-after option to point to either a VBScript (somefile.vbs) or a PowerShell script (somefile.ps1), Duplicati throws the error “The specified executable is not a valid application for this OS platform.”. I believe this might be because, for security reasons, the registry is not set up to allow scripts like this to be directly executed.

Normally, in a case like this, one would essentially call the script from another shell like “cmd.exe somefile.vbs” or “powershell -File somefile.ps1”. But if I set the --run-script-after option to either of these strings, then Duplicati throws the error “The system cannot find the file specified”. After doing a little poking around in the source code, I found that Duplicati initializes a System.Diagnostics.ProcessStartInfo class using “scriptpath”, which is presumably the string given to the --run-script-after option, and that calls the System.Diagnostics.Process.Start() method with this class as an argument. Because the string I provided is not a “scriptpath”, but contains both a script an arguments, it throws the “system cannot find the file specified” error.

Am I correct in that there appears to be no way to either directly call a VBScript or PowerShell script either directly or with arguments?

If so, I would propose modifying the code to allow the “scriptpath” to contain both the script and arguments. The string would be split into two, in which the first part is set to the executable name and the rest of the string would be considered as arguments. Then the process could be started uing System.Diagnostics.ProcessStartInfo(psi, args), where psi = System.Diagnostics.ProcessStartInfo(scriptpath). Some consideration for quoting exectuble paths containing white-space would be required to split the string correctly. Another option would be to just add more Duplicati options such as --run-script-after-arguments. This would probably be cleaner.

By the way, what I am doing now is to create a BAT file that then calls my other scripts. This is really annoying though as it means creating another file I need to manage and makes handling things like exit status and the handling of standard output/error more difficult. Calling the other scripts directly (or allowing arguments so that I could) would make things infinitely simpler.

If anyone has any thoughts about alternative approaches, I would be very interested!

That’s exactly what I would have proposed as a workaround.

In the future perhaps the code could be improved to separate the --run-script-after input into two values – script and parameters – at the first non-quoted space.

Has there been any movement on this at all? I ran into the same issue. Trying to make .bak files of my DB’s before backing them up.

Welcome to the forum @Jonathan_Woodard

looks like it still runs the script without arguments, basically per link below as opposed to the later form.

Does the suggested workaround not work for you? I can envision some reasons, but would rather hear.

Why must I use an exe? is my guess. Unlike Linux execve, Windows kernel won’t do interpreter scripts.
I just ran into this trying to get a perl .pl script to run. A PowerShell .ps1 script wouldn’t run either. Fail:

System.ComponentModel.Win32Exception (0x80004005): The specified executable is not a valid application for this OS platform.
   at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
   at Duplicati.Library.Modules.Builtin.RunScript.Execute(String scriptpath, String eventname, String operationname, String& remoteurl, String[]& localpath, Int32 timeout, Boolean requiredScript, IDictionary`2 options, String datafile, Nullable`1 level)

On the other hand, if arguments were allowed, one could probably start the interpreter, then feed it the interpreter script name as an argument. That’s kind of how a UNIX/Linux/etc. interpreter script works…

I discovered in testing that a .bat file was accepted, basically the same discovery above article made.

EDIT:

I was going to suggest filing a GitHub issue (since forum requests aren’t tracked), but I guess it’s done:

Support Powershell Pre-Script #4290

So currently we have a PS script that just makes bak files and uploads them. It works but not always reliable so i was wanting to have something better as well as have file backup.

However, yes, it seems like trading one quirky thing for another. Not something i want to take to my boss and say to do the same thing we’ll use this software and write a script to call another script.

I love everything else i’ve seen! However, I agree, give an extra parameter for being able to run a command and options.

I assume “file backup” means the PS script. The above sounds like they’re independent, except Duplicati is a convenient scheduler, but earlier statement below sounded like there was also a desire for time proximity:

but this worries me:

because if it hangs or errors, then Duplicati may see its issue. run-script-timeout sounds like it can handle a hung script (although I’m not sure how Windows will feel if a hang happens every run – infinite buildup?). Duplicati is also sensitive to exit codes from the script, so you want to make sure you don’t “signal” wrong:

Also be careful of messages from the script when it’s unreliable. Script output is interpreted per the below:

Where does script output go to (difference between BEFORE and AFTER?)

The second quirky thing is standard Windows quirkiness, as described earlier. You can’t even run PS from Command Prompt via the ps1 suffix. It opens in notepad. Interestingly, perl system also does. Explanation:

image

Command line of the running process:

cmd.exe /x/d/c C:\ProgramData\Duplicati\duplicati-2.0.5.110_canary_2020-08-10\utility-scripts\DuplicatiVerify.ps1

Option parsing is not always the easiest thing, but one way to take care of it is as above – let a command line interpreter do its thing. A thing it does not apparently do (much as one might want it) is run interpreter based on the file extension. It can sometimes, but I’m not sure of method. My Strawberry Perl installation allows me to run .pl scripts, and frankly I’m surprised Microsoft didn’t provide any ability to run .ps1 files.

Given the situation, it seems to me an entirely reasonable thing to use a batch file, and why even justify it?
While you might need to squash or catch the PS exit code, basically it’s powershell <path to script>.

Thank you for your helpful ideas. I was in a bit of a hurry when i replied last.

Perhaps if i explain better you might be able to help me in my understanding.

To explain a bit more… Currently we have 100+ remote servers all over the US. All run our software and have a local DB of various size. (20MB ~ 10+ GB)

Right now we have one PS script that makes a flat bak file. It makes the files and uploads them somewhere.

The PS script does not backup anything else. This is what i hoped to use duplicati for. The additional reporting, logging and management is huge as well.

To my knowledge, Duplicati cannot make the bak files and, my understanding is, that it simply does a VSS of the DBs and uploads the fullsize files.

Forgive a basic question but are these compressed before uploading? Or can they be? If so, this might render null the need for the bak files.

My original thought that i have been working with is to pre-run a PS script to make the smaller bak files and then let duplicati backup the file/folder created once the script completes.

If it was one server that i had to do the bat -> ps1 then that would be ok. I’m just a bit more hesitant to do it over many machines. But perhaps that is just me. :slight_smile:

The DB software being used isn’t stated, but if this is a DB dump, that’s perhaps done with DB tool help?

If this is SQL Server, people have found it does a bit more somehow (it’s slower), but details aren’t known. Basically I think it’s VSS copy though. I guess your DB software can produce things like incremental .bak?

Generally files are compressed, however known compressed file extensions aren’t, as there’s no point.
compression-extension-file controls this, if you have a need for special control for file extensions in use.

You could probably do that, but one question would be how many you’d need to get back for a database restore. Duplicati backups and restores are a point-in-time view, so if the .bak files are indistinguishable, finding out which ones to get may be hard. If they have different names, you still need to gather them all.

Nice scenario is there is a folder full of .bak with different names, and new files every so often to backup. Previously present files would be seen to be backed up already, so only the new files would be uploaded. Presumably, at some point the backup scheme resets, and does a full backup, but I don’t know your DB.

It’s not my call on what the developers prioritize, but you can see there’s a whole lot in the issue backlog. With far too few development volunteers, you might be in for a long wait to fix an issue with workarounds. Mine looks to be not quite accurate (I don’t use PowerShell), but web search will find some better details.

How to Use a Batch File to Make PowerShell Scripts Easier to Run was helpful because it points out that

PowerShell is not associated to the .PS1 file extension by default.

Geek School: Learn How to Automate Windows with PowerShell which it links suggests security benefits.

My Windows 10 system in Settings “Choose default apps by file type” gives my .pl and .ps1 associations:

image

image

so possibly you could make .ps1 actually run PS, but a security review might prefer that you didn’t do that.
There’s also a chance that it still wouldn’t work at the necessary low level, but only in places like cmd.exe.

I’m sorry you’re kind of stuck with Windows limitations, and no current Duplicati way to work around them.

It is fine and not a problem. We do have a current solution, however, I am just looking for alternatives to improve.

Thank you SO much for your insights and help!