Sunday, October 30

Unable to load DLL 'BAUtil.dll': Invalid access to memory location error when using a 32-bit host with a domain group in BizTalk Server

Following on from this post, when you change the Host Instance to a 32-bit host, you may get the error described above. Something like -  "Unable to load DLL 'BAUtil.dll': Invalid access to memory location. (Exception from HRESULT: 0x800703E6)"
This issue occurs if the domain user account that is configured as the BizTalk host instance cannot read the following registry key: HKEY_LOCAL_MACHINE\Software\Microsoft\BizTalkAdapters\Config.

Basically, cthe biztalk applicaiton users group user that you used to configure the host instance is typically not a member of any group on the local computer (the BizTalk Server Machine), and therefore is restricted on the BizTalk Server Machine.

Depending on security considerations, one quick fix is to add the BizTalk Applicaiton Users group to local Administrators on the local machine. This is not the recommended approach, but could at least allow a quick fix in emergency situaitons and / or troubleshooting situations

The Microsoft recommended approach as seen in this post is to modify the registry by granting Read permissions on the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\BizTalkAdapters\Config.

  1. Click Start, click Run, type Regedit, and then click OK.
  2. Locate the following registry key:
    HKEY_LOCAL_MACHINE\Software\Microsoft\BizTalkAdapters\Config
  3. Right-click the registry key that you located in step 2, and then click Permissions.
  4. On the Security tab, click Add.
  5. Type the domain group or the domain user account that is configured as the BizTalk host instance, and then click OK.
  6. On the Security tab, click the domain group or the domain user account that you added in step 5, click to select the Read check box, and then click OK.
  7. Exit Registry Editor.

Friday, October 28

Microsoft.BizTalk.Adapters.CoreTransmitter.dll Not Found error when using the BizTalk Enterprise Adapter for PeopleSoft

There are numerous white papers on the BizTalk Enterprise Adapter for PeopleSoft. It is a wonderful tool, but unfortunately, none of these white papers thoroughly covers the challenges you may face in getting it up and running.


This post continues from this post in explaining some challenges you might face whilst using this Adapter, with the solutions I discovered.


Also read this post for the next error you are likely to encounter


When using the adapter Enterprise Adapter for PeopleSoft with BizTalk Server 2010 on a 64 bit server like Windows 2008 server, you will most likely get an error of the type:


The Messaging Engine failed to create the transport adapter "PeopleSoft".
OutboundAssemblyPath: "NULL"
OutboundTypeName: "Microsoft.BizTalk.Adapters.PeopleSoftTransmitter, Microsoft.BizTalk.Adapters.CoreTransmitter, Version=1.0.5025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Exception Details: "Could not load file or assembly 'Microsoft.BizTalk.Adapters.CoreTransmitter, Version=1.0.5025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified."



For me, a search through the Internet produced little or no results.This error is actually caused because the dll it is seeking is a 32-bit dll and it is in the 32-bit GAC in C:\Windows\Assembly.


In order to use this dll, you therefore need to configure your PeopleSoft port to use a 32-bit Host. In my case, Sendhost was our default host, running in 64-bit mode. All our hosts were specifically allocated as we had a whole host of applications. I created a new host (in this case the BizTalkServerApplication host, as we had no need for it before now). I set the host to run in 32-bit mode and created a new host instance running on the domain app users group
  1. Open BizTalk Server Administration Console
  2. Open the BizTalk Group
  3. Open Platform Setings and Right-click on Hosts, select New, Host
  4. Type a name for the host (BizTalkServerApplicaiton in my case, but most times, this host would already be in use, so you can create a new host with a descriptive name of your choosing)
  5. Select In-Process for the Host Type, and tick the 32-Bit Only box for the mode under Options
  6. In the Windows Group box, type in your BizTalk Application Users Group (If you're in a large organization, then this would most likely be a domain group like it was in my case - read the next post for a fix to the error that is generated for domain groups). Click Apply and OK
  7. Right-click on the new Host you have just created, select New, Host Instance
  8. For the Server, select the correct server instance and click on the Configure button
  9. For the Logon and password , enter the credentials for a BizTalk instance user in the BizTalk Application Users Group (I'm afraid the correct setup of the BTS Application Users Group is out of the scope of this post). Click OK, Apply and OK
  10. Start the new Host Instance (Right-click and click Start)
Go back to your PeopleSoft port (the one you created by following the configuraiton instructions in my previous post).


Right-click on the port, click on Properties and change the Send Handler to the new host


This should fix the error described above.


Next post: Error message 'Unable to load DLL 'BAUtil.dll': Invalid access to memory location' error when using a 32-bit host with a domain group in BizTalk Server

Thursday, October 27

Force an exception with a Throw Exception shape and send the notification using the ESB Portal from an Orchestration Send Port

Sometimes you might wish to force your application to throw an exception if the processing logic goes down a certain decide branch, just to inform the tester or support administrator that the message is being terminated according to plan. the example below forces an exception and sends customized information to the ESB portal

Looking at the post, some might wonder why the scope and exception block? Well, ESB has a known bug - if you try to use the message assignment expression used below outside an exception handler, you will create an endless loop on your host instance. This bug is better described here

1.       In your orchestration, add a reference to Microsoft.Practices.ESB.ExceptionHandling and Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults (Open your project, Richt-Click on References à Add Reference à .Net)
2.       Create a Scope of transaction type None. Create a variable of .Net type System.ApplicationException (found in mscorlib) called excApplication
3.       Add an Expression Shape called ‘CreateException’ in this scope
4.       Add a Throw Exception Shape called ‘ThrowException’. In the Throw Exception Shape properties, enter the exception object you created above as the exception object type (i.e. excApplication)
5.       Create an orchestration Message called ‘msgESBFault’ of type Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage
6.       Right-click on the scope and add a new Exception Handler called ‘ThrowExceptionHandler’
7.       In the Exception properties, enter exApplicationobj as the exception object name
8.       In the Exception properties, Select  System.ApplicationException as your exception object type (found in .Net Exception à mscorlib à system à ApplicationException)
9.       Add a Construct Message Shape called ‘ConstructESBFaultmsg’ with Message Assignment Shape  called ‘AssignESBFaultmsg’ and Send Shape called ‘SndESBFaultmsg’
11.    Add ‘Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage’ as the Message Type of the direct send port’s Operation
12.    In the Message Assignment shape, generate the ESB fault message and the ESB message such as:
// create new fault message msgESBFault=Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage();
// set fault message properties
msgESBFault.FaultCode="0202";
msgESBFault.FaultDescription="Exception notification from branch <branch descriptor> of orchestration <orchestration name>" + System.Environment.NewLine + "InnerXML is: " + exApplicationobj.InnerException.ToString();
msgESBFault.FailureCategory="Exception notification from branch <branch descriptor> of orchestration <orchestration name>";
msgESBFault.FaultSeverity=Microsoft.Practices.ESB.ExceptionHandling.FaultSeverity.Information;
//Add the fault message to the original message
Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.AddMessage(msgESBFault, <Originalmsg>);
13.    Connect the send shape ‘SndESBFaultmsg’ to the direct send port

Create a Delivery Failure Exception Catching Process from an Orchestration Send Port using the ESB Portal

Note that, as explained in posts including this post by Kevin B Smith in 2004, the performance cost of using delivery notifications can be up to 50% depending on design. Therefore, for Request-Response ports, you can use the SOAP error handling capabilities instead of using delivery notification
  1. In your orchestration, add a reference to Microsoft.Practices.ESB.ExceptionHandling and Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults (Open your project, Richt-Click on References à Add Reference à .Net)
  2. Create a Scope of Transaction Type ‘None’. You can also set the scope synchronization to true depending on your requirements. (This will suspend processing of the orchestration until the acknowledgement (Ack/Nack) has been received for the transmitted message)
  3. Add your operations for which you wish to catch the exception in this scope (make sure any messages to be used in the exception catching block are created outside this scope, though they can also be created within the scope if they must be, but some extra steps will be needed to initializie the message properly)
  4. On the Send port from which you wish to capture the delivery failure exception, in the properties, change the ‘Delivery Notification’ Type to ‘Transmitted
  5. Create orchestration Message called ‘msgESBFault’ of type Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage
  6. Right-click on the scope and add a new Exception Handler
  7. In the Exception properties, Enter ‘DeliveryExceptionobjmsg’ as the Exception Object Name (or a name of your choosing)
  8. In the Exception properties, Select .Net Exception type Microsoft.XLANGs.BaseTypes.DeliveryFailureException as the Exception Object Type
  9. Add an Expression Shape called ‘WriteTraceLog’, a Construct Message Shape called ‘ConstructESBFaultmsg’ and a Send Shape called ‘SndESBFaultmsg’.
  10. Within the construct message shape, add a Message Assignment shape called ‘AssignESBFaultmsg’.
  11. Add a direct-bound Send Port ‘ESBFaultPort’ of Type ESBFaultPortType (See step 11 in earlier post Create a Soap Exception Catching Process from an Orchestration Request-Response Port using the ESB Portal)
  12. Add ‘Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage’ as the Message Type of the direct-bound send port’s Operation
  13. In the Message Assignment shape, generate the ESB fault message and add your original message (from the actual scope) such as:
    // create new fault message msgESBFault=Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage();
    // set fault message properties
    msgESBFault.FaultCode="0202";
    msgESBFault.FaultDescription="Delivery notification from port <portname> " + System.Environment.NewLine + "InnerXML is: " + DeliveryExceptionobjmsg.InnerException.ToString();
    msgESBFault.FailureCategory="Delivery notification from port <portname>";
    msgESBFault.FaultSeverity=Microsoft.Practices.ESB.ExceptionHandling.FaultSeverity.Severe;
    //Add the fault message to the original message
    Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.AddMessage(msgESBFault, msgFromOutsideScope);
  14. Connect the send shape ‘SndESBFaultmsg’ to the direct send port
  15. In the Expression shape called ‘WriteTraceLog’, add the event log entry and debug helper messages such as:  System.Diagnostics.Trace.WriteLine("Delivery notification from port <portname>");

WCF errors: simple jargon-free problem and solution approach

There are lots of big terms in internet posts about WCF but it is actually a very simple concept once you can achieve an understanding of it's fundamental ideology. Getting to the core of the methodology can be very daunting for beginners. I just thought I'd make a growing journal of errors I encountered in my first WCF implementations (which I have just discovered nicely noted in one of my old work journals. Hope these will help asomeone out there at some point....

P: You get the error The message could not be processed because the action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT' is invalid or unrecognized” when trying to implement wshttpbinding configuraiton with establishsecuritycontext set to false

S: Most likely caused because your ser4vice reference did not update the establishSecurityContext attribute of the Message element in the binding configuration. This is a VS bug
In your client configuraiton (app.config) manually add the establishSecurityContext="true" attribute to the message node of the security element for the relevant binding. e'g
<message clientCredentialType="Windows" negotiateServiceCredential="true"establishSecurityContext="true" algorithmSuite="Default" />

P: when using the svcutil tool to generate metadata from a wsdl, you get an error of the type "the t option requires that a value be specified"
S: You have most likely added a space between the /t and :metadata in the svcutil.exe command syntax. Remove the space so the command is of the form 'svcutil.exe /t:metadata http:/getme/data.wsdl (where http/getme/data.wsdl is the url of the service wsdl). See this link for more information  on the tool


P: After making changes to a BizTalk IIS-hosted WCF service, when trying to use the service from a client you get constant timeouts. On checking events, you find the BizTalk error "The Messaging Engine received an error from transport adapter "WCF-CustomIsolated" when notifying the adapter with the BatchComplete event. Reason "Attempted to access an unloaded AppDomain."."
S: Reset IIS


P: When publishing your BizTalk application as a wcf service, you get an error of the sort "The Messaging Engine failed to register an adapter.... Details: "Registering multiple adapter types within the same process is not a supported scenario. For e.g. HTTP and SOAP receive adapters cannot co-exist in the same process "
S: You need to create a new applicaiton pool for the service. An isolated host instance can run only one adapter. If you configure the receive handlers of HTTP and SOAP adapters with the same isolated host, you must create two application pools, one application pool for each adapter


P: 'An existing connection was forcibly closed by the remote host' error when using a wcf service - more often than not occurs with large files…”
S: The first port of call for this is to amend your web.config file in the wcf service and increase the maxBufferPoolSize and maxReceivedMessageSize in your binding configuration. (If connecting from BizTalk, you should also increase these values in your port binding configuration from the default .Net value of 65, 356 bytes. This is not the probem in this case anyway, as this would have given you a different error). Setting the attribute transferMode="Streamed" in this section also helps to minimize memory impact

In my case, I was using a WCf service as a wrapper for extra protection to modify and send an xml file to an old-fashioned xmlhttpRequest web page hosted in PeopleSoft. the configuration above (which I had already done when building the wcf service anyway) did not solve the problem. If changing those settings does not work, add a httpruntime config setting in the System.Web section of your web.config file as shown below, using values that work more with your expected message size etc:

<httpRuntime executionTimeout="90" maxRequestLength="200000000" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100"/>
  </system.web>


P: Trying to load a WCF web service and getting error similar to “the runtime is built with a newer runtime…”
S: Browse to Application Pool in IIS (double click) and change the runtime to the same runtime as the one specified in your web service web.config file’s target framework declaration
(e.g. targetFramework="4.0") – This solution may lead to the next error

P: When trying to browse your web service svc file in a IIS hosting environment, you get the error HTTP Error 500.21 - Internal Server Error
Handler "svc-Integrated" has a bad module "ManagedPipelineHandler" in its module list
S: IIS is not properly registered with visual studio – Open visual studio command prompt (run as administrator if using Vista) and type aspnet_regiis.exe –i

P: trying to browse your web service svc file in a IIS hosting environment, you get the error ‘The protocol 'net.pipe' is not supported’
S: IIS 5 and 6 only support http-based bindings. Remove any bindings that do not use one of the http-based protocols to remove this error

P: wcftestclient command runs your client successfully, but once in IIS environment, you get the error ‘Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.’
S: You need to add a metadata exchange (mex) endpoint to your service config file:
Something like:
<services> 
   
<service name="NewService.Service1" behaviorConfiguration="metadataBehavior"> 
     
<endpoint  
         
address="http://localhost/MyService.svc"  
         
binding="customBinding" bindingConfiguration="jsonpBinding"  
         
behaviorConfiguration="MyService.MyService" 
         
contract="MyService.IMyService"/> 
     
<endpoint  
         
address="mex"  
         
binding="mexHttpBinding"  
         
contract="IMetadataExchange"/> 
   
</service> 
</services> 

P: you want to create a wcf service but you don't want the default tempuri.org namespace on your generated schemas
S: You need to add a namespace attribute to your ServiceContract declaration:
Something like:
[ServiceContract( Namespace = "http://www.mynamespace.com/myfunctions.anythingelse" )]

Create a Soap Exception Catching Process from an Orchestration Request-Response Port using the ESB Portal

  1. In your orchestration, add a reference to Microsoft.Practices.ESB.ExceptionHandling and Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults (Open your project, Richt-Click on References > Add Reference > .Net and double-click on Microsoft.Practices.ESB.ExceptionHandling and use the same process for Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults )
  2. In your orchestration, create a Scope of Transaction Type ‘None’
  3. Add your operations for which you wish to catch the exception in this scope (make sure any messages to be used in the exception catching block are created outside this scope, although the message can also be created within the scope if necessary, in which case extra steps will need to be taken to initialize the message)
  4. On the Request-Response port from which you wish to capture the soap exception, Right-click on the port Operation and create a new orchestration Message called ‘Soapfaultmsg’ of Type ‘BTS.soap_envelope_1__1.Fault’. (you can find this type in Referenced Schemas à Microsoft.BizTalk.globalPropertySchemas)
  5. Create an orchestration Message called ‘msgESBFault’ of Type Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage (Schemas >Select from referenced assemblies)
  6. Create orchestration Message called ‘msgSoapFault’ of type System.Xml.XmlDocument
  7. Right-click on the scope and add a new Exception Handler called ‘CatchSoapException’
  8. In the Exception properties, Enter ‘SoapExceptionobjmsg’ as the Exception Object Name (or any other descriptive name you choose)
  9. In the Exception properties, Select ‘<Your Request-Response Port>.<Your Request-Response Port Operation>. Soapfaultmsg’ as the Exception Object Type
  10. In the Exception Handler, add an Expression Shape called ‘WriteTraceEventLog’, Construct Message Shape called ‘ConstructESBFaultmsg’ and a Send Shape called ‘SndESBFaultmsg’. In the construct message shape, add a Message Assignment Shape called ‘AssignESBFaultmsg’
  11. Add a direct Send Port ‘ESBFaultPort’ of Type ‘ESBFaultPortType’ (See steps below)
    • Add a Send Port Shape to the left or right Port Surface in the orchestration designer
    • On the ‘Welcome To The Port Configuratio’n page that opens up in the Port Configuration Wizard, click Next
    • In the Port Properties, enter ‘ESBFaultPort’ as the port name. Click Next
    • On the ‘Select A Port Type’ page, select ‘Create a new Port Type’, in the ‘Port Type Name’ field, enter ‘ESBFaultPortType’, Select ‘One-Way’ as the port Communication Pattern and leave the ‘Access Restrictions’ on the default (Internal). Click Next
    • On the ‘Port Binding’ page, In the ’Port direction of Communication’ drop-down, select ‘I’ll always be sending messages on this port’. In the ‘Port Binding’ drop-down, select ‘Direct’ as the binding method. Leave the default values. Click Next
    • On the ‘Completing the Port Wizard’ page, click Finish
  12. Add ‘Microsoft.Practices.ESB.ExceptionHandling.Schemas.Faults.FaultMessage’ as the message type of the direct send port’s Operation (see step 5 above)
  13. In the Message Assignment shape, generate the ESB fault message and add your original message (from the actual scope – see full sample for more information) such as:
    msgSoapFault = SoapExceptionobjmsg;
    // create new fault message msgESBFault=Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage();
    // set fault message properties
    msgESBFault.FaultCode="0001";
    msgESBFault.FaultDescription="SOAP Exception whilst requesting Information from blah-blah system:" + System.Environment.NewLine + "InnerXML is: " + msgSoapFault.InnerXml.ToString();
    msgESBFault.FailureCategory="SOAP Exception whilst requesting Information from wcf service";
    msgESBFault.FaultSeverity=Microsoft.Practices.ESB.ExceptionHandling.FaultSeverity.Severe;
    //Add the fault message to the original message Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.AddMessage(msgESBFault, msgFromOutsideScope);
  14. Connect the send shape ‘SndESBFaultmsg’ to the direct send port ESBFaultPort
  15. In the Expression shape called ‘WriteTraceEventLog’, add the event log entry and debug helper messages such as:  System.Diagnostics.Trace.WriteLine("SOAP Exception whilst requesting Information from <The SOAP Port Service> system"); System.Diagnostics.EventLog.WriteEntry("<Your Application Name>", "SOAP Exception whilst requesting Information from <The SOAP Port Service> system");
Note: To use the event log, you must ensure your BizTalk instance user has sufficient permissions to write to the host system's event log, otherwise, omit the 'System.Diagnostics.EventLog.WriteEntry' line

Monday, October 24

Adding the PeopleSoft Adapter for Enterprise Applications to BizTalk Server 2010 + Adapter Configuration Information

There are numerous white papwrs on the BizTalk Enterprise Adapter for PeopleSoft. It is a wonderful tool, but unfortunately, none of these white papers thoroughly covers the challenges you may face in getting it up and running. I will try to explain some challenges you might face whilst using this Adapter in the next few posts, with the solutions I discovered.

Please follow up by also reading this post and this post for solutions to challenges you will most likely face if you are using a similar to environment to mine (i.e. BizTalk Server 2010 and Windows Server 2008 R2)

Once you have finished the process below, you can use the adapter by following the steps at this link: http://msdn.microsoft.com/en-us/library/aa995588.aspx. (I will try to find the time to create another post on the steps at some point)

At design time, the BizTalk Server 2010 PeopleSoft LOB adapter evaluates the PeopleSoft Component Interfaces on the PeopleSoft server and exposes a listing of these APIs which can then be consumed within BizTalk Server 2010. This adapter is a send adapter, and is used for initiating calls to PeopleSoft from BizTalk Server. However, note that while the PeopleSoft LOB adapter does not handle retrieving data from PeopleSoft directly, the send handler from BizTalk Server can be used to initiate a request for information using the Get or Find methods of the Component Interfaces exposed by the adapter, provided that the appropriate requesting parameters (keys, guids etc.) are made available
  1. Install the Enterprise Applications Adapters
    1. Double-click ‘Setup.exe’ from your enterprise applications adapters installation pack
    2. Select ‘Install Microsoft BizTalk Adapters’
    3. Click on ‘Step 4: Install Microsoft BizTalk Adapters for Enterprise Applications’
    4. Use the default settings to install the adapters

  2. Register the PeopleSoft Enterprise adapter with the BizTalk Server 2010 Instance
    1. Click Start, point to Programs, point to Microsoft BizTalk Server 2010 and then click BizTalk Server Administration
    2. Expand BizTalk Server Administration, expand BizTalk Group, expand Platform Settings, and then expand Adapters
    3. Right-click Adapters, point to New, and then click Adapter
    4. Enter a Name for the adapter. e.g, PeopleSoft
    5. From the Adapter list, select the adapter, and then click OK
    6. The prompt reads “This configuration changes requires host instance restart. Please restart the associated host instances for the changes to take effect." Click OK to finish the configuration.
    7. From the BizTalk Server 2006/2009 Administration console, navigate to BizTalk Server 2010 Administration -> BizTalk Group -> Platform Settings-> Host Instance
    8. Right-click BizTalkServerApplication, and then click Restart. BizTalkServerApplication is the typical default in-process host instance. If you assigned the adapter to a different host instance, you must restart that host instance instead.

  3. Install the Sun Java JDK
    1. Although BizTalk Server 2010 is built on the Microsoft .NET Framework, the connection of the PeopleSoft LOB adapter into the PeopleSoft application uses Java, and communicates with BizTalk Server using the PeopleSoft JOLT transaction protocol. This is especially evident when configuring the port because it is necessary to reference several JAR file locations in addition to the PeopleSoft connection information
        
      For this reason, the Java Development Kit (JDK) also needs to be installed
      • Download the latest JDK rom Sun microsystems (current version is JDK 7, but I only got a successful connection with jdk 6 in my case at first. I later realised this was because I needed the 32 bit version of the JDK 7 even though I am running on a 64-bit OS - Windows 2008 R2. I installed the 32-bit version of the JDK 7 and got it to work)
      • Double-click the downloaded JDK file (jdk-6-windows-i586.exe and thewn jdk-7-windows-i586.exe in my case) executable. You must have administrative permissions in order to install the JDK on Microsoft Windows)
      • Install the components you need – note the location of the installation (typically something like C:\Program Files (x86)\Java\jdk1.7.0)
      • Set the PATH environment Variable.(You can run the JDK without setting the PATH environment variable, or you can optionally set it so that you can conveniently run the JDK executable files (javac.exe, java.exe, javadoc.exe, and so forth) from any directory without having to type the full path of the command. If you do not set the PATH variable, - I didn't - you need to specify the full path to the executable file every time you run it, in the port configurations)
        1. To set the PATH environment variable, Click Start, then Control Panel, then System
        2. Click Advanced System Settings, then Environment Variables
        3. Under ‘System Variables’, scroll to PATH and Add the location of the bin folder of the JDK installation at the end of the PATH variable. The PATH environment variable is a series of directories separated by semicolons (;) and is not case-sensitive

          The following is a typical value for the PATH variable: C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Java\jdk1.7.0_01
  4. Configure the adapter

    1. The PeopleSoft adapter requires that the send and receive pipelines use the default XML pipelines of XML Transmit and XML Receive respectively
    2. The adapter uses transport properties (see Tables 1 and 2) to connect to PeopleSoft. One important characteristic to note about these transport settings is that the values are case sensitive. Take care when specifying the properties
                                                    

      Figure 1 – Adapter Properties

    Transport Property

    Description / Example
    Application Server PathThe name of the computer and port on which the PeopleSoft application server is running and listening. The syntax of the URL path to the PeopleSoft 8 application is //<machine_name>:<port>

    The <port> value is the JOLT protocol Listener port, not the App Server port. The default JOLT port is 9000.
    JAVA_HOMEThe location where the JDK was installed.

    For example: C:\Program Files (x86)\Java\jdk1.7.0. (Not required if you set up the environment PATH variable as described in step 3d above
    PasswordThe user’s password used to access the PeopleSoft system. The characters do not appear but are represented by asterisks (*).

    This is required only if you are not using Enterprise Single Sign-On (SSO).
    PeopleSoft 8x JAR FilesThe location of the psjao.jar file on the PeopleSoft server.. (I copied the psao.jar file from the PeopleSoft server onto the BizTalk server in my case, so I ecreated a folder for it and entered it as C:\PSJarLoc\psjoa.jar)

    For example: C:\PeopleSoft\psjoa.jar or \\<PeopleSoft Server>\web\psjoa\psjoa.jar

    The psjoa.jar file is unique to each version and installation of PeopleSoft. This file is typically located at <PeopleSoft_Home>\web\PSJOA\psjoa.jar.
    User NameThe user’s login name used to access the PeopleSoft system.

    This is required only if you are not using SSO

    Table 1 – Required Transport Properties

    Transport Property
    Description / Example
    Database date format
    The default format is YYYY-MM-DD - When a date is used as a key value, it may have a different format which needs to tally with the format on the PeopleSoft database.

    Max Concurrent Calls

    Default is 5 - This value specifies the maximum number of concurrent calls that can be made on this send port. If the number of calls exceeds this value, the additional requests will become dehydrated until processing threads become available.

    –1 indicates an unlimited number of calls

    Maximum number of sessions
    Default is 40 - This determines the maximum number of sessions that can be connected to the server at one time

    - Sessions relate to the way in which a client connects to the server. For example, if the login credentials are the same, they use the same session. Concurrent calls relate to the number of simultaneous connections that can be made to a server at a time. You may need to limit the number of sessions based on the number of client licenses, whereas the number of concurrent calls impacts performance and is determined by back-end processing capabilities

    Event Log Level

    Error - This is the level of events that are to be recorded as they are encountered. The default value is Error. Possible values are Info (includes warnings and errors), Warning (includes errors), and Error.

    Refresh Agent

    Yes - When Yes is selected, the runtimeagent.exeand the browsingagent.exe processes will be restarted automatically as required. They are processes that the BizTalk Server runtime and Visual Studio.Net respectively invoke on the LOB adapters for metadata generation

    Affiliate application
    This value is created by Enterprise Single Sign-On tools and is used to represent an external application. The user credentials are stored in the SSO Credential database

    Use SSO – This value determines whether SSO is to be used or not

    Table 2 – Additional Transport Properties




Appendix: References and more reading:
http://msdn.microsoft.com/en-us/library/bb820917(v=bts.10).aspx
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=16310
http://download.oracle.com/javase/7/docs/webnotes/install/windows/jdk-installation-windows.html
http://go.microsoft.com/fwlink/?LinkId=96136
http://hosteddocs.ittoolbox.com/KK022704.pdf
http://download.microsoft.com/download/1/6/9/16968441-c6c8-4bd0-9410-5f4014bc61f0/peoplesoft.doc

Thursday, October 20

BizTalk Factory Powershell Provider error 2869 fix

The Biztalk factory Powershell Provider which works with Powershell 2.0 is a wonderful tool for adding BizTalk functionality to automated PowerShell deployment scripts. However, searching for the topic above on google will throw up numerous posts about frustrations arising from it's problematic installation process on Windows server 2008, with no actual solution posted anywhere

Basically, in some situations, after installing the PowerShell Provider extension from the msi provided at the download location, the application still does not install properly thanks to Microsoft's 'brilliant' UAC (user access control) processes. The other problem is, trying to uninstall it from control panel (or even by using InstallUtil) gives the unexplained error code 2869, and uninstallation promptly fails. you then find yourself in a dilemma... can't go forward, can't go backwards!

In my case, we were 2 days from live release and a tester had pedantically removed and tried to re-install the PowerShell Provider (which was actually out of the scope of his test case) whilst testing my 'brilliant' backup, install and (if needed) restore script. Here I was with hundreds of lines of PowerShell deployment scripts which were dependent on the PowerShell Provider, less than 48 hours before release, and no PowerShell Provider! Fortunately, I was able to solve the issue after a bit of brainstorimng and research once I understood what the problem was

You need to install the extension application with elevated priviledges in order for it to install properly. But just making yourself an administrator won't solve the problem, as windows still doesn't actually make you an administrator thanks to UAC.

To fix this issue, follow the steps below:

  1. Check if the failed installation exists by checking for the folder C:\Program files (x86)\PowerShell Provider - delete the folder if it exists
  2. Open a new notepad file and type in msiexec /i "<location of the downloaded msi you wish to install>"
  3. Save the notepad file as installpsf.bat and save it on the desktop (or anywhere really)
  4. Right-Click the notepad file and click 'Run as administrator' - this will run the msi installer again with the right level or permissions
  5. Click Next and Choose remove if you're trying to remove a failed installation and use the default settings till the end or
  6. Click Next to install a fresh installation (you must have removed any faled installations first - you must also delete the flder as in step 1 if uninstalling and planning to re-install )
  7. If re-installing, click on 'Biztalk Management Automation' and choose 'entire feature will be installed on local hard drive' - do the same for 'Biztalk Powershell Provider'
  8. Click Next till the end of the installation
Your BizTalk Factory Powershell Provider should now be ready to run anew

Tuesday, October 11

BizTalk Server 2010 Automated Backup and Restore Script - PowerShell 2.0

Following on from my first post in this series,  this set of scripts uses the same ideology to create a snapshot of the BizTalk Server Instance before a new deployment script is executed. In the event of deployment failure, the restore script uses the snapshot to restore the server to it's previous state.

Working with the brilliant BizTalk Powershell Provider from codeplex (http://psbiztalk.codeplex.com/), the script uses the BTSCatalogExplorer Class of the Microsoft.BizTalk.ExplorerOm interface to get the BizTalk server applications currently installed on the server, and backs up the BizTalk Server instance

For the sake of clarity and brevity, I have omitted backing up of policies, but that could be easily added with a few extra lines of code. Also, because of my ASP.Net web development development background, I like clearly detailed layouts. So I have added a lot of colouring and spacing to make the logs easier to troubleshoot. These are not compulsory

If you haven't read the previous post, I suggest you do so, as that will make what I am doing here much clearer

This script will be used to backup all non-default, non-microsoft bizTalk applications present on the server. In this scneario, I have once again worked with the canonical CommonArtifacts system described in the last post. I am assuming that the company in question names it's shared applications by adding the word 'Common' into their naming conventions. So you could have department.CommonArtifacts, Department2.CommonArtifacts etc. These will need to be identified and restored first in the restore script

The folder structure is as follows:
D:\BizTalk\RollBackInstance\ is the source folder

All applications and their artifacts are stored in application folders created within child folders of the source folder
so once backed up, we will have:
D:\BizTalk\RollBackInstance\bindings\MyApps.BizTalk.Application2\D:\BizTalk\RollBackInstance\msis\MyApps.BizTalk.Application2\
D:\BizTalk\RollBackInstance\resources\MyApps.BizTalk.Application2\

and so on...

We have:
1. BackUp.bat script which calls the backup process
2. LaunchRollBack.bat script which calls the restore process
3. Functions.ps1 script which contains all the funcitons used for the processes
4. create_rollback.ps1 script which creates the backup folders
5. initiate_rollback.ps1 script which implements the restore process

The folder structure for the scripts is similar to the one used in my last post

Create folder structures as shown below:

Create the folders
D:\BizTalk\RollBackInstance\msis\
D:\BizTalk\RollBackInstance\bindings\
D:\BizTalk\RollBackInstance\logs\rollbacklogs
D:\BizTalk\RollBackInstance\scripts\
D:\BizTalk\RollBackInstance\configs\RedCross (optional, for copying the current BizTalk config file)



In the scripts folder, create the files create_rollback.ps1, initiate_rollback.ps1 and Functions.ps1 as follows



FILE 1
functions.ps1: -  
checks that the environment settings file exists and creates one if it does not exist
declares the functions to be used from the ExplorerOM dll
loads the BizTalk.Powershell.Extensions

- this file could be extended easily to remove and add policies, pipeline components, functoids etc

there are two main functions to note in this file,
CreateApplicationCatalogs which lists all applications in the BizTalk server instance, creates folders for each application found, exports the msi and bindings for each application into the new folders and creates a list of all resources found in each application

RestoreApplicationCatalogs which has two parts:
It first takes a 3rd-level backup of all msis found in BizTalk during the restore process and stored them in a folder called RedCross (some humour here),checks for common applications, stops all applications whose names do not start with 'BizTalk' or 'Microsoft' (so applications like Microsoft.Practices.ESB and BizTalk Applicaiton 1 are not affected), stops and removes all other applications, removing the common applications last 

In part 2, it searches the backup folder structure, counts the number of applications found, checks for common applications and installs them first, then installs all other applications and restarts all host instances

Functions.ps1

# By Stephen Omotomilola 03/02/2010
# Functions for BizTalk rollback section added
# Functions for BizTalk (some taken from the ESB Toolkit sample installation scripts)

# Get Server settings 
($env:USERDOMAIN -eq "MyCompanyDEV")
    {
    $inputFileRelativePath = "\\SharedComputerdev\Bank\BizTalkServerSettings\"
    }
if ($env:USERDOMAIN -eq "MyCompanyTEST")
    {
     $inputFileRelativePath = "
\\SharedComputertest\Bank\BizTalkServerSettings\"    }
    }


$inputFile = $inputFilerelativePath + "SetInputs-" + $env:COMPUTERNAME + ".xml"
if (test-path -path $inputFile)
    {
        Write-Host $inputFile  "found" -Separator " "  -BackgroundColor Green -ForegroundColor White
    }
Else
    {
        Write-Host $inputFile  "does not exist" -Separator " "  -BackgroundColor Red -ForegroundColor White
        Return
    }   


# Set export folders $resExpPath = ".\resources"
$policiesExpPath = ".\policies"


$xmlinput = [xml] (get-content $inputFile)   
   
# Get the top node$item = $xmlinput.BTS2010Config


# Read the parameters we want  $BTSInstallPath = $item.BTS2010InstallationPath
$ESBToolkitPath = $item.ESBToolkitInstallationPath
$btsConnectionString = $item.BTSConnectionString
$btsDBServerName = $item.BTSDBServerName
$btsDBName = $item.BTSDBName


# Colour for sections headers$sectHeadColour = "Gray"
$sectHeadColourALLGo = "Black"
$sectBackColourAllGo = "Green"
$sectBackColourIsOK = "Yellow"
$sectBackColourToDo = "Yellow"


if ($BTSInstallPath.EndsWith("\"))
{
 $BTSInstallPath = $BTSInstallPath.Substring(0, $BTSInstallPath.Length - 1)
}

if ($ESBToolkitPath.EndsWith("\"))
{
 $ESBToolkitPath = $ESBToolkitPath.Substring(0, $ESBToolkitPath.Length - 1)
}

$RulesDeployerPath = $ESBToolkitPath + "\bin\Microsoft.Practices.ESB.RulesDeployer.exe"
$ESBImportUtilPath = $ESBToolkitPath + "\bin\EsbImportUtil.exe"


# Loads the commands for the http://psbiztalk.codeplex.com/ add in
Write-Host "Loading the Powershell Biztalk Extensions"
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'BizTalkFactory.PowerShell.Extensions'}
if ($snapin -eq $null)
    {
        $InitializeDefaultBTSDrive = $false
        Add-PSSnapin –Name BizTalkFactory.PowerShell.Extensions
  New-PSDrive -Name BizTalk -PSProvider BizTalk -ROOT BizTalk:\ -Instance $btsDBServerName -Database $btsDBName
    }


Function Biztalk: { Set-Location Biztalk: }
Function Biztalk:\ { Set-Location Biztalk:\ }


Write-Host "Finished Loading the Powershell Biztalk Extensions"

if ($BTSInstallPath -eq $null)
    {
        Write-Host "Cannot find BizTalk Install Path, check server and correct settings" -BackgroundColor Red -ForegroundColor White
        Return
    }
    Else
    {
        Write-Host "BizTalk Install Path" $BTSInstallPath -Separator `t
    }

   
if ($btsConnectionString -eq $null)
    {
        Write-Host "Cannot find BTS connection string, check server and correct settings" -BackgroundColor $sectHeadColourALLGo -ForegroundColor $sectHeadColour
        Return
    }
Else
    {
        Write-Host "BizTalk connection string" $btsConnectionString -Separator `t
    }

function GetBTSInstallPath
{
 $BTSInstallPath
}   

function GetbtsDBServerName
{
    $btsDBServerName
}

#Creating BTS Applications
function CreateBTSApplication
{
 param([string]$appName, [string]$logFile)
   
    Write-Host "Create Application" $appName -Separator `t
   
    [System.Reflection.Assembly]::LoadFrom($BTSInstallPath +"\Developer Tools\Microsoft.BizTalk.ExplorerOM.dll") | Out-Null

 $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $exp.Applications
   
    Write-Host $exp
 $exp.ConnectionString = $btsConnectionString
 $app = $exp.Applications[$appName]

 if($app -eq $null)
 {
  Write-Output "Creating BizTalk Application "$appName 
  $returnCode = (BTSTask.exe AddApp /A:$appName)

  if ($LASTEXITCODE -eq 0)
  {
   Write-Host "$appname application created sucessfully"
  }
  Else
  {
   Write-Host "Create application $appname failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
   $returnCode | Out-File $logFile
  }
 }
 else
 {
  Write-Host "Application " $appName " exists"
 }
}

#Removing BTS Applications
function RemoveBTSApplication
{
 param([string]$appName, [string]$logfile)
 Write-Host "Removing BTS Application " + $appName
 $returnCode =(BTSTask.exe RemoveApp /A:$appName)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname application removed sucessfully"
 }
 Else
 {
  Write-Host "Remove application $appname failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

#Removing BTS Resources
function RemoveBTSResource
{
 param([string]$appName, [string]$resource, [string]$logfile)
 Write-Output "Removing BTS Resource "+ $resource
 $returnCode =(BTSTask.exe RemoveResource  /A:$appName /L$resource)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$resource removed sucessfully"
 }
 Else
 {
  Write-Host "Remove resource $resource failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

#Importing BTS msi
function ImportBTSApplication
{
    param([string]$appName, [string]$msiPath, [string] $logFile)
    Write-Host "Importing $appName Application"
    $returnCode = (BTSTask.exe ImportApp -Package:$msiPath -ApplicationName:$appname -Overwrite)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname application imported sucessfully"
 }
 Else
 {
  Write-Host "$appname application import failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

#Importing BTS bindings
function ImportBinding
{
 param([string]$appName, [string]$bindingFilePath, [string]$logFile)
 # BTS Task
 BTSTask.exe ImportBindings  /A:$appName /So:$bindingFilePath

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname binding imported sucessfully"
 }
 Else
 {
  Write-Host "$appname binding import failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

# ..................................................
#Specific Backup and Rollback Section Commands

#Backup Creation Process
function CreateApplicationCatalogs
{
 param([string]$mPath, [string]$bPath, [string]$lPath)

 Write-Host "Taking BizTalk Snapshot"
    Write-Host ""
 Write-Host ""
    [System.Reflection.Assembly]::LoadFrom($BTSInstallPath +"\Developer Tools\Microsoft.BizTalk.ExplorerOM.dll") | Out-Null

 $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $exp.Applications
   
    $exp.ConnectionString = $btsConnectionString

#=== Loop through applications in the catalog ===#    $Expcount = $exp.Applications.Count
 $FirstExpcount = $Expcount
 Write-Host "$Expcount Applications found on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo

 foreach($Expa in $exp.Applications)
    {

 $NewExpapp = $Expa.Name

 if ($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft"))
    {     
   $Expcount = $Expcount-1
    }
 }
   
    Write-Host "$Expcount Relevant (non-default) Applications found out of $FirstExpcount on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host ""
    Write-Host "Creating backup..."
    Write-Host ""
    Write-Host ""

    $Expcountb = 0
    foreach($Expapp in $exp.Applications)
    {
     
    #Count Apps whilst Ignoring BizTalk Default Apps    $NewExpapp = $Expapp.Name
    if (!($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft")))
    {
    $Expcountb = $Expcountb-1
    $ExpCountUp = 0-$Expcountb
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host $ExpcountUp ": Now working on " $NewExpapp " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Creating backup..."
       
       #Check for and create application folder    if (!(Test-Path -path $mPath\$NewExpapp\))
          {
              Write-Host "Application folder not found"
     Write-Host ""
     Write-Host ""
     Write-Host "Task 1 - Create Application Folder" -ForegroundColor $sectBackColourIsOK
     New-Item $mPath\$NewExpapp\ -type directory
              if (Test-Path -path $mPath\$NewExpapp\)
              {
                Write-Host "Task 1 Successful - Create Application Folder" -ForegroundColor $sectBackColourIsOK
    Write-Host "$mPath\$NewExpapp\"  -ForegroundColor $sectBackColourIsOK
    Write-Host "folder successfully created" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo  
              }
          }
    Else
    {
        Write-Host "Application folder found"
     Write-Host ""
     Write-Host ""
     Write-Host "Task 1 - Create Application Folder: Not needed" -ForegroundColor $sectBackColourIsOK
     Write-Host "Moving on to Task 2 - Export Application msi" -ForegroundColor $sectBackColourIsOK
    }
   
    #Export Application msi    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host "Task 2 - Export Application msi" -ForegroundColor $sectBackColourIsOK
    ExportBTSApplication $NewExpapp "$mPath\$NewExpapp\$NewExpapp.msi" "$lPath\msiexportlogs\ExportApp_$NewExpapp.log"
   
    #List Application Resources for cross-checking    Write-Host ""
    Write-Host "Task 3 - Record Application Resources" -ForegroundColor $sectBackColourIsOK
    ListAppResources $NewExpapp "$mPath\$NewExpapp\resources\$NewExpapp.Resources.xml" "$lPath\resource_manifestlogs\AppResources_$NewExpapp.log"
   
    #Export bindings    Write-Host ""
    Write-Host "Task 4 (Final Task) - Export Application Bindings" -ForegroundColor $sectBackColourIsOK
    ExportBinding $NewExpapp "$bPath\$NewExpapp\$NewExpapp.bindinginfo.xml" "$lPath\bindings_xportlogs\ExportBindings_$NewExpapp.log"
       }   
    }
}

#Restore Process
function RestoreApplicationCatalogs
{
 param([string]$mPath, [string]$bPath, [string]$lPath)

 [string[]]$NonCommonApps = New-Object System.Collections.ArrayList
 [string[]]$AllCommonApps = New-Object System.Collections.ArrayList

 Write-Host "Restoring From BizTalk Snapshot"
    Write-Host ""
 Write-Host ""
    [System.Reflection.Assembly]::LoadFrom($BTSInstallPath +"\Developer Tools\Microsoft.BizTalk.ExplorerOM.dll") | Out-Null

 $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $exp.Applications
   
    $exp.ConnectionString = $btsConnectionString

#=== Loop through and remove applications in BTS ===#
#=== Loop through and make a list of applications in BTS ===#    $Expcount = $exp.Applications.Count
 $FirstExpcount = $Expcount
 Write-Host "$Expcount Applications found on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
 $CommonExists = "No"

 foreach($Expa in $exp.Applications)
    {
     $NewExpapp = $Expa.Name

  #Add applicastion name to list  if (!($NewExpapp -Like "*Common*") -and !($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft")))
    {
  $NonCommonApps = $NonCommonApps + $NewExpapp
    }

#Check for Common (shared) applications
 if ($NewExpapp -Like "*Common*")
    {
      $AllCommonApps = $AllCommonApps + $NewExpapp
   $CommonExists = "Yes"
    }
   
    #Count Apps whilst Ignoring BizTalk Default Apps   
    if ($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft"))
    {     
   $Expcount = $Expcount-1
    }
 }
    Write-Host "$Expcount Relevant (non-default) Applications found out of $FirstExpcount on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host ""
    Write-Host ""
    $Expcommoncount = $AllCommonApps.Count
    Write-Host "$Expcommoncount Common Applications found on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host ""
    Write-Host "Removing All Relevant Applications..."
    Write-Host ""
    Write-Host ""

    $Expcountb = 0

#Now actually remove relevant apps

 #Remove non-common apps first
    foreach($noncommon in $NonCommonApps)
 {
          
    $NewExpapp = $noncommon  
    $Expcountb = $Expcountb-1
    $ExpCountUp = 0-$Expcountb
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Now working on " $NewExpapp " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Stopping Application..."
              
    #Stop Application    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host "Task 1 - Stop Application" -ForegroundColor $sectBackColourIsOK
    ExportBTSApplication $NewExpapp "$mPath\$NewExpapp\RedCross\msis\$NewExpapp.msi" "$lPath\rollbacklogs\ExportApp_$NewExpapp.log"
       ExportBinding $NewExpapp "$mPath\$NewExpapp\RedCross\bindings\$NewExpapp.bindinginfo.xml" "$lPath\rollbacklogs\ExportBindings_$NewExpapp.log"
         StopBTSApplication $NewExpapp "$lPath\rollbacklogs\StopApp_$NewExpapp.log"
   
    #Remove Application    Write-Host ""
    Write-Host "Task 2 - Remove Application" -ForegroundColor $sectBackColourIsOK
    ListAppResources $NewExpapp "$mPath\$NewExpapp\RedCross\resources\$NewExpapp.Resources.xml" "$lPath\rollbacklogs\AppResources_$NewExpapp.log"
       RemoveBTSApplication $NewExpapp "$lPath\rollbacklogs\RemoveApp_$NewExpapp.log"
             Write-Host ""
       Write-Host ""
  } 
   
  #Now remove Common Apps  if ($CommonExists -eq "Yes")
  {
  foreach($Commonapp in $AllCommonApps)
     {
   
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Now working on " + $Commonapp + " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Stopping Application..."
   
      #Stop Application    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host "Task 1 - Stop Application" -ForegroundColor $sectBackColourIsOK
    ExportBTSApplication $Commonapp "$mPath\$Commonapp\RedCross\msis\$Commonapp.msi" "$lPath\rollbacklogs\ExportApp_$Commonapp.log"
       ExportBinding $Commonapp "$mPath\$Commonapp\RedCross\bindings\$Commonapp.bindinginfo.xml" "$lPath\rollbacklogs\ExportBindings_$Commonapp.log"
         StopBTSApplication $Commonapp "$lPath\rollbacklogs\StopApp_$Commonapp.log"
   
    #Remove Application    Write-Host ""
    Write-Host "Task 2 - Remove Application" -ForegroundColor $sectBackColourIsOK
    ListAppResources $Commonapp "$mPath\$Commonapp\RedCross\resources\$Commonapp.Resources.xml" "$lPath\rollbacklogs\AppResources_$Commonapp.log"
       RemoveBTSApplication $Commonapp "$lPath\rollbacklogs\RemoveApp_$Commonapp.log"
    Write-Host ""
       Write-Host ""   
     }
 
  }
 
  # Restart Host Instances    Write-Host ""
    Write-Host "Task - Restart HostInstances" -ForegroundColor $sectBackColourIsOK
          RestartHostInstances $lPath + "\rollbacklogs\RestartHostinstancesa.log"
       Write-Host ""
    Write-Host ""
    Write-Host "......................................." -ForegroundColor Green
    Write-Host "All Relevant Applications Successfully Removed" -ForegroundColor Yellow
    Write-Host "......................................." -ForegroundColor Green
    Write-Host ""
    Write-Host ""


#PART 2  
#=== Loop through and create applications from the backup directories ===#
 if (!(Test-Path -path $mPath))
    {
   Write-Host ""
   Write-Host ""
   Write-Host "......................................." -ForegroundColor Red
   Write-Host "Error!!! BackUp Directory Not Found - $mPath" -ForegroundColor Red
   Write-Host "Please contact an administrator - Exiting..." -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Red
   Write-Host ""
   Write-Host ""
   Exit
 }
 Else
 {
   Write-Host "......................................." -ForegroundColor Yellow
   Write-Host "Found - $mPath" -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Yellow
   Write-Host ""
   Write-Host ""
   $dirs = get-childitem $mPath | Where {$_.psIsContainer -eq $true -and !($_.name -Like "*Common*")}
   $dcounted = $dirs.Count
   Write-Host "Now Restoring From RollBack Applications..."
   Write-Host ""
   Write-Host ""
   Write-Host "Found $dcounted non-common application folders" -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Yellow
   Write-Host ""
        
   [string[]]$CommonApps = get-childitem $mPath | where {$_.name -Like "*Common*"}
      $dcounted2 = $CommonApps.Count
      Write-Host "Found $dcounted2 common application folders" -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Yellow
  
#  Re-Installing From Folders   #Restore Applications
     #Check for Common Artifacts and install first if found
  $counting = 0
  If ($CommonApps)
  {
      foreach($DFName in $CommonApps)
         {    
       Write-Host "Installing (shared) common artifacts first ..." -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    $counting = $counting + 1
       $AppPath = $mPath + "\" + $DFName + "\" + $DFName + ".msi"
       $AppBingdingsPath = $bPath + "\" + $DFName + "\" + $DFName + ".bindinginfo.xml"
  
       Write-Host ""
             Write-Host ""
             Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
          Write-Host $counting ": Now restoring " $DFName " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
          Write-Host "......................................." -ForegroundColor $sectBackColourIsOK

       Write-Host "Creating Application..."
              
       #Create Application       Write-Host ""
       Write-Host ""
       Write-Host ""
       Write-Host "Task 1 - Create Application" -ForegroundColor $sectBackColourIsOK
       CreateBTSApplication $DFName "$lPath\rollbacklogs\CreateApplication_$DFName.log"
         
       #Import Application             Write-Host ""
       Write-Host "Task 2 - Import Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportApplication_$DFName.log"
       ImportBTSApplication $DFName $AppPath $logFile   
   
       #Import Bindings             Write-Host ""
       Write-Host "Task 3 - Import Application Bindings" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportBindings_$DFName.log"
       ImportBinding $DFName $AppBingdingsPath $logFile
    
 #Install Application             Write-Host ""
       Write-Host "Task 4 - Install Application" -ForegroundColor $sectBackColourIsOK
       $msiFile = $AppPath
             $logFile = $lPath + "\rollbacklogs\$DFName.msi.install.log"
             InstallMSI $AppPath $logFile
             # Restart Host Instances
       Write-Host ""
       Write-Host "Task 5 - Restart Host Instances" -ForegroundColor $sectBackColourIsOK
             RestartHostInstances $lPath + "\rollbacklogs\RestartHostinstances.log"
         
       #Start Application             Write-Host ""
       Write-Host "Task 6 - Start Application" -ForegroundColor $sectBackColourIsOK
             StartBTSApplication $DFName "$lPath\rollbacklogs\StartApplication_$DFName.log"      
  
   }
  } #end if check for common atifacts
   #Run loop again to do non-common apps   foreach($DFName in $dirs)
         {      
         
       $counting = $counting + 1
       $AppPath = $mPath + "\" + $DFName + "\" + $DFName + ".msi"
       $AppBingdingsPath = $bPath + "\" + $DFName + "\" + $DFName + ".bindinginfo.xml"
  
       Write-Host ""
             Write-Host ""
             Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
          Write-Host $counting: Now restoring $DFName Application -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
          Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
       Write-Host ""
             Write-Host ""
       Write-Host "Creating Application..."
              
       #Create Application
       Write-Host ""
       Write-Host ""
       Write-Host "Task 1 - Create Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\CreateApplication_$DFName.log"
       CreateBTSApplication $DFName $logFile
         
       #Import Application             Write-Host ""
       Write-Host "Task 2 - Import Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportApplication_$DFName.log"
       ImportBTSApplication $DFName $AppPath $logFile   
   
       #Import Bindings             Write-Host ""
       Write-Host "Task 3 - Import Application Bindings" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportBindings_$DFName.log"
       ImportBinding $DFName $AppBingdingsPath $logFile
        
#Install Application             Write-Host ""
       Write-Host "Task 4 - Install Application" -ForegroundColor $sectBackColourIsOK
       $msiFile = $AppPath
             $logFile = $lPath + "\rollbacklogs\$DFName.msi.install.log"
             InstallMSI $AppPath $logFile

     # Restart Host Instances       Write-Host ""
       Write-Host "Task 5 - Restart HostInstances" -ForegroundColor $sectBackColourIsOK
             RestartHostInstances $lPath + "\rollbacklogs\RestartHostinstances.log"
         
       #Start Application             Write-Host ""
       Write-Host "Task 6 - Start Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\StartApplication_$DFName.log"
             StartBTSApplication $DFName $logFile
             
   }   
  
 } #end if check for installaiton folder existence
}

#Exporting msi
function ExportBTSApplication
{
    param([string]$appName, [string]$msiExpPathName, [string] $logFile)
    Write-Host "Exporting $appName Application"
 Write-Host ""
    $returnCode = (BTSTask.exe ExportApp -ApplicationName:$appName -Package:$msiExpPathName)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "Task Successful - Export Application msi" -ForegroundColor $sectBackColourIsOK
  Write-Host "$appName application exported sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
  Write-Host ""
  Write-Host ""
     Write-Host ""
 }
 Else
 {
  Write-Host "Task Failure! - Export Application msi"  -ForegroundColor Red
  Write-Host "$appName application export failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  Write-Host ""
  Write-Host ""
     Write-Host ""
  $returnCode | Out-File $logFile
 }
}

#Exporting BTS application bindings
function ExportBinding
{
 param([string]$appName, [string]$bindingFilePath, [string]$logFile)
    Write-Host "Exporting bindings for $appName"
 Write-Host ""
 # BTS Task
 BTSTask.exe ExportBindings -Destination:$bindingFilePath -ApplicationName:$appName
 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "Task Successful - Export Application Bindings" -ForegroundColor $sectBackColourIsOK
  Write-Host "$appname bindings exported sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
  Write-Host ""
  Write-Host ""
     Write-Host ""
 }
 Else
 {
  Write-Host "Task Failure! - Export Application Bindings"  -ForegroundColor Red
  Write-Host "$appname bindings export failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  Write-Host ""
  Write-Host ""
     Write-Host ""
  $returnCode | Out-File $logFile
 }
}

#List resources found in BTS application
function ListAppResources
{
 param([string]$appName, [string]$ResFilePath, [string]$logFile)
    Write-Host "Recording Resources for $appName"
 Write-Host ""
 # List Application Resources to file
 BTSTask.exe ListApp -ApplicationName:$appName -ResourceSpec:$ResFilePath

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname Resources listed sucessfully into file" -ForegroundColor $sectBackColourIsOK
  Write-Host $ResFilePath -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
  Write-Host ""
  Write-Host ""
     Write-Host ""
 }
 Else
 {
  Write-Host "Task Failure! (Not Major) - Record Application Resources"  -ForegroundColor RedWrite-Host
  Write-Host "$appname Resources listing failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  Write-Host ""
  Write-Host ""
     Write-Host ""
  $returnCode | Out-File $logFile
 }
}
# .................................................................
# End Rollback Section Commands


#Installing a BTS msi
function InstallMSI
{
    param([string] $msiPath, [string] $logFilePath)
    $parameters = "-qr -i " + $msiPath + " -le " + $logFilePath
    $installStatement = [System.Diagnostics.Process]::Start("msiexec", $parameters)
    $installStatement.WaitForExit()
}

function UninstallMSI
{
    param([string] $msiPath, [string] $logFilePath)
    $parameters = "-qr -x " + $msiPath + " -le " + $logFilePath
    $installStatement = [System.Diagnostics.Process]::Start("msiexec", $parameters)
    $installStatement.WaitForExit()
}

#starting a BTS Application
function StartBTSApplication
{
 param([string]$appName, [string]$logfile)
 cd BizTalk:\Applications
 Write-Host "Starting BTS Application " + $appName
 Start-Application -Path $appName -StartOption StartAll
}

#Stopping BTs Application
function StopBTSApplication
{
 param([string]$appName, [string]$logfile)
 cd BizTalk:\Applications
 Write-Host "Stopping BTS Application " + $appName
 Stop-Application -Path $appName -StopOption StopAll
}

#Restarting host instances
function RestartHostInstances
{
 param([string]$logfile)

 cd BizTalk:\Applications
 Write-Output "Restarting Host Instances......"
 Set-Location '\Platform Settings\Host Instances'
 Get-ChildItem | `
 Where-Object { $_.ServiceState -eq 'Running' } | `
    Restart-HostInstance
}
FILE 2
create_rollback.ps1: -  
sets the correct folder paths, backs up the BTs config file and calls the backup process 


create_rollback.ps1
#  Create Rollback script for BizTalk installations...
#  Stephen Omotomilola 06-01-2010

# This must be called from a batch file
param
(
    [string]$launchedFromBatch = $(throw '- This script should be launched from a batch file as it relies on relative paths')
)

# Call BTSFunctions file. .\Scripts\Functions.ps1

#Get current location to use as reference
[string]$path = Get-Location
$applicationPath = $path + "\Applications"
$scriptsPath = $path + "\Scripts"
$backupConfigPathExp = $path + "\configs\"
$msiExpPath = $path + "\msis"
$bindingsExpPath = $path + "\bindings"
$applogExpPath = $path + "\logs"

Write-Host "BTS Installation Rollback Creation Package"
Write-Host ""
Write-Host ""

$Error.Clear()
Write-Host "Now Backing Up BTS Snapshot for RollBack  " -Separator `t
CreateApplicationCatalogs $msiExpPath $bindingsExpPath $applogExpPath

# Backup the BTS config file$newBtsFile = $backupConfigPathExp + "\BTSNTSvc64.exe.config"
$BTSInstallPath = GetBTSInstallPath
$existingBtsFile = $BTSInstallPath + "\BTSNTSvc64.exe.config"
Write-Host "Existing config  " $existingBtsFile -Separator `t
Write-Host ""
Write-Host ""
Write-Host "Backing up BTSNTSvc64.exe.config from " $existingBtsFile " to " $backupConfigPathExp
Copy-Item $existingBtsFile -destination $backupConfigPathExp -force
Write-Host ""
Write-Host ""

$a = Get-Date
Write-Host "BackUp Completed at $a"
Write-Host "To use this backup for a rollback, Double-Click on the LaunchRollBack.bat file"
Write-Host "`nPress any key to exit... Thank you"
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")

FILE 3
initiate_rollback.ps1: -  
sets the correct folder paths, restores the BTS server instance by calling the restore process 

 
initiate_rollback.ps1

#  Create Rollback script for BizTalk installations...
#  Stephen Omotomilola 06-01-2010

# This must be called from a batch fileparam
(
    [string]$launchedFromBatch = $(throw '- This script should be launched from a batch file as it relies on relative paths')
)


# Call BTSFunctions file. .\Scripts\Functions.ps1
[string]$path = Get-Location
$applicationPath = $path + "\Applications"
$scriptsPath = $path + "\Scripts"
$backupConfigPathExp = $path + "\configs\"
$msiExpPath = $path + "\msis"
$bindingsExpPath = $path + "\bindings"
$applogExpPath = $path + "\logs"

Write-Host "BTS Installation Rollback Creation Package"
Write-Host ""
Write-Host ""


$Error.Clear()
$a = Get-Date
Write-Host ""
Write-Host ""
Write-Host "Attempting To Intitiate RollBack Catalog at $a"
Write-Host ""
Write-Host ""
Write-Host "Warning: This RollBack Will Restore All BizTalk Applications To An Earlier Snapshot!!" -ForegroundColor White
Write-Host "..................................................." -ForegroundColor Red
Write-Host ""
Write-Host ""
Write-Host "You Need To Confirm To use This Rollback" -ForegroundColor White
Write-Host "`nPress any key to confirm or close this window to exit... Thank you"  -ForegroundColor Yellow
Write-Host "..................................................." -ForegroundColor Red
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")


#Start RollBack$BTSInstallPath = GetBTSInstallPath
$btsDBServerName = GetbtsDBServerName
$RedCross = $backupConfigPathExp + "\RedCross\"

Write-Host ""
Write-Host ""
Write-Host "Now Rollingback BizTalk Server" $btsDBServerName -Separator `t -ForegroundColor White
Write-Host "......................................." -ForegroundColor White
Write-Host ""


# RollBack the BTS config file$newBtsFile = $backupConfigPathExp + "\BTSNTSvc64.exe.config"
$existingBtsFile = $BTSInstallPath + "\BTSNTSvc64.exe.config"
Write-Host "Task - Replacing current BTS config BTSNTSvc64.exe.config with previous config"  -ForegroundColor $sectBackColourIsOK
Write-Host "from" $backupConfigPathExp -Separator `t  -ForegroundColor $sectBackColourIsOK
Write-Host "......................................." -ForegroundColor White

if (!(Test-Path -path $RedCross))
   {
     New-Item $RedCross -type directory
   }
  
Copy-Item $existingBtsFile -destination "$RedCross\BTSNTSvc64.exe.config" -force
Copy-Item $newBtsFile -destination $existingBtsFile -force
Write-Host "Task Successful - BizTalk Server Configuration Replaced" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
Write-Host ""
Write-Host ""


#Restore from catalogRestoreApplicationCatalogs $msiExpPath $bindingsExpPath $applogExpPath
$a = Get-Date
Write-Host ""
Write-Host ""
Write-Host "......................................." -ForegroundColor Green
Write-Host "RollBack Completed at $a" -ForegroundColor White
Write-Host "`nPress any key... Thank you" -ForegroundColor White
Write-Host "......................................." -ForegroundColor Green
Write-Host ""
Write-Host ""
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")


FILE 4
Backup.bat -  
Batch file to start off the backup process 


Backup.bat

@ECHO OFF
SETLOCAL
@TITLE -- Install BizTalk Solution
COLOR 02
FOR /F "tokens=2-4 delims=/ " %%i IN ('date /t') DO SET SHORTDATE=%%i-%%j-%%k
FOR /F "tokens=1-3 delims=: " %%i IN ('time /t') DO SET SHORTTIME=%%i-%%j%%k
SET LaunchedFromBAT=1

:START
:: Check for Powershell v2.0
ECHO - Checking for Powershell 2.0...
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" $host.Version.Major | find "2" >nul
IF ERRORLEVEL 1 (
 COLOR 0C
 ECHO - This script requires PowerShell version 2.0!
 ECHO - Please uninstall v1.0, install v2.0, then re-run this script.
 COLOR
 pause
 EXIT
 )
ECHO - OK.

:: Get existing Powershell ExecutionPolicy
Echo Check Powershell Execution Policy
FOR /F "tokens=*" %%x in ('"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" Get-ExecutionPolicy') do (set ExecutionPolicy=%%x)
:: Set Bypass, in case we are running over a net share or UNC
IF NOT "%ExecutionPolicy%"=="Bypass" (
 ECHO - PS ExecutionPolicy is %ExecutionPolicy%, setting ExecutionPolicy to Bypass.
 "%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" Set-ExecutionPolicy Bypass
 )

GOTO LAUNCHSCRIPT
:LAUNCHSCRIPT
Echo Calling \Scripts\create_rollback.ps1
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" -command "& '%~dp0Scripts\create_rollback.ps1' '%LaunchedFromBAT%'"
GOTO END

:END
Echo All Done!
Echo Review the output and then press a key to close the window
pause
ENDLOCAL