Looking for an Oracle IPM replacement?

You have hundreds of thousands, maybe tens of millions, of documents in your old Oracle IPM 10g system with only 6 months before Oracle closes the support door on that product forever. Or maybe you’re running an Optika Acorde or Stellent IBPM system which has been out of support for years. You’ve looked at the new Oracle 11g platform and it’s too heavy, complex, and missing many key capabilities that you need, features like: external searching with Linked Servers, COLD support, Office and .NET integration points, easy setup and maintenance, and a workflow system that is actually usable for someone without a PhD. Oracle is clearly, and publically, going in a different direction and moving away from traditional enterprise imaging and transactional content management.

And even if you knew of an appropriate replacement technology, how are you going to migrate all of that content out of IPM without disrupting your business? What product vendor is going to know enough about your old IPM system to be able to get the content , applications, saved searches, workflows and profiles moved to their platform? Oh, and you don’t want simply to replacement on product for another – you want a good return on this migration investment!

ImageSource has been delivering and servicing Optika Acorde, Stellent IBPM, and Oracle IPM systems for nearly 20 years (don’t get me started on eMedia!). We recognized Oracle’s change in direction several years ago and have created the perfect replacement solution for the retiring 10g product. The ILINX suite offers the same content management capabilities as IPM but goes way beyond that. In fact, ILINX is more powerful, easier to deploy, use, and maintain, with better scalability, 100% browser-based, built-in retention management, more secure, free mobile clients, cloud-ready, built on the latest Microsoft technologies.. I could go on and on.

Check it out for yourself at www.ilinx.com

Join the dozens of other Oracle IPM customers that have made the easy switch to a better, more powerful ILINX solution!

Randy Weakly
VP of Software Development
ImageSource, Inc.

Moving To The Cloud

For some interesting reading, range about the Internet for articles detailing the way the software world has changed in the past few years with the success of companies like Facebook and similarly ubiquitous, social-node technologies. Those companies have fostered the advent of the DevOps strategy, which is more a paradigm shift in corporate culture than merely a mechanical development/quality assurance/deployment strategy, and it demonstrates a new way of thinking about deployment scaling using the cloud (with an unbelievable number of servers available) while maintaining an aggressive development schedule. Sprint-cycle application development and cloud-based deployment are the order of the day for these newer entities. No longer does dev sit in a development cycle of a year or more, but rather a cycle that is measured in months at most, or weeks – even days. Getting customer-requested features quickly into the product and out to the customers is still job one, but – Oh, hey! – the difference in implementation! Ben Horowitz Article “How Software Testing Has Changed”
Continue reading

Creating Case Insensitive Dictionaries In .NET

For millennia, mankind has looked to the stars and wondered, “How can I create a generic Dictionary in .NET that allows me use case insensitive strings as keys?” Well today that age old question will be answered with this neat trick.

Simply put, all you need to do is add a StringComparer object when constructing a generic Dictionary that uses a string key, and make sure to use on of the IgnoreCase StringComparers that are offered. Below is some sample code to illustrate just how easy this is.

// Create a generic dictionary with a string comparer that ignores case sensitivity.
// This includes the following:
//  - CurrentCultureIgnoreCase
//  - InvariantCultureIgnoreCase
//  - OrdinalIgnoreCase
Dictionary<string, string> stringMap = 
     new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
stringMap.Add("Test Key", "Some value");

// Now try to access or change the corresponding value with the key.
// The case of the key string no longer matters.
stringMap["test key"] = "This will work";
stringMap["TEST KEY"] = "And also this";
stringMap["tEsT kEy"] = "And this as well";
stringMap["tEST kEY"] = "And finally this";

// This can be done with any dictionary that uses a string as the key
Dictionary<string, int> numberMap = 
     new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
numberMap.Add("Test Key", 0);

// Same deal here, you can use any case to get or set the values in the map
numberMap["test key"] = 1;
numberMap["TEST KEY"] = 2;
numberMap["tEsT kEy"] = 3;
numberMap["tEST kEY"] = 4;

And that’s all there is to it.  I hope you enjoy and find this useful.

Richard Franzen
ImageSource, Inc.

Update UI controls form background worker

When you try to update an UI control from background worker, you might see this error message.

Cross-thread operation not valid: Control ‘MyLabel’ accessed from a thread other than the thread it was created on.

This is how you update UI controls from background worker.

public void UpdateLabel(string text)
MyLabel.Invoke((Action)(() => MyLabel.Text = text));
   MyLabel.Invoke((Action)(() => MyLabel.Update()));


Using SQL Parameters for Insert statement.

Sometimes you need to insert a data to your database. Here is the safer way to insert a row using SQL parameter.
Passing parameters to SQL prevents you build dynamic SQL statement. Building a dynamic SQL statement is a security risk such as SQL injection.
Here is the sample code for insert statement using parameters.

public void InsertRowToDatabaseUsingParams()
//create SQL connection.
using (SqlConnection conn = new SqlConnection(connectionString))
//open sql connection.
string sqlCommand = "Insert into TestTable (column1,column2) Values(@column1,@column2);";

using (SqlCommand cmd = new SqlCommand(sqlCommand, conn))
//add column value to parameters of SqlCommand
SqlParameter param = new SqlParameter("@column1", SqlDbType.VarChar, 50);
param.Value ="value1";

param =new SqlParameter("@column2", SqlDbType.VarChar, 50);
param.Value ="value2";



Kyoungsu Do
Software Developer
ImageSource, Inc.

Making Command Line Calls In .NET

Sometimes you just need to call a console executable.  Whether it is legacy code or the only interface for 3rd party software, console applications are still used and still need to be interfaced with.  Fortunately, .NET comes with a class built specifically to get that job done.  The Process class, located in the Systems.Diagnostics library, can be called to handle console executables and their command line arguments.  Below is an example on how to call this useful class:

Process proc = new Process();

// First, specify the executable file name and any command line arguments
proc.StartInfo = new ProcessStartInfo("C:\\temp\\CmdLineProgram.exe", 
     "-i \"C:\\temp\\InputFile.txt\" -o \"C:\\temp\\OutputFile.txt\"");

// Next, since we want to run this in our program, we don't want the 
// shell to execute it nor have it display in an external window.
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;

// We also want to get any error or output data that the executable might write out.
// This should capture data normally written out to the console screen.
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;

// Now let the executable run.  We'll wait here for it to finish process.

// Gather any exit code information
int exitCode = proc.ExitCode;

// And get the output and error messages.
string errorMsg = string.Empty;
using (StreamReader reader = proc.StandardError)
     errorMsg = reader.ReadToEnd();
}string outMsg = string.Empty;
using (StreamReader reader = proc.StandardOutput)
     outMsg = reader.ReadToEnd();

Hopefully this small sample will help out with making calls to console applications.  Regarding retrieval of exit codes, output and error messages, not all console applications like to output them to the same place.  Sometimes all output messages actually go to the error message, so you may need to look there.  Some trial and error may be necessary, so make sure to test out the code to find what works and what doesn’t.