1

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

Screenshot of above error

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 8

4

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
1

Posted it also here:
https://stackoverflow.com/questions/46070152/how-to-run-powershell-command-in-batch-file/65911978#65911978

Following this thread:
https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/converting-powershell-to-batch


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>.

0

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
  • I think you might be about to make me look very silly.... I tested this on my PC first, which is domain connected and will have access to the NAS. The PC i have been second testing this on is just a local account! Never even crossed my mind! I'll give it a try! Thanks! :)
    – Csothcott
    Mar 8, 2016 at 15:57
  • Unfortunately no Joy, there is no restrictions on the NAS anyway and I can access it without entering any credentials on the non domain PC :(
    – Csothcott
    Mar 8, 2016 at 16:36
0

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
  • Unfortunately I can not use this as a work around. We are using an external program to send packages to the PC. This package can send .bat but not .ps1, this is the reason for having to have .bat files launch the .ps1 if this makes sense?
    – Csothcott
    Mar 8, 2016 at 16:36
  • Why not? Your .bat file accesses the .ps1 file in a way doesn't it? So if your .bat file accesses the .ps1 file, it can also copy it. If you edit your original post and include the contents of your .bat file (feel free to rename some paths) I'll edit my answer and write you how the .bat file should look.
    – LPChip
    Mar 8, 2016 at 17:11
0

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

0

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}"
0

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


 

 



0

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .