Home Blog Converting Scripts to EXEs

Converting Scripts to EXEs

ISESteroids 2.0 Enterprise offers the capability to turn a PowerShell script into an application (EXE file).

Let’s check out what exactly happens here, why it could be benefitial, and what the drawbacks are.

Addition: There may have been a false impression that wrapping PowerShell scripts into EXE applications would/could be a safe way of hiding PowerShell code. I decided to highlight some parts of this blog in red. I did not change anything, it has always been in the blog article. 

How does it work?

A PowerShell script will always stay a PowerShell script. It will always require PowerShell to be present on the system. When you convert a script to an Application, you basically generate a wrapper application that contains your script, and unpacks and launches it when needed.

Reasons to wrap a PowerShell script inside an applications include:

  • Ease of use: When you hand over scripts to audiences that are not familiar with PowerShell, this approach makes it easier for them to launch a script.
  • Source Code Protection: Your PowerShell source code is somewhat protected. People cannot easily peek at your code, and change it. The level of protection depends on how you create the application. We’ll cover this in a bit.

Turning a Script into an Application

To turn your current script into a stand-alone application, in ISESteroids choose Tools/Create Application. This pops up a wizard.

Simply click “Create” to create the EXE. For more options, click the arrow in “Advanced Options”.

Advanced Options include the ability to assign a custom icon to your application, require Administrator privileges, and more.

Trusting Your Application

When you ship your script as application, your target audience can no longer openly review the source code. You are basically delivering a “black box”, which might exactly be what you intended.

Your target audience may be worried about this.  At minimum, they will run your application through an Antivirus engine.

AV engines end up having the very same problem: depending on their quality, they may not be able to look at the actual script content, either. When that occurs, the AV engine may at least detect that it is looking at some kind of wrapper application. Since the AV engine can’t tell whether the PowerShell code inside of it is benign or not, it may simply freak out and flag the application as “Virus”, just to be on the safe side. It is a false alarm.

To be clear: ISESteroids does not put any malicious code into the generated application. False virus alarms are an inherent limitation of some AV engines.

Increasing Source Code Protection

Wrapper applications are never a safe way of protecting your script content. This is by nature, because the person that launches the application must have full read access to the application.

With full read access, it is always technically possible to reverse-engineer the wrapping, and get to the original PowerShell code. This is why you should never place sensitive information into PowerShell scripts, regardless of how you ship them, and what tool you used to “wrap” it.

If you want to increase the level of source code protection, there are several ways:

  • Loading from Memory: when you have a relatively short script, you can use the Advanced Options, and choose “Load Script From Memory”. Now, the wrapper application will not unpack the script and run it as a file, but rather feed it directly into PowerShell.
  • Obfuscating Application: The generated application is a standard .NET application. You can use any commercial or free obfuscator software to “scramble” the .NET code inside of it. So even if someone uses reverse engineering tools to examine your wrapper application, it will now be much harder to get to the information (and PowerShell code).

That said, please understand that there is no perfect protection. This is a technical limitation that applies to all products that wrap PowerShell code inside an application. You can  only increase the effort that it takes to get to your code. You cannot prevent this access, though.

Even if an application came up with an extremely hard-to-reverse-engineer technique, an attacker could target the PowerShell process that is actually executing your code, and dump your code from there.

So use this technique wisely. Use it to make launching PowerShell easier, and to keep mere mortals from looking at your code. Do not use it to protect vital secrets such as passwords inside your scripts.




Facebooktwittergoogle_pluspinterestlinkedinFacebooktwittergoogle_pluspinterestlinkedin  rssrss

  • What if I wanted to do the opposite? Take a compiled PowerShell executable and decompile it back to a ps1 script file.

  • Tobias Weltner

    There is no built-in functionality for that. Why would you want to do this?

  • DeployGuy

    I have encountered this issue when using AutoIt a script language so I can relate to the question.
    I used AutoIT heavily before powershell. With AutoIT and its built-in compiler you had an option to include the script into the exe created, since the exe was zip compatible, if you included the script in the exe you could always retrieve it if you lost the source code. I was always afraid I would lose my scripts. The creative mine is not always the most diligent with housekeeping.
    Of course this validates the Dr. Tobias’s comments, never, ever put in sensitive info. In a commercial environment where a security breach can cost millions, companies bring in auditors to search the network for scripts with passwords and sensitive information, even in your development areas and when those audits reveal that sensitive information is being exposed, it must be removed. So DON”T do it, no matter how convenient it is. If you do you are taking the easy path, going to the Dark side and exposing yourself to a CEA (Career Ending Event).
    Since the exe produced by ISE Steroids is not in zip format but .net the option to save the script in the exe in easily extractable form is not available. That is a good thing.
    So it is very important to make sure your source code is backed up as there is, nor there should be an easy way to extract the script.
    Remember the 3 rules of data protection.
    1. Backup
    2. Backup
    3. Backup

  • Stanvy

    Unfortunately, I unable to find any info on how to pass in parameters to “compiled” script neither if it’s possible at all. Does your wrapper provide this functionality?

    • Tobias Weltner

      You can use a default param() block in your script. When you turn it into an exe, the exe will support the same parameters.
      We completely redesigned the exe creator in which will be released next week. We’ll then also have a blog post explaining in detail all of your options.


      Hello i’ve have just dowloaded IseSteroids and made a test by wrapping an actual script in an exe and launched it inside the exec command in windows and adding param value in “the classic and standard way : ” -parameterer1 value
      Exemple : D:softFirewallManage.exe -add -tccport 1135
      and it have worked.
      As it’s a wrapper i support that the argument that your provide to the exe are basically passed to the ps1 file that is launched under the scene (or when the script is directly feed to poweshell “runtime” in the load memory option)
      (I’ m a rookie in powershell world and not a prof developper so sorry for eventual poor word choice)

  • Apathetic

    Is there more documentation on this? Can I run as -verbose or -debug to view the console output when run from powershell? can I use hidden, and then write in a section that pops up to let the user know when something will take a couple minutes?

    • Tobias Weltner

      The EXE files created by ISESteroids work just like regular scripts, so you can add a param() block to the beginning of your script, and then later pass exactly these arguments to your exe. If you add [CmdletBinding()]param(…) then you also have access to the common parameter like -Verbose etc, and when your script uses Write-Verbose, the messages appear in your console when you launch the EXE with -Verbose. Just like a script. The same applies to automatic variables. $PSScriptRoot points to the EXE file. You can even use parameters like -? to show comment based help.

  • Fabian Danner

    Is there a way to build the exe for older Framework versions?