PowerShell script exchange
Post Reply
dfolks
Lurker
Posts: 1
Liked: never
Joined: Jan 17, 2020 2:47 pm
Full Name: Dave Folksman
Contact:

Powershell cmd-let to get name of job that invoked script.

Post by dfolks »

Hi all,

I'm looking for a powershell cmd-let that lets me get the name of the job that invoked the post job script, so I can store it in a variable.

Im trying to run manual truncation on our exchange servers using a script, but i want to pass the name of the job to the script to save me having to write custom scripts for each job.

Thanks.
tsightler
VP, Product Management
Posts: 6035
Liked: 2860 times
Joined: Jun 05, 2009 12:57 pm
Full Name: Tom Sightler
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by tsightler » 2 people like this post

So I wrote this little piece of magic back a few years ago (OK, a lot of years ago):

Code: Select all

# Determine job name from calling Veeam.Backup.Manager process
$parentPid = (Get-WmiObject Win32_Process -Filter "processid='$pid'").parentprocessid.ToString()
$parentCmd = (Get-WmiObject Win32_Process -Filter "processid='$parentPid'").CommandLine
$cmdArgs = $parentCmd.Replace('" "','","').Replace('"','').Split(',')
$jobName = (Get-VBRJob | ?{$cmdArgs[4] -eq $_.Id.ToString()}).Name
Veeam doesn't pass the job name as a parameter, so the code above instead finds the parent process that called the script, which, for pre/post-job scripts is the Veeam.Backup.Manager.exe process. The command line for this process includes the JobID, so you can then just grab the job with Get-VBRJob and filtering on the ID.

This was probably first written for v7 (perhaps even 6.5), but as far as I know it still works with 9.5u4 without any changes, at least, I know some customers that are still using scripts I wrote from back then and they haven't complained to me, but I'll admit I haven't tested it in a while. It's a little difficult to troubleshoot since it obviously only works when run as a pre/post-job script.

Usually, in my scripts, I support a $jobName parameter, which you can pass manually from the cmdline for testing, and, only if this is undefined, does it activate the "automatic" job name. This way I can still easily test my scripts from the cmdline while not having to pass individual parameters for every single pre/post-job.

Let me know if you have any issues.
edingc
Influencer
Posts: 15
Liked: 2 times
Joined: Jun 26, 2018 12:51 pm
Full Name: Cody Eding
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by edingc »

@tsightler

I had been using your code with success until I upgraded to version 10a this week. Now, the IDs I get back from the the process arguments don't seem to match the IDs from Get-VBRJob.

I tested on two different Backup Copy Jobs and saw the same behavior. Has something changed under the hood in v10a that would have broken this code? And if so, is there another alternative to getting the job name in a pre/post script?

Thanks!
oleg.feoktistov
Veeam Software
Posts: 2010
Liked: 670 times
Joined: Sep 25, 2019 10:32 am
Full Name: Oleg Feoktistov
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by oleg.feoktistov »

Hi Cody,

Not sure what has changed to prevent it from working in 10a, but you can use these one liners to filter jobs by script names if known:

Code: Select all

# Pre-script
 $job = Get-VBRJob | where {$_.JobScriptCommand.PreScriptCommandLine -match 'open_url.ps1'} 

# Post-script
 $job = Get-VBRJob | where {$_.JobScriptCommand.PostScriptCommandLine -match 'open_folder.ps1'} 
Hope that helps,
Oleg
edingc
Influencer
Posts: 15
Liked: 2 times
Joined: Jun 26, 2018 12:51 pm
Full Name: Cody Eding
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by edingc »

Oleg -

Thanks, I suppose that is an option. The unfortunate thing is that I would need a script for every single job in order to use that logic, whereas with Tom's original logic I had one script that did everything I needed. But, if that's the only way to do it, that's OK, too.

Cody
JuA
Enthusiast
Posts: 54
Liked: 6 times
Joined: Jan 20, 2015 1:25 pm
Full Name: Julien A
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by JuA »

These workarounds look like crazy old-school UNIX scripts (at least the first one with all process list and string manipulations).

There is really no high-level / purpose made option to get the job name from this script ? Like an argument or an environment variable ?

if not : Hi Guy's at Veeam : this is a feature request.
JuA
Enthusiast
Posts: 54
Liked: 6 times
Joined: Jan 20, 2015 1:25 pm
Full Name: Julien A
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by JuA »

I found a nice way to pass the job name to the script from the job settings. I have to type the job name twice, but at least the two are in the same dialog-box...

In the "Run the following script after the job", I put :
d:\VeeamScripts\myScript.ps1 -jobName=The_Job_Name_Is_There

Then, in the script, I can parse the args variable and extract the job name...
soncscy
Veteran
Posts: 643
Liked: 312 times
Joined: Aug 04, 2019 2:57 pm
Full Name: Harvey
Contact:

Re: Powershell cmd-let to get name of job that invoked script.

Post by soncscy » 1 person likes this post

I'm not sure you can avoid this with Powershell in the current way it works. Checking how it looks in Veeam, they just basically start a process with the following:

Code: Select all

[30.11.2021 22:41:56] <01> Info         Executing custom command [powershell.exe], arguments [ -ExecutionPolicy ByPass -Command " try {& 'C:\scripts\callstacktest.ps1'  -ErrorAction Stop } catch { exit 1 } "]
It's pretty hands-off and probably it's for the best I think to not do anything too fancy.

Tom's general idea still works; I rewrote it slightly with less text munging if that's too concerning :) Powershell has the built-in $PID variable you can call which speeds this up a little.

Code: Select all

$ScriptPID = Get-WMIObject win32_process | Where-Object {$_.ProcessID -eq $PID}
$ParentProc = Get-WMIObject win32_process | Where-Object {$_.ProcessID -eq $ScriptPID.ParentProcessId}
$JobID = $ParentProc.CommandLine.Split()[7].Trim('"')
$Job = Get-VBRJob | Where-Object {$_.id -eq $JobID}
The main issue is that Powershell requires you to go through the win32_process to get information on the parent process; it's unavoidable to do some splitting/trimming, but hopefully this is a bit more aesthetically pleasing.

Code + Example Output (the last line in screenshot is just for making an example)

Image

So seems to work pretty well I think; there is a brief execution time though as it loads the Veeam Powershell Module.
Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests