October 17th, 2008 | Tags:

I’ve been working on a small application recently and decided to include in the ability for the application to remember its position when closed and then when reloaded to appear is the same position.  I’ve run into a few problems with programs that do this is the past.  Specifically when resolution is changed or monitor configuration is changed.  For example my laptop may be connected to a secondary monitor at work, but not at home.  If I am running the application on the secondary monitor and close it, then when I’m at home and try to start the application it appears off the screen and I have to right click the task bar for the app, choose move, and then use my arrow keys to move it to a visible location.

I decided that I didn’t want my application to have this problem, but I still wanted to be able to save the position.  I searched the Internet for anything that would work and found many ways to save the position, but none of them seemed to take multiple monitors into account or more precisely an inconsistent monitor setup).  So after many tries I finally came up with a method that worked.  In this method I am storing the position in an INI file, but it could be stored in the registry or an XML file as easily.

I easily found code that would allow me to specify which screen to start on, but using that code, the coordinate reference assumes that 0,0 is the top left of the specified monitor.  When getting the coordinates of the form I could find nothing that would give me the coordinates based on the monitor in use.  Every method I found gave coordinates based on 0,0 being the top left of the primary monitor.  So if I positioned the form in the middle of my left monitor and exited I would store an X position of -600 (600 pixels to the left of the primary monitor), but when loading the form I need to tell it to move 424 pixes to the right from its origin on the secondary monitor.  All very confusing.

The key was to determine the bounds of the monitor used.  This uses the same coordinates referenced in the forms location so a 1024×768 monitor to the left of the primary monitor (also 1024×768) would have it’s upper left corner be -1024,0.  We can subtract the Bounds coordinates from the saved coordinates to find the coordinates relative to the top left corner of the monitor used.  I also check to verify that the position stored is within the bounds of the selected monitor, and if not display the form in the upper left corner of the selected monitor.  This way the form is never displayed in a position where it can not be seen.

Another problem with the code I found for specifying which screen to start on was that it did not verify the existence of that screen before trying to change to it.  So if a monitor was disconnected you would end up with an error.  Storing the selected monitor wound up being a bit more of a challenge than expected.  The property Screen.DisplayName pads the end of the string with a number of hidden characters.  Trimming off the extra characters solved my problems with this section, but it was annoying to track down.

I hope this helps anyone else who might be trying to achieve the same effect.

The following code goes in the Form_Load procedure
‘ Multi Monitor Aware – Restore Postition to last Used
Dim posScreen As Integer
Dim posX As Integer
Dim posY As Integer
Dim screen As Screen
‘ Read the previous screen used from the INI file
posScreen = Val(ReadIni(File, “Main”, “PosScreen”))
screen = screen.AllScreens(0)
‘ Verify the Specified screen exists, if so then use it
If screen.AllScreens.Length > posScreen + 1 Then
screen = screen.AllScreens(0)
Else
screen = screen.AllScreens(posScreen)
End If
‘ Read the Position from the INI File
posX = Val(ReadIni(File, “Main”, “PosX”))
posY = Val(ReadIni(File,
“Main”, “PosY”))
Dim pt As New Point(posX, posY)
If screen.Bounds().Contains(pt) Then
pt.X = posX – screen.Bounds().X
pt.Y = posY – screen.Bounds().Y
Else
pt.X = 0
pt.Y = 0
End If
Me.StartPosition = FormStartPosition.Manual
Me.Location = screen.Bounds.Location + pt

The following code goes in the Form_FormClosing procedure
‘ Save Screen Position
For i As Integer = 0 To
screen.AllScreens().Length – 1
If stringtoasc(screen.AllScreens(i).DeviceName.ToString) _
= stringtoasc(screen.FromControl(
Me).DeviceName.ToString) Then
WriteIni(File, “Main”, “PosScreen”, i)
End If
Next
WriteIni(File, “Main”, “PosX”, Me.Location.X)
WriteIni(File,
“Main”, “PosY”, Me.Location.Y)

*Note the ReadINI and WriteINI functions are in a module not shown here.  As they are not really a major part of the issue with positioning the form.  If anyone would like to see the related code I will be happy to post it, however there are several variations available by searching the Internet.

August 29th, 2008 | Tags:

I’ve recently come up with the need to copy a huge number of small files from one system to another.  Basically we are backing up about 20 million files that total a little under 10 terabytes.  So how is the best way to do this?  I first tried just setting up an extra gigabit ethernet adapted in each server and using a cross-over cable started copying with Microsoft’s Robocopy program.  If you’re not familiar with this it is available in the Windows 2003 resource kit and is a bit like xcopy with a lot more features.  My problem is that it just seemed to be going very slowly, taking about 2.5 days to copy 1 terabyte.  Perhaps that is as fast as it should be, I don’t know, but it was sure slower than I expected. 

I suppose I should explain the hardware involved to give the full picture.  The older server is a Pentium 4 server running Windows 2003.  The system has an external drive array with 16 drives.  The external drive system is configured as 4 RAID 5’s each about 1.5 TB.  This array is connected to the server via a SCSI adapter. 

The new server is a Xeon Quad Core also running Windows 2003 and has 24 driver bays internal to the server chasis.  The drives in the new server are configures with the first 16 drives as a RAID 60 (two 8 drive raid 6’s striped together for better performance) this provides about 11.2 TB, a 6 drive RAID 5 (4.5 TB) and 2 drives in a RAID 1 for the O/S.  The reason for the odd splitting is that I used two RAID controllers to connect all of the drives, a 16 port and an 8 port.  All of the drives in both systems are SATA II.

I decided to take the network cards out of the loop assuming that this was where my bottleneck was, although I never saw network utilization on the cards in question going above 10%.  I moved the SCSI card from the old server to the new and attached the external drive array to the new server.  This I assumed would give me a much faster transfer.  Unfortunately this has not been the case.  After 20 hours of copying only 650 GB have transferred to the new system. 

I’ve started testing some utilities that claim to improve copy speed (teracopy, fastcopy, totalcopy) and will post the results of the results of these tests here.  In the mean time it’s slow going.  Comments or suggestions?

————–

Update:

Well I tried a few of the copy programs I mentioned above.  I finally wound up using FastCopy.  There is one confusing part in that program depeding on if you include a trailing \ or not will affect what is copied, but this is documented as a feature, not a bug and overall the program did an excellent job.  One very nice feature of it is to queue copy jobs so that they will start one after the other.