Miscellaneous Ramblings on Hacking

September 27, 2011

Getting Started: Unica Marketing Operations’ Custom Triggers

Filed under: Uncategorized — Zack @ 2:52 pm

You have the SDK. You have the JavaDocs. There are samples, but how does it all glue together? This post is all about writing your first UMO custom trigger. These triggers help to automate tasks or enforce business rules within UMO.

What you Need?

A few needed items:

  • Unica Marketing Operations (UMO) environment
  • Eclipse IDE for EE
  • Associated JARs: affinium_plan.jar, log4j.jar

The JARs are best grabbed from the UMO environment.

Start Eclipse & Code

Startup Eclipse and create a new Application Client Project. This project template option is available under the Java EE folder.

Capture2

Set the JDK to the same level as the web application server that UMO is deployed on. I selected 5.0 for JDK 1.5.

Here I define my AutoReviewerAssignment class. All triggers are required to implement the IProcedure interface.

   1:  

   2: public class AutoReviewerAssignment implements IProcedure {

   3:  

   4:     // The Name and Description of this Procedure.

   5:     private static final String name           = "AutoReviewerAssignment";

   6:     private static final String desc           = "Provides automatic assignment of reviewers based on project member assignment";

   7:     private static final PluginVersion pv        = new PluginVersion(1, 0, 0); 

   8:       

   9:     // Constants

  10:     private static final String DEBUG          = "debug";

  11:     private static final int    STATUS_SUCCESS = 0;

  12:     private static final int    STATUS_FAILED  = -1;

  13:     

Unica products use Log4J for all system logging. There are a couple of products in the Unica suite that don’t, but it’s a safe bet that log4j is being used. For UMO, it is. I’m getting the logger and setting it to a static variable. This way I can add my own class’ log entries to the main log file.

   1: //added - latch on to the log4j logger

   2:     private static final Logger _LOG = Logger.getLogger(AutoReviewerAssignment.class);

   3:     

The interface defines some standard methods, the first of importance is the initialize() method. This is your time to grab some site specific parameters. In some cases, I’ve grabbed from a standard Java .properties file. But Unica also provides the ability to define these parameters in the actual procedure definition file  where the procedure is declared (more on this later).

   1: public void initialize(Map initParams) throws PluginInitializationException {

   2:         // TODO Auto-generated method stub

   3:         _LOG.info("Initializing class trigger procedure..");

   4:         

   5:         //only expecting one init parameter

   6:         if(initParams.containsKey(DEBUG))

   7:         {

   8:             try{

   9:                 isDebug = ((Boolean) initParams.get(DEBUG)).booleanValue();

  10:                 _LOG.debug("Debug mode is enabled: " + String.valueOf(isDebug));

  11:             } catch(Exception e)

  12:             {

  13:                 _LOG.fatal("Exception in initialization. "+ e.getMessage());

  14:                 throw new ProcedureInitializationException("Problem using init parameter: DEBUG");

  15:             }

  16:         }

  17:     }

Finally, there’s the execute method. This is where the action happens and is unique to your own implementation goals.

Configuration Deployment

Once compiled, it’s time to migrate the compiled class file for your procedure. Here’s the steps:

  • Review the [PLAN_HOME]\conf\plan_config.xml to ascertain the environment’s configuration. We’re looking for the following UAPInitParams: integrationProcedureDefinitionPath and integrationProcedureClasspathURL
  • integrationProcedureDefinitionPath points to a procedure_plugins.xml file. This file defines the class, including the initialization parameters. Here’s an example:
   1: <procedure>

   2:     <key>POCtest</key>

   3:     <class-name>com.amberleaf.procedure.POCtest</class-name>

   4:     <init-parameters>

   5:     <init-parameter>

   6:       <param-name>debug</param-name>

   7:       <param-type>java.lang.Boolean</param-type>

   8:             <param-value>true</param-value>

   9:     </init-parameter>

  10:     </init-parameters>

  11: </procedure>

  • integrationProcedureClasspathURL points to the directory where the resulting class file should be placed
  • Finally, bounce the web application server so that the new class can be cached

Now that the environment is setup, it’s time to define the actual trigger. This defines when the trigger should actually fire within Unica Marketing Operations. To do this, we go to: Settings > Marketing Operations Settings > Trigger Bindings.

  • Click ‘Add New Trigger Binding’
  • Define the trigger with the appropriate attributes:

Capture

For example, my trigger would be limited to the ‘Project’ marketing object. The trigger would be limited to the context of ‘People’. Put another way, the trigger would be limited to the ‘People’ tab under the ‘Project’ object. I then further limit the trigger to only execute on the ‘Updated’ event. In summary, the trigger will fire when the ‘People’ tab of a ‘Project’ is ‘Updated’.

And there you have it. You’ve created your first trigger. A special note here. Since we latched on to the log4j logger of Unica’s, we will see our logging entries in the Unica Marketing Operation’s system log. Just be sure to set your log4j logging level appropriately.

March 3, 2011

Best Summary for String.Format Ever

Filed under: Uncategorized — Zack @ 3:20 am

Perfect.

http://www.csharp-examples.net/string-format-datetime/

September 3, 2010

Unica Monitoring SQL

Filed under: Unica — Zack @ 11:43 pm

Doing some Unica troubleshooting today and wrote this little SQL gem. It’s a basic query that does a fine job of retrieving run log errors for flowchart runs. I figure it could come in handy as an Administrator asking the question:

What are my most common errors and where should I focus my troubleshooting?

The SQL:

select to_char(r.runstarttime,'yyyy-mm-dd') runday
, c.name campaign, f.name flowchart
, substr(rr.resultxml,instr(rr.resultxml,'<Process>')+9, instr(rr.resultxml,'<RunStatusCode>')-(instr(rr.resultxml,'<Process>')+9)) as process_name
, substr(rr.resultxml,instr(rr.resultxml,'<ErrorMessage>')+14, instr(rr.resultxml,'</ErrorMessage>')-(instr(rr.resultxml,'<ErrorMessage>')+14)) as result_error
, count(*)
from uacsys.ua_ccrunlog r
join uacsys.ua_runresult rr on r.runid=rr.runid
join uacsys.ua_flowchart f on r.flowchartid=f.flowchartid
join uacsys.ua_campaign c on f.campaignid=c.campaignid
where r.runstatus = 'Run Failed'
and r.runstarttime >to_date('2010-08-01','yyyy-mm-dd')
and instr(rr.resultxml,'<ErrorMessage>') &gt; 0
group by to_char(r.runstarttime,'yyyy-mm-dd')
, c.name, f.name
, substr(rr.resultxml,instr(rr.resultxml,'<Process>')+9, instr(rr.resultxml,'<RunStatusCode>')-(instr(rr.resultxml,'<Process>')+9))
, substr(rr.resultxml,instr(rr.resultxml,'<ErrorMessage>')+14, instr(rr.resultxml,'</ErrorMessage>')-(instr(rr.resultxml,'<ErrorMessage>')+14))
order by runday desc

 

This in turn creates some nice little results for analysis:

July 30, 2010

Unica Interact via SOAP – How To

Filed under: .Net, Unica — Zack @ 9:50 pm

Background

Unica Interact extends Unica’s Campaign Suite for real-time offer management. If you want a full background of what it can offer, I’d suggest a read from Unica’s site. Here I’ll be discussing how to get started for some real basic integration. First, what you’ll need:

  • Unica’s v7 demo image or access to a Unica Interact implementation
  • Visual Studio 2008 (C# Express should work)

Interact Setup

When using the VMWare demo image provided, most of this is setup as part of the image. As an overview, however, I’ll review the following steps:

  1. Interactive Channel
  2. Session
  3. Assigned Campaign Offers and Ratings

Interactive Channel – Insurance

I’ll be using the already defined interactive channel Insurance. This is part of the Unica v7 demo image available to their partners. This interactive channel represents a website for an Insurance company and is defined with two zones, each with a single interaction point. One for home page landings, which would be the assumed landing page a user would see. Second, a signup page where a user would sign in based on existing credentials and/or register for first time use.

image

Interactive Session

From within the Interactive Channel summary tab, click on the related session Insurance. This will show the interactive session and its associated flowchart into focus for review.

image

Reviewing the associated flowchart, we see a simple segmentation of the incoming individual based on their related FICO score. Examining the process box FICO Score, the segmentation is as follows:

Low FICO Score Score < 200
Med FICO Score 200 < Score < 400
High FICO Score Score > 400

image

Lastly, examining the interaction process box Indiv_Id Profile the expected meta data for a session is shown along with the expected Audience. This will come into play later when the API initiates an interact session. For now, note that the audience level is Individual and the associated key is Indiv_Id. Also note the Score attribute in the record’s metadata used above for segmentation purposes.

image

Interactive Campaign

The last piece of the Interact puzzle is the associated interact campaign. Here is where the associated offers are defined by segment. I won’t go into the specifics as there is a complete User’s Guide for that, but here is where we can rank our offers. Note that some of the offers listed have expired, which is why they will not be shown later during the coding exercise. Also note that we have some offers tied directly to a given zone and that the offers have an associated ranking for presentation purposes.

image

Visual Studio Setup

With the review of the interact setup out of the way, it’s time prepare the VS environment for some coding. I’m using C# for this exercise which will limit me to using SOAP. Unica warns that the best performance is achieved using their interact_client.jar, but 1) I’m playing and 2) I’m not concerned with performance right now and 3) C# and .jar wouldn’t work to well and 4) I like C# more that I like java.

Import the WSDL

The WSDL for Interact can be found under:

<Affinium_Home>\Interact\conf\InteractService.wsdl

Be sure to use the file from your installation as a version incompatibility could exist!

Once you have the WSDL downloaded, you can build a DLL out of it by doing the following steps:

  1. As administrator, open a Visual Studio command prompt. This is different from just a normal DOS prompt as it has environment settings. The link is in the start menu under the Visual Studio 2008 folder.
  2. Using the wsdl.exe utility, generate a C# Class
    wsdl /l:CS /protocol:SOAP \InteractService.wsdl
  3. Compile the proxy class as a DLL
    csc /t:library /r:System.Web.Services.dll /r:System.Xml.dll InteractService.cs

Visual Studio C# Console Program

Add a InteractService.DLL Reference

Create a new C# Console program. Once the project structure is created, we’ll reference the DLL that was compiled from above. Once does this by Right-Clicking on the Reference folder in the Solution Explorer window and opting for Add Reference..

image

Build a Helper Class

I created a helper class in my code. The class is basic as potatoes, but it allows for the quick definition of NameValuePairs. These name-value pairs are important as they define the session’s record structure. Recall I mentioned that earlier in reviewing the session’s metadata.

    class InteractHelper
    {
        public NameValuePairImpl defineParm(string parmName, int valNumeric)
        {
            NameValuePairImpl parm = new NameValuePairImpl();
            parm.name = parmName;
            parm.valueAsNumeric = valNumeric;
            parm.valueDataType = "numeric";
            return parm;
        }
        public NameValuePairImpl defineParm(string parmName, string valString)
        {
            NameValuePairImpl parm = new NameValuePairImpl();
            parm.name = parmName;
            parm.valueAsString = valString;
            parm.valueDataType = "string";
            return parm;
        }
        public NameValuePairImpl defineParm(string parmName, DateTime valDate)
        {
            NameValuePairImpl parm = new NameValuePairImpl();
            parm.name = parmName;
            parm.valueAsDate = valDate;
            parm.valueDataType = "datetime";
            return parm;
        }
    }

Note in the code that there are three defined valueDataTypes for the NameValue pairs. These are:

  1. numeric
  2. string
  3. datetime

Build Console Main()

Keep in mind that this is just a glorified HelloWorld program with the intention to get you started. That being said, the bulk of the code is just thrown into the Main method in the Console Program’s class. Computer Science geeks can check their attitude at the door.

class Program
    {
        static void Main(string[] args)
        {

            InteractService _svc = new InteractService();
            //define the URI for the interact service listening for requests
            _svc.Url = "http://localhost:7001/interact/services/InteractService";

            //this will validate that we connect successfully upon receiving a version
            //number from the service
            getVersionResponse rVersion = _svc.getVersion();

            //setup the name-value pair(s) specifying the audience
            NameValuePairImpl IndivId = new NameValuePairImpl();
            IndivId.name = "Indiv_Id";
            IndivId.valueAsNumeric = 948;
            IndivId.valueDataType = "numeric";
            NameValuePairImpl[] initAudience = { IndivId };

            //setup the expected record structure for the session
            //these values don't have to have values, but the structure must
            //be defined!
            List<NameValuePairImpl> parmList = new List<NameValuePairImpl>();
            InteractHelper hlpr = new InteractHelper();
            parmList.Add(hlpr.defineParm("Score", 250));
            parmList.Add(hlpr.defineParm("HHold_Id", 372));
            parmList.Add(hlpr.defineParm("Head_Of_Hhold", "1"));
            parmList.Add(hlpr.defineParm("Score_Date", DateTime.Now));
            parmList.Add(hlpr.defineParm("Score", 300));
            parmList.Add(hlpr.defineParm("Age",30));
            parmList.Add(hlpr.defineParm("Income",35000));
            parmList.Add(hlpr.defineParm("Gender","M"));
            parmList.Add(hlpr.defineParm("Primary_Language","English"));
            parmList.Add(hlpr.defineParm("Marital_Status", "Single"));
            NameValuePairImpl[] sessionParms = parmList.ToArray();

            //start the interact session
            Response r = _svc.startSession("123456", false, true, "Insurance", initAudience, "Individual",
                sessionParms);

            //get available offers for the session
            Response rOffersAvail = _svc.getOffers(r.sessionID, "OnLineInsuranceHomePage", 5);

            //end the program
            Console.WriteLine("Done");
        }
    }

Summary

There are a few things that are important to review. These are represented in the images below.

First, the record structure defined within the Interact session should be in sync with the name-value pair array submitted when initiating an Interact session. This is shown in the image below while using my helper class for defining the Name-Value pair array.

Second, the offers received as part of the session match against the offer rules defined as part of the campaign for the given interaction zone. All offer rules from other campaigns are applied, such as expiration dates rendering an offer invalid. In the example below, I’m showing the program running in debug mode while watching variable assignment. Note that two offers are returned when making the getOffers() request for an individual with a FICO of 300 (aka. segment=MedFICO). The offers suggested are both active across all zones. The other two defined across the zones have both reached their expiration date. As a result, they are not returned.

And that is it. If you haven’t fallen asleep by now, congrats you made it. Hope it helps as you learn Interact. There are some tricky bits that make the getting started process bumpy. This post with the code samples should help you get going faster.

July 9, 2010

Pimp your Eclipse!

Filed under: Uncategorized — Zack @ 6:30 pm

Props to the dark theme creator for a better looking Eclipse.

http://blog.prabir.me/post/Dark-Eclipse-Theme.aspx

June 8, 2010

RightNow .NET API Performance = Not So Good

Filed under: CRM, RightNow — Zack @ 1:59 am

Just a little update to my previous posting on RightNow‘s .NET API performance.

I’m not a fan of Salesforce.com, but this API has me CRYING for their Apex Data Loader. Apex was FAST!!! It was extremely fast for selecting records. But it was even fast inserting and updating records. That was an awesome tool — dump the records out, massage them in Access using SQL, pump the records back in, go home an eat lunch. Done in 3hrs.

So here are the latest metrics:

RightNow .Net API

Extract: 1.5MM records in 1hr 4min

Update: 1.5MM records 3days+

Some of you may ask what is the update and how involved is it? I believe it to be a fairly simple task, myself. I’m updating each contact record and setting a custom field’s value to an externally assigned primary key. The one excuse I will allow RightNow is that there are 250 or so custom fields for the contact. I would expect some performance degradation, but a data conversion of 1.5mm records taking longer than 3days is just stupid.

I love coding in .Net, but man is this worthless!

RightNow Analytics — The SQL Way

Filed under: CRM, RightNow — Zack @ 1:47 am

I always lose sight of this when I need it. That and RightNow’s website hides this from anyone’s view (side rant: really, how does one search in Google for RightNow the product?). Gartner says RightNow is #1 for customer support KB search, but I can never find shit using their support KB search. (side rant: seriously how much was Gartner paid?)

Create a New Report via SQL

To do this, we’re going to be using a custom script.

  1. Define a filter that will always return zero rows.
    filter: 1=0
  2. Select Level > Custom Scripts
  3. Select the ‘Finish tab of custom scripts
  4. Paste in the following while modifying the SQL to your liking:$temp=array();
    $row_idx = 0;
    //Run the desired query
    $query=sql_prepare
    (sprintf("
    SELECT label,ac_id, header_code, init_code, process_code, exit_code
    FROM ac_scripts a, labels l
    where a.ac_id = l.label_id
    and tbl=121
    and (header_code is not NULL
    or init_code is not NULL
    or process_code is not NULL
    or exit_code is not NULL)
    "));
    //Each column in the SELECT clause will need to be returned as the appropriate data-type (INT for integer, NTS for string, DTTM for datetime)
    sql_bind_col($query,1,BIND_NTS,80);
    sql_bind_col($query,2,BIND_INT,0);
    sql_bind_col($query,3,BIND_NTS,1000);
    sql_bind_col($query,4,BIND_NTS,1000);
    sql_bind_col($query,5,BIND_NTS,1000);
    sql_bind_col($query,6,BIND_NTS,1000);
    //For each record returned in the above query, return it as one row of output, each field in its respective column
    while ($temp = sql_fetch($query))
    {
    $exit_obj[$row_idx][0]->val = $temp[0];
    $exit_obj[$row_idx][1]->val = $temp[1];
    $exit_obj[$row_idx][2]->val = $temp[2];
    $exit_obj[$row_idx][3]->val = $temp[3];
    $exit_obj[$row_idx][4]->val = $temp[4];
    $exit_obj[$row_idx][5]->val = $temp[5];
    ++$row_idx;
    }
    //Clear your buffer
    sql_free($query);
  5. $exit_obj is the array returned, whose values are subsequently displayed in the report

May 26, 2010

Outlook Barfing on GMAIL via IMAP

Filed under: Uncategorized — Zack @ 5:56 pm

No idea what happened, but found that Outlook wouldn’t send anymore messages via GMAIL IMAP. I found this little morsel and viola… problem fixed.

http://theofficecubicle.com/2008/02/01/outlook-2003-red-x-where-embedded-image-should-be-in-email/

  1. Exit out of Outlook 2003 on the machine with the issue
  2. Open the registry (Start->Run->type cmd->click Ok)
  3. Navigate and open the following registry key HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Outlook\Security\OutlookSecureTempFolder
  4. Within the key…it should say something like  %USERPROFILE%\Local Settings\Temporary Internet Files\OLK3D\
  5. Highlight and delete %USERPROFILE%\Local Settings\Temporary Internet Files\OLK3D\
  6. Close out of the registry and open Outlook 2003!
  1. Exit out of Outlook 2003 on the machine with the issue
  2. Open the registry (Start->Run->type cmd->click Ok)
  3. Navigate and open the following registry key HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Outlook\Security\OutlookSecureTempFolder
  4. Within the key…it should say something like  %USERPROFILE%\Local Settings\Temporary Internet Files\OLK3D\
  5. Highlight and delete %USERPROFILE%\Local Settings\Temporary Internet Files\OLK3D\
  6. Close out of the registry and open Outlook 2003!

February 24, 2010

Fun with c# and the RightNow API

Filed under: .Net, RightNow — Zack @ 12:29 am

I wanted to dump out data from RightNow’s Contact tables. The intention was to load a SQL Server table that would then be used in later ETL for data quality rules.

The code does the magic I want.

  • Execute a RightNow report for a range of contacts.c_id values
  • Store the results in a SQL Server table on my local machine

The only problem is performance. SFDC can dump out 2-3million rows in an hour. My code was far from efficient as it was built for a quick-exercise. The code for 1.5million rows would finish in about 14hours. YUCK! Update: I was able to score 760k records in 1.5hrs … much better.

Here’s my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using obj.api.rightnow.com;
using fault.api.rightnow.com;
using api.rightnow.com;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;

namespace Becker_DataExtract
{
    class Program
    {
        static void Main(string[] args)
        {

            RNOWObjectFactory ofactory = new RNOWObjectFactory(Properties.Resources.RNOWConnection);
            ofactory.login(Properties.Resources.RNOWLogin, Properties.Resources.RNOWPass);

            //database stuff
            string connString = "server=(local)\\SQLEXPRESS;Initial Catalog=BeckerPOC;User ID=becker;Password=becker";
            string insertSQL = @"insert into RNContacts(c_id,org_id,last_name,first_name,email,email1,email2,street
,city,prov,postal_code,country,ph_asst,ph_fax,ph_home,ph_mobile,ph_office, RNLastUpdated)
values
(@c_id, @org_id, @last_name, @first_name, @email, @email1, @email2, @street
,@city, @prov,@postal_code,@country,@ph_asst,@ph_fax,@ph_home,@ph_mobile,@ph_office, @RNLastUpdated)
";
            SqlConnection conn = new SqlConnection(connString);
            conn.Open();
            SqlDataAdapter da = new SqlDataAdapter();

            object[][] reportResult;

            System.Console.WriteLine("Staring process: " + DateTime.Now.ToShortTimeString());

            for (int i = 1; i <= 25; i++)
            {
                List<RNOWAcFilter> reportFilters = new List<RNOWAcFilter>();
                RNOWAcFilter reportFilter = new RNOWAcFilter();
                reportFilter.Operator = Convert.ToInt32(RNOWUtil.SearchOperator.RANGE);
                reportFilter.Value = i.ToString() + "|" + (i * 1000).ToString();
                reportFilter.FilterId = 1;
                reportFilters.Add(reportFilter);
                reportResult = ofactory.ExecuteReport(Convert.ToInt32(Properties.Resources.RNOWExtractReport), reportFilters.ToArray());

                foreach (Object[] result in reportResult)
                {
                    SqlCommand cmdSQL = new SqlCommand(insertSQL, conn);

                    SqlParameter c_id = new SqlParameter("@c_id", Convert.ToString(result[0]));
                    cmdSQL.Parameters.Add( c_id );

                    SqlParameter org_id = new SqlParameter("@org_id", Convert.ToString(result[1]));
                    cmdSQL.Parameters.Add(org_id);
                    SqlParameter last_name = new SqlParameter("@last_name", Convert.ToString(result[2]));
                    cmdSQL.Parameters.Add(last_name);
                    SqlParameter first_name = new SqlParameter("@first_name", Convert.ToString(result[3]));
                    cmdSQL.Parameters.Add(first_name);
                    SqlParameter email = new SqlParameter("@email", Convert.ToString(result[4]));
                    cmdSQL.Parameters.Add(email);
                    SqlParameter email1 = new SqlParameter("@email1", Convert.ToString(result[5]));
                    cmdSQL.Parameters.Add(email1);
                    SqlParameter email2 = new SqlParameter("@email2", Convert.ToString(result[6]));
                    cmdSQL.Parameters.Add(email2);
                    SqlParameter street = new SqlParameter("@street", Convert.ToString(result[7]));
                    cmdSQL.Parameters.Add(street);
                    SqlParameter city = new SqlParameter("@city", Convert.ToString(result[8]));
                    cmdSQL.Parameters.Add(city);
                    SqlParameter prov = new SqlParameter("@prov", Convert.ToString(result[9]));
                    cmdSQL.Parameters.Add(prov);
                    SqlParameter postal_code = new SqlParameter("@postal_code", Convert.ToString(result[10]));
                    cmdSQL.Parameters.Add(postal_code);
                    SqlParameter country = new SqlParameter("@country", Convert.ToString(result[11]));
                    cmdSQL.Parameters.Add(country);
                    SqlParameter ph_asst = new SqlParameter("@ph_asst", Convert.ToString(result[12]));
                    cmdSQL.Parameters.Add(ph_asst);
                    SqlParameter ph_fax = new SqlParameter("@ph_fax", Convert.ToString(result[13]));
                    cmdSQL.Parameters.Add(ph_fax);
                    SqlParameter ph_home = new SqlParameter("@ph_home", Convert.ToString(result[14]));
                    cmdSQL.Parameters.Add(ph_home);
                    SqlParameter ph_mobile = new SqlParameter("@ph_mobile", Convert.ToString(result[15]));
                    cmdSQL.Parameters.Add(ph_mobile);
                    SqlParameter ph_office = new SqlParameter("@ph_office", Convert.ToString(result[16]));
                    cmdSQL.Parameters.Add(ph_office);
                    SqlParameter RNLastUpdated = new SqlParameter("RNLastUpdated", Convert.ToString(result[17]));
                    cmdSQL.Parameters.Add(RNLastUpdated);

                    //da.InsertCommand = cmdSQL;
                    cmdSQL.ExecuteNonQuery();
                    cmdSQL.Dispose();
                }

                System.Console.WriteLine("Done with loop run: " + i.ToString());
            }

            System.Console.WriteLine("End of process: " + DateTime.Now.ToShortTimeString());
            conn.Close();
            ofactory.logout();
            ofactory.Dispose();

        }

    }

}

Update:

Looking at the comments on this post, it appears that I have RightNow checking my code. Yes. there is a bug in it. The idea is to use a report to dump out data. So the start range needs to be incremented more than it is in the AcFilter.

February 17, 2010

C# interacting with a web form

Filed under: .Net, RightNow — Zack @ 11:45 pm

Sweet.. I love the web. I needed to build a POC for a RightNow project I’m working on. BAZINGA

Not only was it an awesome domain name. But, the code is exactly what I require. THANKS!

Older Posts »

Theme: Shocking Blue Green. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.