Executing a Powershell Script Through Batch File

Executing a Powershell Script Through Batch File

I am trying to execute a powershell script through a batch file, at the moment I am only testing this to get it running so the .ps1 file is simply a hello world script.

This ALMOST works fine except there is a spanner to throw into the works;

I am trying to have the .ps1 stored in a remote location (on a shared NAS to be specific). This works when I have the .ps1 saved locally and point the .bat to the local .ps1.

However now that the .ps1 is in the remote location I am thrown with the following error;

"file (pathname) cannot be loaded. The file (pathname) is not digitally signed. The script will not execute on the system"

Now I am aware of execution policies and mine are as follows;

MachinePolicy  =   RemoteSigned
UserPolicy     =   Undefined
Process        =   Undefined
CurrentUser    =   RemoteSigned
LocalMachine   =   Bypass

I have tried changing CurrentUser to Bypass but I am thrown with the following;

Windows Powershell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope

Any ideas would be greatly appreciated!

Sorry if this has been a lot of information! If any of it is unclear feel free to ask me to clarify! I'm fairly new to all of this!

1

8 Answers

You can still run the script - you just need to tell PowerShell to bypass the system's executionpolicy like this:

powershell.exe -executionpolicy bypass -file \\server\share\yourscript.ps1

I think the GroupPolicy configured by the company is enforcing the policy to revoke any execution of script from the remote location. Kindly check the Group Policy in the Administrative tools.

2

The other answer might actually be the answer, but in case you (or anyone else) is looking for a workaround, here it is.

In your batchfile, first copy the .ps1 file to a local folder, such as C:\TEMP, and then execute it by using start c:\temp\My_Script.ps1

The command start will make the script work the same way as double clicking it from explorer. You might not actually need to copy it locally if you used a different way to start the file.

2

For the .bat only aspect, a work around would be to make a .bat file that used echo statements to build a local powershell script, then execute the local script

How practical this would be would depend on how complex the script needed to be

This is what I use:

Standard Powershell, no admin elevation:

PowerShell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File ""c:\your\file\path\PSscript.ps1""'}"

Prompting for admin credentials:

PowerShell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File ""c:\your\file\path\PSscript.ps1""' -Verb RunAs}"

Posted it also here:

Following this thread:

you can convert any PowerShell script into a batch file easily using this PowerShell function:

function Convert-PowerShellToBatch
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [string]
        [Alias("FullName")]
        $Path
    )
 
    process
    {
        $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
        $newPath = [Io.Path]::ChangeExtension($Path, ".bat")
        "@echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
    }
}


To convert all PowerShell scripts inside a directory, simply run the following command:

Get-ChildItem -Path <DIR-PATH> -Filter *.ps1 |
  Convert-PowerShellToBatch

Where is the path to the desired folder. For instance:

Get-ChildItem -Path "C:\path\to\powershell\scripts" -Filter *.ps1 |
  Convert-PowerShellToBatch


To convert a single PowerShell script, simply run this:

Get-ChildItem -Path <FILE-PATH> |
  Convert-PowerShellToBatch

Where is the path to the desired file.

The converted files are located in the source directory. i.e., <FILE-PATH> or <DIR-PATH>.

Elyasaf755, Thank you very much. I turned your converter into a batch file, onto which multiple ps1 files can be simultaneously dropped to convert to batch, or it can be clicked upon to convert all psi files in the current folder.

REM    POWERSHELL TO BATCH CONVERTER

REM    DRAG & DROP ONE OR MULTIPLE POWERSHELL FILES ONTO THIS BATCH,

REM    OR CLICK ON IT TO CONVERT ALL POWERSHELL SCRIPTS IN THE FOLDER

REM    AND THEIR BATCH VERSIONS WILL BE CREATED IN THE SAME DIRECTORY

if [%1]==[] goto :CLICKED

:loop
SET INPUT=%1
if [%1]==[] goto :EOF

:DROPPED
REM    COPIES ALL LINES FROM THIS BATCH WHICH DO NOT HAVE "A1B2XZ" IN THEM TO "ZZZZZAMA.TXT"
if not exist "ZZZZZAMA.TXT" FINDSTR /V /L /I /C:"A1B2XZ" "%~0">> "ZZZZZAMA.TXT"

REM    "X_VARIABLE_X" STANDS FOR THE PATH TO THE FILE YOU DRAGGED & DROPPED 
REM    "X_VARIABLE_X" GETS REPLACED WITH THE REAL PATH FROM "%INPUT%"

SET "search="X_VARIABLE_X""
SET "replace=%INPUT%"
SET "File=ZZZZZAMA.TXT"
SET "Destination=ZZZZZAMA2.TXT"

setlocal DisableDelayedExpansion
for /F "TOKENS=* EOL= delims= " %%a in ('"findstr /n ^^ "%File%""') DO (
   set "line=%%a"
   
   setlocal EnableDelayedExpansion
   set "line=!line:*:=!"
REM    IF THE LINE IS BLANK IN THE INPUT, IT WRITES A BLANK LINE TO THE OUTPUT FILE   
   if [!line!]==[] ( 
   
      echo.>> "!Destination!"

REM    IF THE LINE IS NOT BLANK IN THE INPUT, IT WRITES THE LINE TO THE OUTPUT FILE
REM    REPLACING YOUR SEARCH WORD, IF IT EXISTS, WITH THE REPLACE WORD    
   ) else (
  
      echo(!line:%search%=%replace%!>> "!Destination!"
      
   )
   endlocal
)

REM    CTEATES "CONVERTER.PS1" FROM A PORTION OF TEXT IN "ZZZZZAMA2.TXT"
REM    NOTE:    A1B2XZ MUST STAY IN THE FOUR LINES BELOW

ECHO($config = Get-Content "ZZZZZAMA2.TXT" -Raw>> "YMCA.PS1" & REM A1B2XZ
ECHO( if ("$config" -Match '(?ms)YOUR_TEXT_BELOW_ME(.*?)YOUR_TEXT_ABOVE_ME') {>> "YMCA.PS1" & REM A1B2XZ
ECHO(    $matches[1].Trim() ^| Set-Content 'CONVERTER.PS1'}>> "YMCA.PS1" & REM A1B2XZ
powershell -NoProfile -ExecutionPolicy Bypass -File "YMCA.ps1" & DEL /Q /F "YMCA.ps1" & REM A1B2XZ

REM     SKIPS THE BLOCK POWERSHELL SCRIPT BELOW WHICH HAS ALREADY BEEN MADE INTO A FILE
goto :MoveOn

REM     DO NOT REMOVE THE LINE BELOW [ BEGIN OF POWERSHELL SCRIPT "CONVERTER.ps1" ]
YOUR_TEXT_BELOW_ME

##    POWERSHELL TO BATCH CONVERTER

##    AS THIS SCRIPT IS AUTOMATED, DO NOT WRITE YOUR PATH AT THE BOTTOM

##    AND IT WILL CREATE THE BATCH IN THE SAME DIRECTORY


function Convert-PowerShellToBatch
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [string]
        [Alias("FullName")]
        $Path
    )
 
    process
    {
        $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
        $newPath = [Io.Path]::ChangeExtension($Path, ".bat")
        "@echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
    }
}

Get-ChildItem -Path "X_VARIABLE_X" |
  Convert-PowerShellToBatch

YOUR_TEXT_ABOVE_ME
REM     DO NOT REMOVE THE LINE ABOVE [ END OF POWERSHELL SCRIPT "CONVERTER.ps1" ]

:MoveOn

REM     IT RUNS THE POWERSHELL SCRIPT NAMED "CONVERTER.ps1" TO CONVERT YOUR FILE
powershell -NoProfile -ExecutionPolicy Bypass -File "CONVERTER.ps1" 

REM     THE FILES BELOW MUST BE DELETED FOR THE SEQUENCE IN THIS SCRIPT TO WORK
del /f /q "CONVERTER.ps1"
del /f /q "ZZZZZAMA2.TXT"

REM     THE TWO LINES BELOW PROVIDE THE LOOP FOR MULTIPLE FILES DRAGGED & DROPPED
shift
if not [%1]==[] goto loop

EXIT

:CLICKED

REM    COPIES ALL LINES FROM THIS BATCH WHICH DO NOT HAVE "A1B22XZ" IN THEM TO "ZZZZZAMA3.TXT"
if not exist "ZZZZZAMA3.TXT" FINDSTR /V /L /I /C:"A1B22XZ" "%~0">> "ZZZZZAMA3.TXT"

REM    CTEATES "CONVERTER3.PS1" FROM A PORTION OF TEXT IN "ZZZZZAMA3.TXT"
REM    NOTE:    A1B22XZ MUST STAY IN THE FOUR LINES BELOW - AN EXTRA 2 WAS ADDED

ECHO($config = Get-Content "ZZZZZAMA3.TXT" -Raw>> "YMCA3.PS1" & REM A1B22XZ
ECHO( if ("$config" -Match '(?ms)WRITE_UNDER_ME(.*?)WRITE_ON_TOP_OF_ME') {>> "YMCA3.PS1" & REM A1B22XZ
ECHO(    $matches[1].Trim() ^| Set-Content 'CONVERTER3.PS1'}>> "YMCA3.PS1" & REM A1B22XZ
powershell -NoProfile -ExecutionPolicy Bypass -File "YMCA3.ps1" & DEL /Q /F "YMCA3.ps1" & REM A1B22XZ

REM     SKIPS THE BLOCK POWERSHELL SCRIPT BELOW WHICH HAS ALREADY BEEN MADE INTO A FILE
goto :MoveOn3

REM     DO NOT REMOVE THE LINE BELOW [ BEGIN OF POWERSHELL SCRIPT "CONVERTER3.ps1" ]
WRITE_UNDER_ME

##    POWERSHELL TO BATCH CONVERTER

##    AS THIS SCRIPT IS AUTOMATED, DO NOT WRITE YOUR PATH AT THE BOTTOM

##    AND IT WILL CREATE THE BATCH IN THE SAME DIRECTORY


function Convert-PowerShellToBatch
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [string]
        [Alias("FullName")]
        $Path
    )
 
    process
    {
        $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
        $newPath = [Io.Path]::ChangeExtension($Path, ".bat")
        "@echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
    }
}

Get-ChildItem -Path "." -Filter *.ps1 |
  Convert-PowerShellToBatch

WRITE_ON_TOP_OF_ME
REM     DO NOT REMOVE THE LINE ABOVE [ END OF POWERSHELL SCRIPT "CONVERTER3.ps1" ]

:MoveOn3

REM     IT RUNS THE POWERSHELL SCRIPT NAMED "CONVERTER3.ps1" TO CONVERT YOUR FILE
powershell -NoProfile -ExecutionPolicy Bypass -File "CONVERTER3.ps1" 

REM     THE FILES BELOW GET DELETED
del /f /q "CONVERTER3.ps1"
del /f /q "ZZZZZAMA3.TXT"
del /f /q "CONVERTER3.BAT"
EXIT





____________________ END OF THE BATCH ABOVE __________________




BELOW ARE TWO BATCH HERESTRING SCRIPTS WHICH ARE EXACTLY THE SAME,
BUT ONE IS A MULTI-LINER AND THE OTHER A ONE-LINER:




REM    _____________  HERESTRING - BATCH MULTI-LINER  _____________

REM    EXTRACTS TEXT BETWEEN TWO SEARCH PATTERNS = STRINGS OR LINES.

REM    USE IT TO EMBED A POWERSHELL SCRIPT INTO A BATCH, OR ADAPT 

REM    THE EXTENSIONS & LAUNCHER ACCORDINGLY TO EMBED A VBSCRIPT.

REM    NOTE:  A PIPE "|" HAS BEEN ESCAPED AS "^|". 

REM           \s+ ENSURES THAT ONLY THE SEARCH PATTERNS FOLLOWED 

REM           BY SPACE ARE FOUND, THUS SKIPPING THE COMMAND LINE.

REM           THE SEARCH PATTERNS, ESCAPED HERE WITH BRACKETS, ARE: 

REM           [YOUR_TEXT_BELOW_ME] & [YOUR_TEXT_ABOVE_ME].


SETLOCAL ENABLEDELAYEDEXPANSION & SET "SOURCE=%~0"
ECHO.$config = Get-Content "!SOURCE!" -Raw>> "TTTT.ps1"
ECHO.if ("$config" -Match '(?ms)YOUR_TEXT_BELOW_ME\s+(.*?)YOUR_TEXT_ABOVE_ME\s+') {>> "TTTT.ps1"
ECHO.$matches[1].Trim() ^| Set-Content 'YOUR_TEXT.ps1'}>> "TTTT.ps1"
powershell -NoProfile -ExecutionPolicy Bypass -File "TTTT.ps1" & "YOUR_TEXT.ps1"
del /f /q "TTTT.ps1" "YOUR_TEXT.ps1" & ENDLOCAL & goto :MoveOn & YOUR_TEXT_BELOW_ME


  YOUR TEXT HERE


YOUR_TEXT_ABOVE_ME & DO NOT REMOVE THIS LINE

:MoveOn

EXIT



OR



REM    _____________  HERESTRING - BATCH ONE-LINER  _____________

SETLOCAL ENABLEDELAYEDEXPANSION & SET "SOURCE=%~0" & ECHO.$config = Get-Content "!SOURCE!" -Raw; if ("$config" -Match '(?ms)YOUR_TEXT_BELOW_ME\s+(.*?)YOUR_TEXT_ABOVE_ME\s+') {$matches[1].Trim() ^| Set-Content 'YOUR_TEXT.ps1'}>> "TTTT.ps1" & powershell -NoProfile -ExecutionPolicy Bypass -File "TTTT.ps1" & "YOUR_TEXT.ps1" & del /f /q "TTTT.ps1" "YOUR_TEXT.ps1" & ENDLOCAL & goto :MoveOn & YOUR_TEXT_BELOW_ME


  YOUR TEXT HERE


YOUR_TEXT_ABOVE_ME & DO NOT REMOVE THIS LINE

:MoveOn

EXIT


 

 



From what I've gathered in my own explorations of the topic, batch (or cmd) does not work with network locations. Additionally, from what I can see in your first post, you skipped some parts of the set-executionpolicy cmdlet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Sophia Al-Mansoor
Author

Sophia Al-Mansoor

Sophia analyzes international trade, startup ecosystems, retail transformation, and supply chain logistics for modern digital publications.