Get Batch Script Name (Parant Process) from ps1 script

Hi Folks -

I have a batch script where I call a .ps1 script. Rather than pass the batch script name as a parameter to the ps1 (which is easy enough to do), I was wondering if there is an easy to way to extract the batch script name within the ps1 script itself?

I call the ps1 as follows:

POWERSHELL -ExecutionPolicy ByPass -file "%EMAIL_BIN%Email_Utility.ps1" ^
"%EMAIL_SERVER%" ^
"%EMAIL_FROM%" ^
"%EMAIL_TO%" ^
"%EMAIL_PSSWD%" ^
"%EMAIL_PORT%" && (
ECHO Success : Email Sent Successfully
) || (
ECHO Warning : Email Failed
ECHO.
TYPE "emailerror"
)

Thank you!

The problem is the parent process would probably be cmd.exe. You can use win32_process CIM to get to the parent process then access any properties you need (commandline property should point you to the executable). Also the automatic variable $PID will have the processID of the current instance of PowerShell. Here is an example:

$ParentPID = Get-CimInstance -ClassName win32_process -Filter "ProcessID=$PID" | 
            Select-Object -ExpandProperty ParentProcessID

$ParentProc = Get-CimInstance -ClassName win32_process -Filter "ProcessID=$ParentPID"

 

THank you! Can’t seem to derive the batch script name thought from the PID.

So I am getting closer. This code retrieves the full path and script name. However I need to parse the output between the " symbols and then get the string AFTER the last \ symbol.

Is that possible?

$ParentProc = gwmi Win32_Process | ? { $_.commandline -match “.cmd” } | ft commandline,processid -auto

You can certainly parse a string in PowerShell however you want. I would use the -replace operator which uses regex to find the section of string you are looking for. I’m assuming in your case that the batch file is an argument to the .cmd If so -replace may look something like this:

$teststring = "C:\Windows\System32\test.cmd arguments.bat"
$teststring -replace ".+\.cmd ", ""

Also you may not want to assume there is only one process running who’s commandline matches the regular expression “.cmd”. I would find the actual parent process using the $PID variable like I did in my previous example. Since “.cmd” is a regular expression (-match operator) the “.” means match any character. If you want the literal “.” you would need to escape it “.”

Recommend review Get-Help about_Comparison_Operators and Get-Help about_Regular_Expressions

Hi -

I’m calling a ps1 within a batch file as such:

POWERSHELL -ExecutionPolicy ByPass -file “%EMAIL_BIN%Email_Utility.ps1” ^
“%EMAIL_SERVER%” ^
“%EMAIL_FROM%” ^
“%EMAIL_TO%” ^
“%EMAIL_PSSWD%” ^
“%EMAIL_PORT%”

I use that code in many batch scripts, therefore I from the ps1 I want to be able to determine the name of the batch script it has been called from. I don’t understand your examples based on my need…

I can very easily add a new parameter from the batch file and pass the batch file name to ps1, but I have hundreds of batches I’d need to update. Hence, I’ trying to do this logic int he ps1 since I use the same ps1 file across all batch scripts…

Did you try using the method I posted? What are the results? Can you post the script (at least the applicable portion)?

Hi -

I’m not sure what script you are looking for? I posted the Batch script above which calls a ps1 script I use to send emails. Nothing in the ps1 should matter for this exercise. I’m merely trying to ADD a peice to my ps1 to derive the batch script name.

I tried your example but doesn’t make sense to me on how I can derive the batch script name from the ps1. Can you spin up an example of a batch script calling a ps1 and then trying to derive the batch script name from the ps1? Thanks!

The .ps1 script you are talking about in this quote is what I’m looking for. Isn’t that the script you want to find the batch script in? If not where do you plan on putting this PowerShell code?

Yes it is. My apologies, I assumed you would use an example. Here is the ps1:

 

#::-- Param values passed in from Parent script in strict order --::#
Param(
#::-- Required & cannot be Null --::#
[Parameter(Mandatory=$True)]
[ValidateNotNull()]
[string]$EmailSMTPServer,
[Parameter(Mandatory=$True)]
[ValidateNotNull()]
[string]$EmailFrom,
[Parameter(Mandatory=$True)]
[ValidateNotNull()]
[string]$EmailTo,
#::-- Optional & can be Null --::#
[string]$EmailPassword,
[int]$EmailPort
)

#::-- Ensure email recipient string is in proper format --::#
$EmailDelims = (")|#|$|!|%|&")
$EmailTo = $EmailTo.Trim() -replace $EmailDelims,","

#::-- Check PowerShell Version --::#
If($PSVersionTable.PSVersion.Major -lt 5) {
Throw “WARNING : Please install PowerShell 5.0 or greater to be compatible with this script”
Echo “WARNING : Please install PowerShell 5.0 or greater to be compatible with this script”>>"$Env:LOGFILEemailerror"
}

#::-- Determine Cloud Environment --::#
If("$Env:INTRAPATH") {
If("$Env:CLOUD_URL" -ilike “test”) {
$EmailEnv = “[TEST]”
} Else {
$EmailEnv = “[PROD]”
}
}

If("$Env:EMAIL_PSSWD") {
$EmailSecurePassword = Get-Content $EmailPassword | ConvertTo-SecureString
$EmailSecureCreds = New-Object System.Management.Automation.PSCredential ($EmailFrom, $EmailSecurePassword)

$MailParams = @{
SmtpServer = $EmailSMTPServer
From = $EmailFrom
To = $EmailTo.Split(’,’)
Subject = $Null
Body = $Null
Port = $EmailPort
Credential = $EmailSecureCreds
UseSsl = $True
Priority = $Null
}
} Else {
$MailParams = @{
SmtpServer = $EmailSMTPServer
From = $EmailFrom
To = $EmailTo.Split(’,’)
Subject = $Null
Body = $Null
Priority = $Null
}
}
#::-- Extensions to exclude from Email Attachments --::#
$EmailExtArray = “deletefile.log”,".cmd",".bat",".exe", ".ps1", “*.*emailerror”

#::-- Determine if there are any Attachments --::#
$EmailAttachments = Get-ChildItem “$Env:INTRAPATH” -exclude $EmailExtArray </code> <code>| Where-Object { !( $_ | Select-String "0% loss" -quiet) }
| Where { !$_.PSisContainer } |
Select -ExpandProperty FullName

#::-- Add additional attachments if applicable handled in parent batch --::#
$EmailAttachmentsExtra = @("$Env:MISMATCH_DMFILE", “$Env:IMPORTERROR_DMFILE”)
ForEach ($EAE In $EmailAttachmentsExtra) {
If ($EAE) {
If(Test-Path $EAE -PathType Leaf) {
$EmailAttachments += $EAE
}
}
}

#::-- Define Attachment Parameter if applicable --::#
If($EmailAttachments){$MailParams.Attachment = $EmailAttachments}

#::-- Determine Script Success from Parent Script via ERR variable --::#
If("$Env:ERR"){
$MailParams.Subject = “WARNING : $ParentScript Failed $EmailEnv”
$MailParams.Body = “The $EmailEnv $ParentScript process failed to complete successfully.” + “n” + “n” + “Please the check log file(s) for additional details.” + “n” + “n”
$MailParams.Priority = “High”
} Else {
$MailParams.Subject = “ATTENTION : $ParentScript Succeeded $EmailEnv”
If("$Env:INTRAPATH") {
$MailParams.Body = “The $EmailEnv $ParentScript process completed successfully.” + “n” + “n” + “Please the check log file(s) for additional details.” + “n” + “n”
} Else {
$MailParams.Body = “The $EmailEnv $ParentScript process completed successfully.” + “n” + “n”
}
$MailParams.Priority = “Normal”
}

#::-- Send Email --::#
#::-- Redirect stderr to err file --::#
Try {
Send-MailMessage @MailParams -ErrorAction Stop
}
Catch {
Echo “Failed to send message because: $($Error[0])”>>"$Env:LOGFILEemailerror"
exit 1
}

Thanks for the script. I did provide an example, but I don’t see where you tried to use it in this script. Having said that, the formatting of the script is a little hard to read. Make sure you are following the posting guidelines for scripts. Recommend using the PowerShell_ISE format because it adds line numbers which would be easier to reference in a discussion post.

When you get the batch file, what do you want to do with that data? Include it in the email?

Yes, you’ll see the $ParentScript variable in the Subject/Body lines of code. I need $ParentScript populated with the batch script name.

Then assign the $ParentScript variable using the example I provided. Something like…

$ParentProc = Get-CimInstance -classname win32_process -filter ("ProcessID={0}" -f (Get-CimInstance -ClassName win32_process -Filter "ProcessID=$PID" |
                    Select-Object -ExpandProperty ParentProcessID))

$ParentScript = $ParentProc.CommandLine

 

Ah thank you! I was forgetting the .Commandline portion on the variable!

 

One last thing, $ParentScript is now populated as such:

C:\WINDOWS\system32\cmd.exe /c "“C:\Cloud_Automation\Applications\AEW-Test\Scripts\Batch_EPMAutomate_Cloud_Utility.cmd” "

is it possible to then parse that output to get everything between the “” symbols and then ONLY reutrn the string following the LAST \ symbol.

For instance: _EPMAutomate_Cloud_Utility.cmd

 

Possible? Thank you!

Absolutely. I previously posted an example of this. You can use the -replace method with a regular expression. In this example I’m assuming they all end in .cmd. If that’s not correct you’ll have to modify the regular expression to handle other extensions.

 

$ParentScript = $ParentProc.CommandLine -replace '.+\\', '' -replace '.cmd.*','.cmd'

Wow, thank you so much!! This is great!!