Always on top batch script - powershell

I have created a simple batch script to pseudo-lock a computer using the following code:
#ECHO OFF & setlocal ENABLEDELAYEDEXPANSION
setlocal EnableDelayedExpansion
color a
TITLE Lock
if not "%1" == "max" (
powershell -command "& { $x = New-Object -ComObject Shell.Application; $x.minimizeall() }"
start /MAX cmd /c %0 max & exit/b
)
:Lock
echo Please enter a password to lock your computer . . .
powershell -Command $pword = read-host "Enter password" -AsSecureString ; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword) ; [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) > EOFlock.txt & set /p Pass1=<EOFlock.txt & del EOFlock.txt
TITLE Lock
taskkill /IM explorer.exe /F >nul
cls
echo Please type the password to unlock the computer . . .
:Locked
set /p Pass2=
:Unlock
if !Pass1! == !Pass2! (goto End)
goto Locked
:End
start explorer.exe
echo This Computer is unlocked.
I want this window to stay on top, and preferably be unclosable until it has reached the end of the file. However, I did not find a way to do this yet.

You can call into PowerShell which in turn can call into the WinAPI... at least on Windows 8+ (7 might work too, previous versions probably not).
It's relatively straightforward:
Call PowerShell
Tell it to run independent of context
Use SetWindowPos to bring a window to the front
Use GetConsoleWindow to find out which window to act on
It all fits pretty neatly into a single command:
#powershell -ExecutionPolicy UnRestricted -Command "(Add-Type -memberDefinition \"[DllImport(\"\"user32.dll\"\")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x,int y,int cx, int xy, uint flagsw);\" -name \"Win32SetWindowPos\" -passThru )::SetWindowPos((Add-Type -memberDefinition \"[DllImport(\"\"Kernel32.dll\"\")] public static extern IntPtr GetConsoleWindow();\" -name \"Win32GetConsoleWindow\" -passThru )::GetConsoleWindow(),-1,0,0,0,0,67)"

Related

Using PowerShell to send space character to desktop - to wake screen from sleep

I know the following 2 line PowerShell script sends a space character to a new "shell" object it creates.
Which does bring my sleeping screen out of its slumber.
But that opens, momentarily, a PowerShell window. So, if the screen is truly asleep-not a problem.
But, there are times of the day when this will run when the screen isn't in a sleeping slumber. Hence, when that happens, the user sees a very short annoying flash of the created Wscript.Shell
I'd like to just send the space keystroke to the desktop - to wake the sleeping screen. Without the momentary opening and closing of the Wscript.Shell
i.e., send the " " character to "the desktop" and not to a new shell object.
Is this possible?
I know nothing (obviously) about writing PowerShell.
$myshell=New-Object -com "Wscript.Shell"
$myshell.sendkeys(" ")
Perhaps there is a way the PowerShell script could know if the screen and/or computer is not in a sleep state, and therefore this could all just be avoided from running in that situation?
Any help is much appreciated.
It's being setup with a Powershell script to create a Task in task scheduler. That task then calls the 2 line PowerShell script to send the " " key, to wake the computer up just prior to the day's activity.
I found my answer. Since I am using AutoHotKey, the following code will use PowerShell to create a new task in task scheduler. By using the cmd /c start /min "" powershell ... style of command, the pop-up window does not display - but the computer and screen wake up.
WakeUp:= A_Now
EnvAdd WakeUp, 10, Minutes ; wake 10 minutes from now
UTC_Delta-= A_NowUTC, Seconds ; Seconds is more accurate due to rounding issue
UTC_Delta:= Round(-UTC_Delta/60) ; Round to nearest minute to ensure accuracy
WakeUp += UTC_Delta, Minutes ; Apply offset to convert to UTC
FormatTime, WakeTime,% WakeUp, "yyyy-MM-ddTHH:mm:ssZ"
psScript =
(
$action = New-ScheduledTaskAction -Execute cmd -Argument '/c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -command {$myshell=New-Object -com "Wscript.Shell" $myshell.sendkeys(" ")}'
$settings = New-ScheduledTaskSettingsSet -WakeToRun
$trigger = New-ScheduledTaskTrigger -Once -At %WakeTime%
Register-ScheduledTask -TaskName wakeup -Action $action -Settings $settings -Trigger $trigger -Force
)
RunWait PowerShell.exe -Command &{%psScript%} ,, hide
;use the following if you want to see PowerShell output
;Run PowerShell.exe -NoExit -Command &{%psScript%}
This wakes the screen by mouse movement, not keyboard but seems to work for me.
Based on Screen wake up settings in power options or registry for windows OS?
$Signature = #"
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam,
IntPtr lParam);
[DllImport("user32.dll")]
public static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);
"#
Try {
$ShowWindowAsync = Add-Type -MemberDefinition $Signature -Name
"Win32ShowWindowAsync" -Namespace Win32Functions -PassThru -ErrorAction Ignore }
Catch { }
$MONITOR_ON = -1;
$MONITOR_OFF = 2;
$MONITOR_STANBY = 1;
[System.Int64]$MOUSEEVENTF_MOVE = 0x0001;
[System.IntPtr]$HWND_BROADCAST = New-Object System.IntPtr(0xffff)
[System.UInt32]$WM_SYSCOMMAND = 0x0112
[System.IntPtr]$SC_MONITORPOWER = New-Object System.IntPtr(0xF170)
# this commands puts monitors to sleep
# $ShowWindowAsync::SendMessage($HWND_BROADCAST, $WM_SYSCOMMAND, $SC_MONITORPOWER, [System.IntPtr]$MONITOR_OFF);
# this command wakes monitors up
$ShowWindowAsync::mouse_event($MOUSEEVENTF_MOVE, 0, 1, 0, [System.UIntPtr]::Zero);

Embed VBScript in PowerShell Script - One File

I recently learned a lot messing with batch + VBScript hybrid scripts and while it was great learning and works, it's time to learn PowerShell more thoroughly. But, my favorite part of Batch/VBScript solution is that I can create a single script.cmd file to distribute.
Is there any sort of solution with PowerShell/VBScript? Ideally I think I'd prefer a .ps1 script with embedded VBScript, but interested in knowing my options.
There seems to be some confusion regarding the goal.
One Single File (This is the most important part)
Extension either .ps1 or .vbs
Both POWERSHELL and VBScript inside single file
Bonus:
No writing to external file
Prefacing each line
Having to escape special characters in code
Encoding entire sections of script (overhead CPU intensive operations)
Here is a thoeretical example:
script.{ps1/vbs}:
<!-- : Begin PS1 script
$strString = "Hello PowerShell"
write-host $strString
cscript //nologo "%~f0?.wsf" //job:HELLOWORLD
exit /b
PAUSE
----- Begin wsf script --->
<package>
<job id="HELLOWORLD">
<script language="VBScript">
MsgBox "Hello World VBS"
</script>
</job>
<job id="VBS">
<script language="VBScript">
'Second Script!
</script>
</job>
</package>
Something like this -->
https://stackoverflow.com/a/9074483/5079799
<!-- : Begin batch script
#ECHO OFF
CLS
cscript //nologo "%~f0?.wsf" //job:HELLOWORLD
exit /b
PAUSE
----- Begin wsf script --->
<package>
<job id="HELLOWORLD">
<script language="VBScript">
MsgBox "Hello World"
</script>
</job>
<job id="VBS">
<script language="VBScript">
'Second Script!
</script>
</job>
</package>
Create the VBS script as usual. Save in some location and then convert it into Base64. Byte encoding is used so that this will work on binary files too, and overcomes character encoding issues. Like so,
$Content = Get-Content -Path C:\temp\myScript.vbs -Encoding Byte
$Base64 = [System.Convert]::ToBase64String($Content)
$Base64 | Out-File c:\temp\myScript.b64
Then, in your Powershell script, include the encoded version of the VBS script. Convert Base64 back into string and write it into a file. Finally, call cscript to run the .vbs.
$Base64 = "ZgB1AG4AYwB0AGkAbwBuACAAR..."
$Content = [System.Convert]::FromBase64String($Base64)
Set-Content -Path $env:temp\myScript.vbs -Value $Content -Encoding Byte
& cscript /nologo $env:temp\myScript.vbs
Another an option is to embed the VBScript in a here-string like so,
# Paste the VBS in a here string
$Content = #'
dim foo
...
'#
Set-Content -Path $env:temp\myScript.vbs -Value $Content
& cscript /nologo $env:temp\myScript.vbs
Perhaps, you mean create a .ps1 script file and run it from vbscript ?
If so, here is an example named as Compress_Archive_by_Extension.vbs
Remark : Compress-Archive is only available with PS v4
Option Explicit
Dim Title,ArrExt,Ext
Title = "Compress Archive With Powreshell And Vbscript by Hackoo 2020"
REM We define an array of extensions for archiving !
ArrExt = Array("vbs","vbe","cmd","bat","ps1","js","jse","lnk")
REM Looping thru extensions defined from our array in order to zip and archive them,
REM so you can add or remove what you want as extension in the array above !
For each Ext in ArrExt
Call Compress_Archive("%Temp%\*."& Ext,"Temp_Archive_"& Ext)
Call Compress_Archive("%AppData%\*."& Ext,"AppData_Archive_"& Ext)
Call Compress_Archive("%LocalAppData%\*."& Ext,"LocalAppData_Archive_"& Ext)
Call Compress_Archive("%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup\*."& Ext,"ProgramData_Archive_"& Ext)
Call Compress_Archive("%UserProfile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\*."& Ext,"UserProfile_Archive_"& Ext)
Next
MsgBox "Archive Script is completed !",vbInformation,Title
'---------------------------------------------------------------------
REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive?view=powershell-5.1&redirectedfrom=MSDN
Sub Compress_Archive(Source,Destination)
Const ForWriting = 2
Dim fs,Ws,ts,Ret,PSFile,ByPassPSFile
Set fs = CreateObject("Scripting.FileSystemObject")
Set Ws = WScript.CreateObject("WScript.Shell")
Source = Ws.ExpandEnvironmentStrings(Source)
Destination = Ws.ExpandEnvironmentStrings(Destination)
PSFile = Ws.ExpandEnvironmentStrings("%Temp%") & fs.GetTempName & ".ps1"
ByPassPSFile = "PowerShell -ExecutionPolicy bypass -noprofile -file "
Set ts = fs.OpenTextFile(PSFile,ForWriting,True)
ts.WriteLine "Compress-Archive -Path " & DblQuote(Source) &_
" -Update -CompressionLevel Optimal -DestinationPath "& DblQuote(Destination)
ts.Close
Ret = Ws.run(ByPassPSFile & PSFile,0,True)
If fs.FileExists(PSFile) Then fs.DeleteFile(PSFile)
End Sub
'---------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'---------------------------------------------------------------------
Second example : To download an image from site : Download_File.vbs
Option Explicit
Dim URL,Ws,ByPassPSFile,PSFile,MyCmd,Result
URL = "https://cdn2.unrealengine.com/Fortnite%2FBoogieDown_GIF-1f2be97208316867da7d3cf5217c2486da3c2fe6.gif"
Set Ws = CreateObject("wscript.Shell")
PSFile = Left(Wscript.ScriptFullName, InstrRev(Wscript.ScriptFullName, ".")) & "ps1"
ByPassPSFile = "cmd /C PowerShell.exe -ExecutionPolicy bypass -noprofile -file "
MyCmd = "$source = " & DblQuote(URL) & VbCrlF
MyCmd = MyCmd & "$Filename = [System.IO.Path]::GetFileName($source)" & VbCrlF
MyCmd = MyCmd & "$dest = " & DblQuote("$env:temp\$Filename") & VbCrlF
MyCmd = MyCmd & "$wc = New-Object System.Net.WebClient" & VbCrlF
MyCmd = MyCmd & "$wc.DownloadFile($source,$dest)" & VbCrlF
MyCmd = MyCmd & "Start-Process $dest"
Call WriteMyPSFile(MyCmd)
Result = Ws.run(ByPassPSFile & PSFile,0,True)
'----------------------------------------------------------------------------------------
Sub WriteMyPSFile(strText)
Dim fs,ts,PSFile
Const ForWriting = 2
PSFile = Left(Wscript.ScriptFullName, InstrRev(Wscript.ScriptFullName, ".")) & "ps1"
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(PSFile,ForWriting,True)
ts.WriteLine strText
ts.Close
End Sub
'----------------------------------------------------------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'----------------------------------------------------------------------------------------
EDIT : 21/08/2020 # 20:45
Here is a "pseudo-hybrid" because it use a temporary file to be executed :
inspired from #vonPryz answer.
You can save it as Test.ps1 and execute from PowerShell ISE
$VBS_Content = #'
Dim http, WAN_IP
Set http = CreateObject( "MSXML2.ServerXmlHttp" )
http.Open "GET", "http://icanhazip.com", False
http.Send
WAN_IP = http.responseText
wscript.echo "WAN_IP : " & WAN_IP
'#
Set-Content -Path $env:temp\myScript.vbs -Value $VBS_Content
& wscript.exe $env:temp\myScript.vbs
$url = "https://externals.lesechos.fr/medias/2019/04/26/2262811_pourquoi-salto-le-futur-netflix-francais-devra-seuropeaniser-195514-1.jpg"
#https://stackoverflow.com/questions/35813186/extract-the-filename-from-a-path
$output = $env:temp + "\" + $url.Split("/")[-1]
$start_time = Get-Date
Try {$wb = (New-Object System.Net.WebClient).DownloadFile($url,$output)}
Catch {
Write-Host "Error from $url ! " -ForegroundColor Red -BackgroundColor Yellow
Write-Host "Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor Yellow
}
Write-Output "Running Script Time taken is : $((Get-Date).Subtract($start_time).Seconds) second(s)"
Start-process $output
Another simple example :
$VBS_Content = #'
MsgBox "This a simple MsgBox from Vbscript"
'#
$TmpVBS="$env:temp\myScript.vbs"
SC $TmpVBS $VBS_Content
wscript.exe $TmpVBS
Echo 'Hello World from Powershell !'
Here is my final answer, I haven't tested with anything super complicated, so not sure how it would handle things like special characters...
#https://stackoverflow.com/questions/63514534/embed-vbscript-in-powershell-script-one-file
#######################Begin VBS1#######################
###JOB_A START###
$VBS_Content_Job_A = #'
MsgBox "This a simple MsgBox from Vbscript (Job_A)"
'#
###JOB_A END###
###JOB_B START###
$VBS_Content_Job_B = #'
MsgBox "This a simple MsgBox from Vbscript (Job_B)"
'#
###JOB_B END###
#######################Begin PS1#######################
ECHO 'Hello World from Powershell !'
PAUSE
ECHO "Running VBS Now"
PAUSE
###VBS CALL START###
$VBSJob=$VBS_Content_Job_A
$TmpVBS="$env:temp\myScript.vbs"
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
SC $TmpVBS $VBSJob
cscript //nologo $TmpVBS
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
###VBS CALL END###
ECHO "Some More PowerShell"
PAUSE
ECHO "I need anoter VBS Script"
PAUSE
###VBS CALL START###
$VBSJob=$VBS_Content_Job_B
$TmpVBS="$env:temp\myScript.vbs"
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
Set-Content -Path $TmpVBS -Value $VBSJob
cscript //nologo $TmpVBS
Remove-Item $TmpVBS -ErrorAction SilentlyContinue
###VBS CALL END###
ECHO "All Done!"
PAUSE
You can embed VB.NET code into powershell code with TypeDefinition:
$code = #"
Imports System
Namespace MyNameSpace
Public Class Responder
Public Shared Sub StaticRespond()
Console.WriteLine("Static Response")
End Sub
Public Sub Respond()
Console.WriteLine("Instance Respond")
End Sub
End Class
End Namespace
"#
# Check the type has not been previously added within the session, otherwise an exception is raised
if (-not ([System.Management.Automation.PSTypeName]'MyNameSpace.Responder').Type)
{
Add-Type -TypeDefinition $code -Language VisualBasic;
}
[MyNameSpace.Responder]::StaticRespond();
$instance = New-Object MyNameSpace.Responder;
$instance.Respond();
Not exactly vbscript but is a good solution.

Is there a problem with passing variable to command-prompt from powershell?

I have a script for stress testing networks in batch, and it has been working fine for me and doing exactly what I wanted it to do. I recently tried to remake it in powershell, and overall it was the same, except for one detail. Whenever I tried to start new command prompts with start cmd.exe -argumentlist {/k ping $p /l $Bytes /t} -windowstyle Minimized, it starts cmd, but it gets lost at the $p saying Ping request could not find host $p. Please check the name and try again. instead of actually passing the variable. I have been stumped for a while and couldn't find what was causing this issue since when I passed other variables to set the title of the prompts, it worked fine. The variable $p isn't getting undefined either, so I don't know what is causing this.
Here are my scripts
Batch file:
#echo off
title MainPingCenter
(call )
choice /c DC /m "Would you like to ping the default gateway or a custom IP/Web Address?"
IF %ERRORLEVEL% EQU 1 ((for /f "tokens=2,3 delims={,}" %%a in ('"WMIC NICConfig where IPEnabled="True" get DefaultIPGateway /value | find "I" "') do (echo Default IP Gateway : %%~a & set i=%%~a))
goto add)
set /p i="Type in the IP address or website address you want to ping: "
:add
set /p loopcount="How many cmds do you want to ping with? "
set /p Bytes="How many bytes of data do you want to ping with? "
set /a loopcount=loopcount+1
:loop
set /a loopcount=loopcount-1
if %loopcount% LEQ 0 (goto exitloop)
start /min cmd.exe /k ping %i% /l %Bytes% /t
goto loop
:exitloop
echo Success
echo Commands are running in background
pause
:back
choice /c CP /m "Would you like to create more ping cmds or proceed? "
IF %ERRORLEVEL% EQU 1 goto add
IF %ERRORLEVEL% EQU 2 goto choose
:choose
(call )
choice /c YNTC /m "Would you like to close all cmd processes? (Yes, No, Timer, Cancel)"
IF %ERRORLEVEL% EQU 1 goto yes
IF %ERRORLEVEL% EQU 2 goto no
IF %ERRORLEVEL% EQU 3 goto timer
IF %ERRORLEVEL% EQU 4 goto back
:yes
echo Closing all instances of cmd excluding this...
taskkill /im cmd.exe /t /f /fi "windowtitle ne MainPingCenter"
echo Taskkill complete. Press any key to continue...
pause >nul
title Command Prompt
goto :eof
:no
echo Ok, press any key to end this file...
pause >nul
title Command Prompt
goto :eof
:timer
set /p timer="Set amount of seconds until processes are closed: "
choice /c YN /m "Would you ike it to close automatically when the time is finished? "
IF %ERRORLEVEL% EQU 1 (timeout /t %timer% /nobreak & goto yes)
timeout /t %timer% /nobreak
echo Time is up. Press any key to terminate all command prompts
pause >nul
goto yes
Powershell
$host.ui.RawUI.WindowTitle = "Main Ping Center"
while (!($p)) {
$choice = read-host "Do you want to ping the default gateway, localhost, or a custom address? `n[D,L,C]"
switch ($choice) {
"D" {$p = WMIC NICConfig where IPEnabled="True" get DefaultIPGateway /value |findstr "{"; $p = $p.trimstart('DefaultIPGateway={"'); $p = $p.trimend('"}'); break}
"L" {$p = "localhost"; break}
"C" {$p = read-host "What address do you want to ping?"; break}
}
if (!($p)){echo "Invalid input"}
}
$p
while (!($lc -is [int])){
$lc = read-host "How many cmds do you want to ping with? "
$ErrorActionPreference = 'SilentlyContinue'
[int]$lc = $lc
if (!($lc -is [int])){echo "Invalid input"}
}
while (!($bytes -is [int])){
$Bytes = read-host "How many bytes of data do you want to ping with? "
$ErrorActionPreference = 'SilentlyContinue'
[int]$bytes = $bytes
if (!($bytes -is [int])){echo "Invalid input"}
}
$ErrorActionPreference = 'continue'
$nametitle = (Get-Random)*([math]::pi)*(Get-Random)
$p
do {
start cmd.exe -argumentlist {/k title $nametitle `& ping $p /l $Bytes /t} -windowstyle Minimized
# Variable "$nametitle" gets passed normally but even if I remove the title and "&", $p never gets passed
$lc--
} until ( $lc -eq 0 )
write "Success`nCommands are running in background"
pause
while (!($C2)) {
$choice2 = read-host "Would you like to close all cmd processes? (Yes/Y, No/N, Timer/T)"
switch ($choice2) {
"Yes" {$C2 = "Yes"}
"Y" {$C2 = "Yes"}
"No" {$C2 = "No"}
"N" {$C2 = "No"}
"Timer" {$C2 = "Time"}
"T" {$C2 = "Time"}
}
if (!($C2)){echo Invalid input}
}
switch ($C2) {
"Yes" {echo "Closing all instances of cmd excluding this..."
taskkill /im cmd.exe /t /f /fi "windowtitle eq $nametitle"
echo "Taskkill complete. Press any key to continue..."
pause | out-null
exit}
"No" {cd "$home\desktop"
echo $nametitle > PingName.txt
echo "Ok, sending name of ping cmds to text file..."
echo "Press any key to exit this file..."
pause | Out-Null
exit}
"Time" {$timer = read-host "Set amount of seconds until processes are closed"
timeout /t $timer /nobreak
echo "Closing all instances of cmd excluding this..."
taskkill /im cmd.exe /t /f /fi "windowtitle eq $nametitle"
echo "Taskkill complete. Press any key to continue..."
pause | out-null
exit}
}

Automating batch files and powershell script execution

The goal is to automate the execution of 3 files:
A batch file that runs a selenium webdriver automated test suite.
Another batch file that generates a reports for the tests run in step 1.
A PowerShell script that attaches the reports and sends an email.
How can I automate the execution of these 3 files so that upon running a command or executing a file, all 3 are executed?
This is how my PowerShell looks like:
$Username = "";
$Password = "";
function Send-ToEmail([string]$email, [string]$attachmentpath) {
$message = New-Object Net.Mail.MailMessage;
$message.From = "c#c.com";
$message.To.Add($email);
$message.Subject = "abc";
$message.Body = "abc";
$attachment1 = New-Object Net.Mail.Attachment($attachmentpath);
$message.Attachments.Add($attachment1);
$smtp = New-Object Net.Mail.SmtpClient("build3", "25");
$smtp.EnableSSL = $false;
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($message);
Write-Host $smtp.EnableSSL;
Write-Host "Mail Sent";
}
Send-ToEmail -email "a#a.com" -attachmentpath "C:\file1";
Send-ToEmail -email "b#b.com" -attachmentpath "C:\file1";
This is what the first batch file looks like:
FOR /F "TOKENS=2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%A
FOR /F "TOKENS=2,3 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=2,3,4 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET yyyy=%%C
SET todaysdate=%yyyy%%mm%%dd%
start /d "nunitPATH" nunit3-console.exe "seleniumtestsuite dll PATH" --where:cat==SignUp --result="xmlreportPATH"
This is what the second batch file looks like:
start /d "exeFilePATH" ReportUnit.exe "folderPATH"
Simply write a batch script that runs
call script1.bat
call script2.bat
D:\path\to\powershell.exe -File script3.ps1
If you need async:
start script1.bat
start script2.bat
start "" "D:\path\to\powershell.exe" "-File" "script3.ps1"
Note the pair of double quotes before powershell.exe path.
Note that this assumes your device has at least powershell v2
However, this question is a duplicate of here

How do I plug in a file I select in a powershell file selector gui?

I found a powershell script to open up a gui filepicker now how do I get the file I pick in it to be plugged into a variable? Also I have a program called binsmp that replaces hex in files from the command line how would I plug the file into that?
#echo off
setlocal
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
echo You chose %%~I
)
goto :EOF
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Roms (*.sfc;*.smc)|*.sfc;*.smc|All Files (*.*)|*.*"
$f.ShowHelp = $false
$f.Multiselect = $false
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
binsmp filename -paste paste.txt
Assuming that the filename part of your binsmp invocation is where the actual filename is supposed to be, give this a try:
<# :
:: launches a File... Open sort of file chooser and outputs choice(s) to the console
:: https://stackoverflow.com/a/15885133/1683264
#setlocal
#echo off
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
binsmp %%~I -paste paste.txt
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
You broke it when you removed the totally non-standard/supported powershell comment block around the actual cmd script code.