Unbinding BizTalk orchestrations with PowerShell - powershell

What is the cleanest way to unbind an orchestration using PowerShell?
I'd like to have something that works on both 32bit and 64bit platform.
I know I can load and use the Microsoft.BizTalk.ExplorerOM assembly (forcing 32bit mode with something like "Start-Job -RunAs32") and do something similar to what is explained here: http://msdn.microsoft.com/en-us/library/dd792703(v=bts.10).aspx
But I'd like to find something better.

I see the sample script you linked is loading this DLL from the GAC:
[System.reflection.Assembly]::LoadWithPartialName("Microsoft.BizTalk.ExplorerOM")
I'm not familiar with this assembly but if it's pre-compiled to x86 in the GAC then you'll need to load it with 32bit PowerShell (when on a 64bit Windows system). In your script you can do a check to see what PowerShell process bitness is:
if ( [IntPtr]::Size -eq 4 ) { # x86 } else { # x64 }
If your script is not running in the right bitness there's three things I can think of:
Start a 32 bit background job as you noted
Re-launch your script using 32 bit PowerShell (doesn't work well if your script has params):
if (-not $correctBitness) {
Start-Process "C:\WINDOWS\syswow64\windowspowershell\v1.0\powershell.exe" -ArgumentList "-file", $Invocation.MyCommand.Path
exit
}
Tell the user they need to re-launch the script using the 32 bit PowerShell and exit.

Related

PowerShell 6 - support for Windows GUI libraries

I understand that the new PowerShell 6/core lacks support for Windows GUI libraries, I have developed some important projects in PS-5.1 using the Windows.Forms .NET classes.
Problem:
We are planning to upgrade to PowerShell 6 this summer, which means I will lose all the GUI functionalities (developed using Windows.Forms).
Question:
What should we do in this situation in order to retain the GUI functionality in our PS apps. Do you envisage Microsoft will provide any alternatives for GUI support going forward?
TIA
thanks to all who added informative comments.
After a bit of research I discovered that the XAML UI is going to be available in the .NET Core, its support has been added the Universal Windows Platform and Xamarin applications, hence it will be available in PowerShell core/6 for GUI solution development.
Development in XAML appears to be very straight forwards, in fact, in some aspects - easier and quicker than other APIs (especially if you have to hand code the UI components).
One question I have is what you mean by "Upgrading" to PowerShell 6? On Windows there is no upgrade. You will run PowerShell 6 side-by-side with your existing version of PowerShell. So, if you want to keep running your old scripts that use GUI stuff, keep doing so in PowerShell 3, 4 or 5.1. If you want to start using PowerShell 6 in order to write scripts that will function on all platforms, then use PowerShell 6 for that. The good news is, you will continue to have both. (for now at least)
It's a russian method, but you can use for the non-PowerShell Core compatible part the default PowerShell "powershell.exe" instead of PowerShell Core "pwsh.exe" in your PowerShell Core script:
Test.ps1:
<# Here you start your script code with your called PowerShell/PowerShell Core: #>
$PSVersionTable
chcp.com 65001;
<# Pause the PowerShell Core code execution and run here a temporary default PowerShell session
(Non-PowerShell Core) for the Non-PowerShell Core compatible code part: #>
powershell -NoProfile -ExecutionPolicy Bypass -Command {
$PSVersionTable
chcp.com 65001;
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing");
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms");
$objForm = New-Object System.Windows.Forms.Form;
[void] $objForm.ShowDialog();
<# Exit the temporary default Non-PowerShell Core session: #>
exit
}
<# And continue here the PowerShell Core script code #>
$PSVersionTable
This works fine for me with Visual Studio Code and also CLI-only execution with System PowerShell (currently: v5.1) and with the PowerShell Core (currently: v6.1.2).
It's not the best solution and Windows only, but a workaround for Windows systems with installed PowerShells.

Powershell running a cmdlet from a called script

I have a script that calls another script (with arguments). The called script contains the Install-WindowsFeature cmdlet. When I run the script, the called script runs, but returns the following error:
Install-WindowsFeature : The term 'Install-WindowsFeature' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path
Of course, I can run the cmdlet just fine from a PowerShell console. I can also run the called script from a PowerShell console and Install-WindowsFeature works fine. So, is it something to do with calling a script from a script that runs a cmdlet? Here is my calling code:
$script = "C:\Path\script.ps1"
$argumentList = #()
$argumentlist += ("-Arg1", "value")
$argumentlist += ("-Arg2", "value")
$argumentlist += ("-Arg3", "value")
Invoke-Expression "$script $argumentList"
In the called script, I called Install-WindowsFeature as below:
if ($someValue) { Invoke-Command -ScriptBlock {Install-WindowsFeature -Name RSAT-AD-Tools} }
I've also tried it as below:
if ($someValue) { Install-WindowsFeature -Name RSAT-AD-Tools }
12/16/16 EDIT: This script is running in a GUI built with Sapien PowerShell Studio. When I change the build type to "Native" it works. I have to reset my lab to check, but I suspect it will also run if I just run it in the x64 context. This article explains why I think this matters.
Running on Windows Server 2012 R2
Unless you've got a compelling reason for it, let's see if we can clean up your calling pattern a bit - and hopefully make your other issues go away by avoiding the contortionism.
Rather than creating your parameter list as a string, take advantage of parameter splatting. It's good to get out of the habit of treating PowerShell like other scripting languages that don't work with objects.
$splat = #{
Arg1 = "value1";
Arg2 = "value2";
Arg3 = "value3"
}
& c:\path\script.ps1 #splat
Using that on a script.ps1 something like this:
param(
$Arg1,
$Arg2,
$Arg3
)
Write-Host "Arg1 = $Arg1, Arg2 = $Arg2, Arg3 = $Arg3
You'll get an expected output of:
Arg1 = value1, Arg2 = value2, Arg3 = value3
Once you've got that, there's probably no reason to use Invoke-Command on the call to Install-WindowsFeature, unless you're leaving out details like invoking remotely to a server. Invoke-Command { Install-WindowsFeature } still works fine for me on Server 2012R2 with PowerShell 5, and there's no reason it shouldn't.
This assumes you're running this script on a Server that support Install-WindowsFeature, as the other comments point out. Client Windows doesn't support Install-WindowsFeature, and the RSAT tools are installed via a stand-alone RSAT .MSU package, which you manage differently.
Install-WindowsFeature is natively provided with Server Manager on Server 2012R2 - there's no need to Import-Module... unless you've done something to your profile or fouled up your modules folders. One of the earlier versions of Windows Server needed it - but that was a couple versions back. Likewise, Add-WindowsFeature was the old name - and it's still available as an alias for Install-WindowsFeature.
I'm assuming you've tried Install-WindowsFeature directly from the command line to ensure it's in working order, and Get-Module Install-WindowsFeature looks reasonable.
PS C:\Windows\system32> get-module ServerManager
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 2.0.0.0 ServerManager {Get-WindowsFeature, Install-WindowsFeature, Uninstall-Win...
While we're on the topic, there's very little reason to drop to DISM on Server that supports Install-WindowsFeature, and a number of reasons not to.
Server Manager and several other tools (including Win32_ServerFeature) rely on the feature states parsed and understood by the WMI provider used by Install-WindowsFeature. It's possible to enable the right set of features using DISM, but needs attention and detail. Enabling only "part" of a role and feature may get the functionality you want for specific cases, but the role or feature may not show up as installed in Get-WindowsFeature, may not be uninstallable via Remove-WindowsFeature, and may not offer relevant UI features in Server Manager like monitoring health of the role, viewing relevant events, or offering tools for administering it.
Install-WindowsFeature integrates with additional code from the role & features you're installing, and may run additional health and pre-requisite checks to ensure your correctly configured.
DISM featurenames tend to change more often than the role & feature name of Server Manager, so your script portability will be better.
There are other points, but I won't go into them since DISM was primarily a comment fork.
You are probably right, it seems like the script gets executed with x86 PowerShell. I want to share a snippet with you which I use for scripts that needs to run in a specific environment (e. g. x64 PowerShell).
The script restarts itself in a x64 PowerShell if its started as x86 process. Just put this at the top of your script:
# Reinvoke the script as x64 if its called from a x86 process.
if ($env:Processor_Architecture -eq "x86")
{
&"$env:windir\sysnative\WindowsPowerShell\v1.0\powershell.exe" -noprofile -file $myinvocation.Mycommand.path -executionpolicy bypass
exit
}
Also note that the Install-WindowsFeature cmdlet doesn't work on all windows versions so consider to use dism instead:
$featuresToInstall = #('RSAT-AD-Tools')
$dismParameter = #('/online', '/Enable-Feature', ($featuresToInstall | % { '/FeatureName:{0}' -f $_ }), '/NoRestart')
dism #dismParameter
The running environment determines what modules you have access to. When I created this project in PowerShell Studio, it took the default of x86 (a 32 bit environment). This worked but because I was running it on Windows Server 2012 R2 (a 64-bit environment) I did not have access to the powershell modules such as Import-Module and Install-WindowsFeature. Changing this to a x64 project resolved my issue.
In order to avoid this scenario, it is important to make sure you run PowerShell scripts and modules in the architecture that is native to the OS. You can do this by setting the project correctly (if using a tool like PowerShell Studio) or by verifying that you are running in the native mode for that OS with the code Martin Brandl provided.

Enqueuing MSI installs - via Powershell

I'm trying to install both the 32-bit and the 64-bit versions of Visual Studio 2005 as part of a Powershell script on our Win2008 instances. When I try to invoke the installation of both EXE files without a break, the second EXE (x86) doesn't execute since the x64 one hasn't finished installing.
So, I added a 5 sec sleep after each invoke and that seems to work now. However, I'm not very happy with this solution as it looks more like a workaround than a proper way to handle the task at hand.
Is there a better way to do this - maybe enqueue the files for install - so they execute one after another?
Here are the specific lines of code:
if ($OSArchitecture -eq "64-bit")
{ Write-Output "Found 64-bit OS. Installing both VC++ files for compat"
start-process .\vcredist_x64.exe /Q
start-sleep 5
start-process .\vcredist_x86.exe /Q
start-sleep 5
}
You must use the Start-Process -Wait parameter.
-Wait Waits for the specified process to complete before accepting more input. This parameter suppresses the command
prompt or retains the window until the process completes.

Powershell: Script to run with x86 powershell/ise

The script i've created uses componets which are only available with the 32 bit version of powershell.
By default windows excutes the script with powershell x64 and it causes several errors.
Is the a way to set an value at the beginning of a script to force windows to use powershellx86 instead of x64?
Example:
using powershell(x86).exe
scriptblock
Thank you
Couldn't you just start the "powershell(x86).exe" file?
%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
/Fredrik
There is no straightforward way to do it, but there is a way to invoke another instance of Powershell host in x64 host, and that instance may as well be x86. $env:PROCESSOR_ARCHITECTURE will tell you what version of Powershell host you are running.
Just a sketch, use chisel and sand paper to finish.
function Execute-Scriptx86
{
param(
[Parameter(Mandatory=$True,Position=1)]
[string]$ScriptFile
)
if($env:PROCESSOR_ARCHITECTURE -eq "AMD64")
{
$powershellx86 = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell.exe"
& $powershellx86 -File $ScriptFile
}
else
{
& $ScriptFile
}
}

Creating an executable .exe file from a PowerShell Script?

Is it possible to create an executable file.exe file from a PowerShell Script?
No. At least, not yet, and after 5 versions of PowerShell, it seems unlikely ever.
I wish I could just leave it at that, but other people have provided a bunch of "workaround" type answers I feel compelled to address:
You can wrap your .ps1 script in another script type to make it double-clickable, and you can even generate an executable with the script embedded (see the other answers on this thread) ... but those "executables" require the right version of PowerShell to be already present on the system, so you're not gaining anything by doing that, and you loose a lot of the features of PowerShell (like streaming object output, help documentation, and automatic parameter handling with tab completion for users).
Here is a simple .cmd batch file wrapper (you could extend this to allow parameters):
REM <#
copy %0 %0.ps1
PowerShell.exe -ExecutionPolicy Unrestricted -NoProfile -Command "&{Set-Alias REM Write-Host; .\%0.ps1}"
del %0.ps1
exit
REM #>
### Your PowerShell script goes below here.
### I've put a couple of lines as an example ...
ls | sort length -desc | select -first 5 | ft
ps | sort ws -desc | select -first 10 | ft
I know ...
With Portable PowerShell, it would probably be possible to package up a sort of self-extracting zip that would contain the right version of PowerShell and a script and would work. That's not an executable in any normal sense of the word -- it's a bit like if Valve had decided to just ship a vmware image on a thumbdrive as their solution to letting Linux users play Half Life. However, the product seems abandoned.
With PrimalScript (or PowerShell Studio) or PowerGui or pShellExec, your script can be encrypted, so it's slightly secured against prying eyes ... but this is basically just obfuscation, and essentially no different than the batch file, and in some ways worse.
Out of the box - no. However I have built a PowerShell script that can take a script and create an EXE wrapper around it. I created this script a while ago but decided to blog it here for folks to check out.
Use PowerGUI's Script Editor (it is free and works). Open your script in the PowerGUI Script Editor > Tools > Compile script > Choose whatever options you would like for your .exe (password protect source code, automatically close console after .exe runs, etc.).
Yes, there is a option with PS2EXE to create such *.exe Files.
Usage
The whole thing is really simple and well explained nevertheless
here is a snippet of it:
C:\Scripts\PS2EXE\PS2EXE_0.5.0.0.0\ps2exe.ps1
-inputFile C:\Scripts\ExampleEXE\example.ps1
-outputFile C:\Scripts\ExampleEXE\example.exe -sta -noConsole -runtime40 -verbose -x64
The only bad thing is that the project is depreciated. No Updates or new Versions since 2015.
EDIT:
This projected has been picked up and is being maintained by a new person now. You can find the updated code here, last updated 01/04/2018 as of this edit.
https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-GUI-Convert-e7cb69d5
Version Information
For adding and editing the version information use something like VERPATCH.
UPDATE 2019
Shout out to a git-repo which is called PythonEXE.
It demonstrates how to create an executable from a Python project and also provides a YouTube Step-By-Step Guide.
I understood your question as "Can my PowerShell script generate an executable?" That is what I was trying to do when I found this post. That is possible using the Add-Type command.
Add-Type -TypeDefinition #"
using System;
class Program {
public static void Main(string[] args) {
Console.WriteLine("Hello World!");
}
}
"# -CompilerParameters #{
"GenerateExecutable" = $true
"OutputAssembly" = "test2.exe"
}
PrimalScript from Sapien will generate an exe from a PowerShell script. The machine one which the executable is run must have PowerShell installed.
The solution I found best to distribute a PowerShell script as exe was to wrap it in a NSIS executable.
I write a .nsi script like this:
Name "Maintenance task"
OutFile "maintenance.exe"
ShowInstDetails show
Section "Main"
;Executes the "script-to-run.ps1" PowerShell script
InitPluginsDir
SetOutPath "$pluginsdir\MyOrg" ;It is better to put stuff in $pluginsdir, $temp is shared
;extract the .ps1 and run it, collecting output into details.
File script-to-run.ps1
nsExec::ExecToLog 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "$pluginsdir\MyOrg\script-to-run.ps1" '
SetOutPath $exedir
SectionEnd
I just have to compile the script to an exe with the NSIS toolchain, and it will run on any OS that has PowerShell, no matter what is the execution policy.
This was inspired by this question How to call PowerShell in NSIS.
There's a project called Portable PowerShell that is still in beta after a couple of years ... might be worth looking at for your needs.
http://shelltools.wik.is/Portable_PowerShell