Cuma, Eylül 19, 2008

When a method calls itself

This you can't do in RPG - have a method call itself. Sounds like something you would never use? Think again.

See this small console program that recurses through directories to get a list of folders and files. When the method finds a directory, it calls itself with the sub folder as a parameter whereupon the File part of the IF statement is executed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Recurse(@"c:\temp");
}

public static void Recurse(string directory)
{
DirectoryInfo path = new DirectoryInfo(directory);
FileSystemInfo[] files = path.GetFileSystemInfos( );
foreach (FileSystemInfo file in files)
{
if (file is DirectoryInfo)
{
Console.WriteLine("Folder-> " + ((DirectoryInfo)file).FullName);


// Now the method calls itself passing in the subfolder name. When the method is called
all the files in the subfolder are listed
Recurse(((DirectoryInfo)file).FullName);
}
if (file is FileInfo)
{
Console.WriteLine("File-> " + ((FileInfo)file).FullName);
}

}



}

}
}

Read, write and delete files in windows

Sooner or later you'll need to access files from the Window's file system. You'll need to check if a file exists, delete it, move it , you'll need to read and write to it and upload data from it to an iSeries table etc.

To illustrate how easy this is, I've included a full C# project.

This program cleans up a desktop. It moves unwanted items automatically to a 'clean up' folder automatically. Items you don't want to remove are maintained in a text file manually. This file is in 'CleanUp' on your desktop after you run it the first time.
Set it up to run in 'scheduled tasks' to run daily. My desktop gets absolutely splattered with downloads, images, files etc. etc. Now it gets cleaned automatically and the stuff I want to keep is always there. Files are moved but not folders.

The app demonstrates two things.

  1. How to access the windows file system
  2. How to write a RPG-like app in C#. i.e. in a procedural way There is a 'main', an init etc. There are no class objects created, everything runs from the class. Methods are just like subroutines. Variables are defined that are needed throughout the application as public at the top of the class. (If you define a variable in a method - it is only available within that method.)
using System;
using System.Collections.Generic;

using System.Text;
using System.IO;

using System.Security.Principal;


//Lists each object on the desktop
//Checks if the object is in the list.
//If not, moves it to cleanup.

namespace ClearDesktop
{
class Program
{

// Declare class level variables that are accessible from all methods
public static string cleanUpFolder = @"Cleanup\";
public static string desktopPathAllUsers = @"C:\Documents and Settings\All Users\Desktop\";
public static string desktopPath = "";
public static string cleanUpPath = "";
public static string cleanUpFile = "";
public static string allowedOnDesktop = "";



// Main Routine
static void Main(string[] args)
{
initializationRoutine(); // Set paths needed

RemoveFilesFromDesktop(desktopPath); // remove unwanted files
RemoveFilesFromDesktop(desktopPathAllUsers); // some file paths are in 'all users'
// Console.ReadLine();
}




public static void RemoveFilesFromDesktop(string dir)
{
// First create directory object from the desktop path
DirectoryInfo mainDir = new DirectoryInfo(dir);


// This single line fills an array called 'items' of everything on the desktop

// The items in the array are not strings but FileSystemInfo objects.


// What's cool here is each item has a ton of methods and properties


// available directly from it.



            FileSystemInfo[] items = mainDir.GetFileSystemInfos();



// Now go through each item in the array and check if it is allowed
foreach (FileSystemInfo item in items)
{
// Check if the file on the desktop is in the 'allowed' file
bool allowedyn = allowedOnDesktop.Contains(item.Name.ToString());

if (item is FileInfo && !allowedyn)
{
// If it is to be moved any existing same name file has to be deleted
String alreadyExists = cleanUpPath + item;

if (File.Exists(alreadyExists))
{
try
{
// Delete the file with the same name
File.Delete(alreadyExists);
}
catch (Exception)
{


}

}

// Move the file on the desktop to the clean up folder
((FileInfo)item).MoveTo(cleanUpPath + item);

}

}
}




// Get a list of all the files allowed on the desktop
public static string WhatsAllowedOnTheDesktop(string logFileName)
{

string contents = "";

using (FileStream fileStream = new FileStream(logFileName,
FileMode.Open,
FileAccess.Read,
FileShare.None))
{
using (StreamReader Reader = new StreamReader(fileStream))
{
contents = Reader.ReadToEnd(); // Reads the entire file in one statement
Reader.Close();
fileStream.Close();
}


}
return contents;
}

// Write to the 'Allowed files' directory those files you don't want to move
public static void WriteToLog(string logFileName, string data)
{
using (FileStream fileStream = new FileStream(logFileName,
FileMode.Append,
FileAccess.Write,
FileShare.None))
{
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine(data);
}
}
}

// Do basic setup - path names etc.
public static void initializationRoutine() {
string username = getUserName();

desktopPath = @"C:\Documents and Settings\" + username + @"\Desktop\";
cleanUpPath = desktopPath + cleanUpFolder;
cleanUpFile = cleanUpPath + @"CleanUpFile.txt";

// If the cleanup directory does not exist, create it
if (!Directory.Exists(cleanUpPath))
{
Directory.CreateDirectory(cleanUpPath);
}

// Create the log file of items you want to keep on the desktop

if (!File.Exists(cleanUpFile))
{
File.Create(cleanUpFile);
}

allowedOnDesktop = WhatsAllowedOnTheDesktop(cleanUpFile);
}

// Get the log on name of the user who started the app in order
// to know the path of their desktop
public static string getUserName()
{
WindowsIdentity ident = WindowsIdentity.GetCurrent();

string userid = ident.Name;
string username = "";
int pos = userid.IndexOf("\\");
if (pos > -1)
{

username = userid.Substring(pos + 1);
}
else
{
username = userid;
}


return username;

}

}



}

Converting RPG code to C# automatically?

What if you could take your RPG programs and hey presto! have them converted into .NET and instantly sell your product to the rest of the world. This would be a boon to AS/400 vendors locked into the small(ish) AS/400 market. The advantage is that the original product is likely a mature business proven system which can provide a critical edge against the deluge of competition once in the new windows space. While webfacing does provide a web front end to applications and is great for hosted models it does not help customers who are windows only and want windows only software.
Granted companies need to migrate on the competition level . However, all the supposed advantages such as performance, cost savings, availability of talent etc sounds hollow to long time AS/400 owners. Anecdotally we know that the uptime for the AS/400 is absolutely stunning compared to windows. It's super stable and extremely reliable. At windows only shops instead of maintaining one iSeries server and a handful of windows server you end up maintaining 20-30 windows servers for a small organization. But like I said, it's about getting your product out to a bigger market.
A big issue with migration products is that often your migrated solution will not be able to operate without them. Yikes!

I'll be doing a review of these migration products once I get my hands on them but in the meantime here's an overview. Click the title to go to the product website.

TranSoft ML-Impact
Well, the boys and girls at TranSoft claim that they can convert your old F-specs, c-specs to .NET . I would love to see the code generated (post a sample in comments pleez). They claim that CL and RPG will be converted to C#. Not only that they can take the DB2 tables and migrate them to SQL server. Not everything can be converted directly of course and the end result looks much like a 5250 application.
Without having the product available to me I can't give it the thumbs up or down but if you have any experience with this tool, please drop a comment.

ADC Austin
Remember Synon? The hot product of 20 years ago is now trying to be cool. They have jiggered a way to migrate from CA2E (Synon) to Plex which uses .NET. Sounds complicated. If you've tried it, drop me a line.

ASNA Monarch and AVR for .NET
ASNA monarch is a code converter that creates RPG for .NET while AVR is a Visual Studio add-in that allows RPG for .NET (an ASNA creation) development and compiles as a .net app. Seems like these two products have the same product base. The only feedback I've seen on this product is that there is no code completion, no automatic layout and ctl-z doesn't work. Your comments pls.

Lansa Ramp and the rest
There are a bunch of other sticky migration tools out there that are designed to keep you using their applications. While the products above are somewhat sticky you can still migrate off them. Products like the Lansa Ramp platform is a staged migration solution that requires you to develop a an application framework using their tools, prototype it, then recreate your screens in that framework. However the end product is a Lansa architecture that you have to stick with for the rest of eternity.

Typing the RenderView method in ASP.Net MVC

Since the first minutes I started playing around with the MVC framework something has bothered me about the use of magic strings in regards to the RendorView methods.

With the current implementation of RendorView there is NO compile time type checking to ensure that view even exists (evil magic strings). Also, there is no way to find all usages of a view without doing a 'global find' on the project.

If you can strongly type the view to be used you will benefit from compile time type checking, you can use ReSharpers 'Find Usages' and it is just less evil.

Here are 2 ways to do this:

1 - Generics
public virtual void RenderView<T>( object viewData )
{
RenderView(typeof(T).Name, string.Empty, viewData);
}

2 - Type provided
public virtual void RenderView(Type viewType, object viewData)
{
RenderView(viewType.Name, string.Empty, viewData);
}
Here are a few examples of code calling the new RendorView methods

1 - Generics

RenderView<SportsListing>(sports);

2 - Type provided

RenderView(typeof(SportsEdit), new SportsEditViewModel(sports));
Now if I change the name of my views, I will get a compile time error letting me know ALL the places the view was being used.

This is a GOOD thing.

Salı, Eylül 02, 2008

SQL Server 2008

Şuanda üzerinde çalışmakta olduğumuz proje sebebiyle SQL Server 2008 Enterprise sürümü veritabanı işlemlerini gerçekleştireceğiz. Bu kapsamla bu uygulamayı kurmam gerekti. Bir önceki sürümüne oranla kurulumu daha basit ve anlaşılır. Ayrıca da bellek/performans faktörlerini düşünürsek bir önceki sürümüne göre çok daha optime ve hızlı olduğunu görebiliriz. İlerleyen zamanlarda sql server 2008 ile ilgili yenilikleri(benim gözüme çarpan) sizlerle paylaşmaya çalışacağım. Alt tarafta sizler için SQL Server 'in olmazsa olmazlarından Management Studio 'unun başlangıç ekranını sunuyorum.

sql server 2008enterprise

Umarım kullanım olanağınız olur...