Monthly Archives: May 2014

Start or stop BizTalk Applications using PowerShell

This is not actually something new but for anyone else that wants to quickly have a reference to it, here are two PowerShell scripts to stop and start BizTalk applications.

Stopping a specified Application:

if ($args.count -eq 0) {
  "You must specify the BizTalk Application name to stop!"
}
else{
    $BTSAppName = $args[0]
    $SQLInstance = "."
    $BizTalkManagementDb ="BizTalkmgmtdb"
    [void] [System.reflection.Assembly]::LoadWithPartialName("Microsoft.BizTalk.ExplorerOM")
    $Catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $Catalog.ConnectionString = "SERVER=$SQLInstance;DATABASE=$BizTalkManagementDb;Integrated Security=SSPI"

    $BTSApp = $Catalog.Applications[$BTSAppName]
    if ($BTSApp.Status -ne "stopped")
    {
        "Stopping" + $BTSApp.Name
        $BTSApp.Stop("StopAll")
        $catalog.SaveChanges()
    }
    else
    {
        $BTSApp.Name + " is already stopped"
    }
}

Starting a specified Application:

</pre>
<pre>if ($args.count -eq 0) {
  "You must specify the BizTalk Application name to start!"
}
else{
    $BTSAppName = $args[0]
    $SQLInstance = "."
    $BizTalkManagementDb ="BizTalkmgmtdb"
    [void] [System.reflection.Assembly]::LoadWithPartialName("Microsoft.BizTalk.ExplorerOM")
    $Catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $Catalog.ConnectionString = "SERVER=$SQLInstance;DATABASE=$BizTalkManagementDb;Integrated Security=SSPI"

    $BTSApp = $Catalog.Applications[$BTSAppName]
    if ($BTSApp.Status -ne "started")
    {
        "Starting " + $BTSApp.Name
        $BTSApp.Start("StartAll")
        $catalog.SaveChanges()
    }
    else
    {
        $BTSApp.Name + " is already started"
    }
}

List all .Net versions using PowerShell

A quick tip (script) how to list all the .Net (major) versions of a list of machines.

$serverListFile = "<Path to file>\computers.txt";
$computers = Get-Content -path $serverListFile

$BASEDOTNETPATH = "\c$\Windows\Microsoft.NET\Framework\"

function CheckNet45($computerName){
  $NETROOTKEY = "SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4"
  $keyname = $NETROOTKEY + "\\Full"
  try{
    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $computerName)
    if ($reg -ne $null){
      if ($reg.OpenSubKey($keyname).GetValue("Version").ToString().StartsWith("4.5")){
        return $True
      }
    }
  }
  catch {
    #do nothing
  }
  return $False
}

foreach($computer in $computers)
{
  $computer
  $ok = Test-Connection $computer -Count 1 -Quiet
  if ($ok) {
    $computerBasePath = "\\" + $computer + $BASEDOTNETPATH
    $versionStr = ""
    if (Test-Path ($computerBasePath + "v1.0.3705")){
      $versionStr = $versionStr + "1.0,"
    }
    if (Test-Path ($computerBasePath + "v1.1.4322")){
      $versionStr = $versionStr + "1.1,"
    }
    if (Test-Path ($computerBasePath + "v2.0.50727")){
      $versionStr = $versionStr + "2.0,"
    }
    if (Test-Path ($computerBasePath + "v3.0")){
      $versionStr = $versionStr + "3.0,"
    }
    if (Test-Path ($computerBasePath + "v3.5")){
      $versionStr = $versionStr + "3.5,"
    }
    if (Test-Path ($computerBasePath + "v4.0.30319")){
      $versionStr = $versionStr + "4.0,"

      if (CheckNet45($computer)){
        $versionStr = $versionStr + "4.5,"
      }
    }
    $versionStr = $versionStr.TrimEnd(',')
    "  Installed version(s): " + $versionStr

  }
  else{
   " Is not pingable!"
  }
}

All you have to do is create a text file with a list of machine names (one name per line). It does assume you have Admin rights so you can access the C$ share and read the remote registries.

A little (versioning) pain with Powershell

First thing to mention is I’m not complaining about PowerShell itself or functionality provided with PowerShell. Rather, this is a problem with referencing it from .Net (C#) and versioning when used on another machine where the .Net App was deployed and happen to have an older version of PowerShell (PS for short).

Scenario

If you want to run PowerShell scripts from a C# program like I’m doing in QuickMon now, you have to add a reference to “System.Management.Automation.dll“. I happen to have Version 4.0 of PowerShell on the computer where the C# app is compiled. Now, this is all fun and games until you want to run the same app on another machine that only have, say Version 2.0 of PowerShell. PS 2 does have a version of System.Management.Automation.dll but somehow it is not compatible (at run time). When I compiled the same app on a computer that only has V2.0 of PowerShell and deploy that app to machines that has either PS v2.0 or v4.0 it works on all of them.

If this was C++ it would have made sense (dll versioning very strict) but this is a C# app that supposively should not care about the version of the referenced assembly (and yes, this is a .Net assembly). The methods (I) used in the dll are all the same of both versions.

I even tried generating the System.Management.Automation.dll file manually on the ‘target’ machine and copy that dll to the App’s directory (using the PS “Copy ([PSObject].Assembly.Location) C:\” command) but this gave other versioning referencing errors.

Possible solution

The solution that seems to work for now is to set the ‘Specific Version‘ property on the referenced dll in the C# project to true (making sure it points to the PS 2.0 related version – dll version 6.1.7601.17514). Interestingly enough when switching the project to ‘release’ configuration it display pointing to ‘C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll’. That tells me the PS version ‘2.0’ of that assembly is still available (on my PS 4.0 computer). As a safety precaution I also set the ‘Copy Local’ property on this referenced dll to True to have it deployed with the app.

Deploying this combination seems to work on all ‘target’ machines – I even saw it working on a computer that only has PS 1.0!

All fun and joy… as long as there’s no lawyer sitting on a loo in the bush… with an angry T-Rex nearby…