How to Use a Batch File to Make PowerShell Scripts Easier to Run

998
How to Use a Batch File to Make PowerShell Scripts Easier to Run

Here we can see, “How to Use a Batch File to Make PowerShell Scripts Easier to Run”

PowerShell scripts aren’t as portable and usable as batch scripts for various reasons, the most important of which is security. To go around these limitations, we can bundle a batch script with our PowerShell scripts. Here, we’ll go over a number of those issues and work around them with a batch script.

Why can’t I just copy my .PS1 file to another computer and run it?

Unless the target system has been pre-configured to execute arbitrary scripts with the proper privileges and using the appropriate parameters, you’re likely to run into some issues.

  1. By default, PowerShell is not connected with the.PS1 file extension.

This was first mentioned in our PowerShell Geek School course. Windows has a connection. Instead of sending PS1 files to the PowerShell command interpreter, they are sent to Notepad by default. This is to prevent dangerous scripts from being executed by accident when double-clicked. There are ways to change this behavior, but you don’t want to do it on every computer where you carry your scripts, especially if some computers aren’t your own.

2. By default, PowerShell does not allow the execution of external scripts.

In all versions of Windows, the ExecutionPolicy setting in PowerShell disables the execution of external scripts by default. Script execution is disabled by default in several Windows editions. We showed you how to alter this setting in How to Allow the Execution of PowerShell Scripts on Windows 7. This isn’t something you want to perform on just any computer, either.

Also See:  How to: Fix This Site May Harm Your Computer in Google Chrome

3. Without Administrator permissions, some PowerShell programs will not run.

To accomplish specific operations, even with an Administrator-level account, you must first pass through User Account Control (UAC). We don’t want to disable it, but it’s always wonderful when we can make things a little easier.

4. Some users may change PowerShell environments.

You probably won’t come across this very often, but it can be a pain to run and troubleshoot your scripts when you do. Fortunately, we can get around this without having to make any long-term modifications.

Step 1: Double-click to run.

Let’s start with the most basic issue: PS1 file associations. You can’t double-click.PS1 files to run them, but you can do so with.BAT files. As a result, we’ll create a batch file that will automatically run the PowerShell script from the command line.

It will use a self-referencing variable to generate the file path for the PowerShell script, so we won’t have to rewrite the batch file for every script or every time we move a script around. To make this work, you’ll need to put the batch file in the same folder as your PowerShell script and give it the same name. So, if your PowerShell script is called “MyScript.ps1,” name your batch file “MyScript.bat” and save it in the same folder as your PowerShell script. Then add the following lines to the batch script:

@ECHO OFF
PowerShell.exe -Command "& '%~dpn0.ps1'"
PAUSE

That would be all it takes to launch a PowerShell script from a batch file if it weren’t for the other security constraints. In actuality, the first and last lines are mostly a question of personal preference; the second line is the one that works. Here’s how it works:

The command echoing is turned off with @ECHO OFF. When the batch file starts, this prevents your other commands from appearing on the screen. The usage of the at (@) sign in front of this line hides it from view.

The PowerShell script is run with PowerShell.exe -Command “& ‘%~dpn0.ps1′” PowerShell.exe, like any other CMD window or batch file, can be used to start PowerShell to a bare console.

Using the -Command parameter and the proper arguments, you can use it to run commands directly from a batch file how this is used to target ours. The %~dpn0 variable is used in the PS1 file. When run from a batch file, %~dpn0 returns the batch file’s drive letter, folder directory, and file name (without extension). Because the batch file and the PowerShell script are in the same location and have the same name, %~dpn0.ps1 will be translated to the PowerShell script’s complete file path.

PAUSE pauses the batch process and awaits user input. This is a good idea to include at the end of your batch files.

So that you have time to look over any command output before the window closes, the utility of this will become clearer as we test each step.

As a result, the basic batch file has been created. This file is saved as “D:\Script Lab\MyScript.bat” for demonstration purposes, and there is also a “MyScript.ps1” in the same folder. Let’s see what happens when MyScript.bat is double-clicked.

The PowerShell script didn’t run, but that’s to be expected given that we’ve only addressed the first of our four issues. However, there are a few key points highlighted here:

  1. The title of the window indicates that the batch script successfully started PowerShell.
  2. The first line of output indicates the use of a custom PowerShell profile. This is the above-mentioned possible problem #4.
  3. ExecutionPolicy limitations are in force, as evidenced by the error notice. That is our second issue.
  4. The error message’s underlined portion (done natively by PowerShell’s error output) confirms that the batch script correctly targeted the appropriate PowerShell script (D:\Script Lab\MyScript.ps1). So, at the very least, we know that a lot of things are working well.

In this scenario, the profile is a simple one-line script used to generate output whenever the profile is active. If you want to test these scripts yourself, you can customize your PowerShell profile to do so. Adding the following line to your profile script is all it takes:

Write-Output 'Custom PowerShell profile in effect!'

On this test system, the ExecutionPolicy is set to RemoteSigned. This permits the execution of locally written scripts (such as the profile script) but prevents scripts from outside sources from being executed unless a trustworthy authority signs them. The following command was used to mark MyScript.ps1 as being from an external source for demonstration purposes:

Add-Content -Path 'D:\Script Lab\MyScript.ps1' -Value "[ZoneTransfer]`nZoneId=3" -Stream 'Zone.Identifier'

That tells Windows that the file came from the Internet by setting the Zone. Identifier alternate data stream on MyScript.ps1. It’s simple to undo with the following command:

Clear-Content -Path 'D:\Script Lab\MyScript.ps1' -Stream 'Zone.Identifier'

Step 2: Getting around ExecutionPolicy.

It’s quite simple to get around the ExecutionPolicy setting from CMD or a batch script. We add one more parameter to the PowerShell.exe command in the second line of the script.

PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"

When you spawn a new PowerShell session, the -ExecutionPolicy parameter can change the ExecutionPolicy. This won’t last beyond that session, so we can use PowerShell like this whenever we want without jeopardizing the system’s overall security. Let’s give it another shot now that we’ve fixed that:

We can see what the script does now that it has been properly executed. It’s informing us that the script is being run as a Limited user. User Account Control is getting in the way of the script running an account with Administrator permissions.

Though it is beyond the scope of this article to go into detail about how the script checks for Administrator access, here is the code that is being used for demonstration:

if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{Write-Output 'Running as Administrator!'}
else
{Write-Output 'Running Limited!'}
Pause

You’ll also notice that the script output now contains two “Pause” operations, one from the PowerShell script and the other from the batch file. In the next step, the reason for this will become clearer.

Step 3: Getting Administrator access

You can skip the remainder of this if your script doesn’t run any commands that require elevation and you’re confident that no one’s custom profiles will get in the way. However, if you’re using Administrator-level cmdlets, you’ll need this.

Also See:  Evercade Reveals a New Retro Games Console Called the Evercade VS

Unfortunately, you can’t use a batch file or a CMD session to activate UAC for elevation. Start-Process in PowerShell, on the other hand, allows us to achieve this. Start-Process will attempt to run an application with Administrator permissions if given the “-Verb RunAs” argument.

If the PowerShell session isn’t already elevated, a UAC prompt will appear. To use this from the batch file to run our script, we’ll need to create two PowerShell processes: launch Start-Process and run the script. The batch file’s second line should be updated to this:

PowerShell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"

The PowerShell profile script will be the first line of output when the batch file is run. When Start-Process tries to run MyScript.ps1, a UAC prompt will appear.

A new PowerShell instance will appear after you click through the UAC prompt. We’ll see the profile script notice again because this is a new instance. Then, after running MyScript.ps1, we can see that we are in an elevated session.

That’s also why there are two pauses in this section. We wouldn’t see the script’s output if it weren’t for the one in the PowerShell script – the PowerShell window would pop up and disappear as soon as the script finished running. We wouldn’t be able to see if any errors were launching PowerShell in the first place without the pause in the batch file.

Step 4: Getting around custom PowerShell profiles

Let’s get rid of that obnoxious custom profile message right now, shall we? It’s hardly a bother in this case. Still, it can be extremely inconvenient if a user’s PowerShell profile modifies default settings, variables, or functions in ways you didn’t expect with your script. You don’t have to worry about this because it’s much easier to run your script without the profile. All we have to do now is change the second line of the batch file once more:

PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"

Bypassing the -NoProfile parameter to both PowerShell instances launched by the script, the user’s profile script is completely bypassed in both steps. Our PowerShell script runs in a fairly predictable default environment. You can see that neither of the spawned shells has a custom profile noticed.

If you’ve skipped step 3 and don’t need Administrator rights in your PowerShell script, you can skip the second PowerShell instance, and the second line of your batch file should look like this:

PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"

(Of course, you could skip the end-of-script pause in your PowerShell script for non-Administrator scripts because everything is captured in the same console window and would be retained there any way by the pause after the batch file.)

Completed batch files

Whether or not you require Administrator permissions for your PowerShell script (and you shouldn’t), the final batch file should resemble one of the two examples below.

If you don’t have administrative access:

@ECHO OFF
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"
PAUSE

With admin privileges, you can:

@ECHO OFF
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"
PAUSE

Remember to save the batch file in the same folder as the PowerShell script you’ll be using and name it the same. Then, regardless of which machine you transfer those files to, you’ll be able to run your PowerShell script without having to fiddle with any of the system’s security settings. You could easily make those adjustments by hand each time, but this saves you time and eliminates the need to worry about undoing the changes later.

Conclusion

I hope you found this information helpful. Please fill out the form below if you have any questions or comments.

User Questions:

  1. What is the process for converting a batch file to a PowerShell script?

There is no way to convert batch file scripts to PowerShell with a tool. You’ll have to rewrite a batch file script if you want a PowerShell script to replace it. No tool can help you with this.

  1. Can I use PowerShell to run a batch file?

Most of the time, you run Windows batch files through the Command Execution Method, which is similar to running them through a command prompt window (cmd.exe). Anyone can use the start-process cmdlet because it is a standard PowerShell cmdlet.

  1. Is PowerShell a better alternative to CMD?

PowerShell is more difficult to use than the traditional Command Prompt, but it is also more powerful. The Command Prompt pales in comparison to shells for Linux and other Unix-like systems, but PowerShell holds its own.

Also See:  How to: Fix Can’t Upload Pictures From My Camera on Windows 10
  1. Run the batch file’s PowerShell script.

Run powershell script from batch file from PowerShell

  1. Running batch script to run the PowerShell script. Needs to run in the background

Running batch script to run powershell script. Needs to run in background from learnprogramming