Scoregraphic
Scoregraphic

Reputation: 7200

PowerShell script acts different when run from C# application then from PowerShell ISE

I'm trying to automate BizTalk deployment using the available PowerShell commands (https://psbiztalk.codeplex.com). Things are working when I run my script from the PowerShell ISE UI. But I want to have my own UI for the deployment and this is where my problem is. The script behaves different and doesn't find any resources at one point which leads to errors (currently):

Type 'Microsoft.BizTalk.ApplicationDeployment.ResourceCollection' in Assembly 'Microsoft.BizTalk.ApplicationDeployment.Engine, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.

The output of the Get-ApplicationResourceSpec would be a System.Xml.XmlDocument object. It seems as the command cannot find the BizTalk application resources from the hosted PowerShell stuff, but the ISE environment can so I think it should be possible somehow.

Any ideas and/or help is appreciated.

PowerShell script:

$SnapIn = Get-PSSnapin | Where-Object { $_.Name -eq "BizTalkFactory.PowerShell.Extensions" }
if ($SnapIn -eq $null)
{
    Add-PSSnapin -Name "BizTalkFactory.Powershell.Extensions"
}

Set-Location -Path BizTalk:
cd "BizTalk:\Applications"
Get-ApplicationResourceSpec -Path "MyTestApplication"

Call from C# application

string script = File.ReadAllText("GetResources.ps1")));

Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();

Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(script);

StringBuilder builder = new StringBuilder();
Collection<PSObject> objects = pipeline.Invoke();
foreach (PSObject obj in objects.Where(t => t != null))
{
    builder.AppendLine(obj.ToString());
}

runspace.Close();

UPDATE

As the BizTalk PowerShell commands are open source, I digged a little deeper and tried to isolate the failing command(s). I found the following code to give different results:

# Replace Get-ApplicationResourceSpec -Path "MyTestApplication" from the
# other script with these lines
$App = Get-ChildItem | Where-Object { $_.Name -eq $Application } | Select-Object -First 1
$Group = New-Object Microsoft.BizTalk.ApplicationDeployment.Group
$Group.DBName = $App.Catalog.Database
$Group.DBServer = $App.Catalog.Instance
$Group.SqlConnection.ConnectionString

In the ISE environment, the ConnectionString is set to a valid value but not in the C# case. This leads to non-existing resources in the second case:

$App = $Group.Applications["MyTestApplication"]
$App.ResourceCollection.Count # equals 88 vs. 0

So it seems that the BizTalk internal type Microsoft.BizTalk.ApplicationDeployment.Group doesn't behave the same way. Any more ideas on this finding?

Upvotes: 2

Views: 568

Answers (2)

Jeroen Maes
Jeroen Maes

Reputation: 673

Try changing the startup mode in your config file:

<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
</configuration>

As written on the BizTalk360 Blog:

... else when you try to access the resource collection, you’ll receive the following error

Type ‘Microsoft.BizTalk.ApplicationDeployment.ResourceCollection’ in Assembly ‘Microsoft.BizTalk.ApplicationDeployment.Engine, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′ is not marked as serializable.

This is because of the support for side-by-side runtimes, .NET 4.0 has changed the way that it binds to older mixed-mode assemblies. These assemblies are, for example, those that are compiled from C++\CLI. Mixed mode assembly is built against version ‘v1.1.4322′ of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.

Also, as you are writing a C# application, be aware of the fact that you can reference the BizTalkFactory.Management.Automation.dll and BizTalkFactory.HealthAndActivity.Automation.dll in your project and achieve the same thing without the need for PowerShell:

The BizTalk Factory Management Automation is designed to be a supporting library for the BizTalk PowerShell Provider, but it can be used as a standalone project that does not incur any dependencies on PowerShell. This makes it an ideal candidate for use in your own programming projects around administrating and manipulating BizTalk artifacts. psbiztalk on CodePlex

Upvotes: 1

Tim Long
Tim Long

Reputation: 13778

I can't claim to have any expertise in this area, but it seems clear that there is some sort of environmental difference between PowerShell ISE and your hosted environment.

The runtime grumbling about something not being serializable suggests that it is being marshalled across a process boundary, or possibly between application domains, both of which require the object to be serializable. Are your objects loading into different AppDomains, by any chance?

Upvotes: 1

Related Questions