Thursday, 21 March 2013

QuikTip: Window Shake - Win7

Click and hold the top bar of an Window... (if it's maximized, drag the Window down a bit so it auto-restores, and then give the mouse a slow shake side-to-side...   All the Windows around it will minimize.   Another slow shake side-to-side and they all come back.

(If the Window is a modal dialog then all but its parent Window will minimize.)

I found a Windows tool recently (via a Twitter post) called AltDrag:  With this you can press ALT and click anywhere within a Window to drag it around... using CTRL as well makes the Window active..  Change options so that the Window you drag snaps to borders and taskbar (works like Aero in XP)...  AutoRemaximize - a window dragged from one screen to another will re-maximize after a second...

Unfortunately it doesn't implement the shake I mention above.  Perhaps in the next release.

Tuesday, 26 February 2013

MySQL Pager Options

I've had a long hiatus from Windows Server work... I wasn't working much whilst moving away from the Peak District to York... and now I am diving back in with a digital asset management software, ResourceSpace running on a RackSpace Cloud Server (and on a local BitNami ResourceSpace VM, PHP, MySQL - not my usual bunch, but they are proving not too hard to dig deep and debug).

The MySQL console app is a very powerful .. and probably one should only go into a small function in detail, rather than attempt to explain everything that can be done with it... I've been using it in several ways over the last few weeks.. most of this will be familiar to seasoned Unix users...

This one comes in handy when I want to output a whole load of detail into a tab-delimited file, which I can then grab via ftp and stick into Excel (unfortunately not directly - I needed to open the text file in Notepad++, select all, copy, then paste into Excel - that little trick converts the Unix tabs into Excel cells correctly) - from the command prompt (not in MySQL):
echo "select field1, field2, field3 from table1 where somecriteria = true" | mysql resourcespace -uroot -p > results.txt
If I just want to log what I am seeing to inspect it later, or just in case I want to keep a track of what I have done in that session .. then on the MySQL command line \T /home/user/os.txt will log output to the file, ox.txt.  All output.  It won't stop logging until you enter \t by itself.

Anyway, today I have taken a break from using SSH to access the Cloud Server, where I can scroll back through the handy buffer.. and am using the terminal session on my local VM via VirtualBox... and there's no buffer... So here's my discovery for today (which I'll probably use later in SSH too)... (in mysql)

  \P cat > results.txt

Pager...  I just wanted to stop the results scrolling off screen, to page through them one page at a time so I can scan the records...  but I've discovered something that is altogether very powerful...  Pager - this relies on popen() - which creates a pipe, forks the results and invokes the shell to process the command - it is very useful for passing results into sh scripts which is where a lot of power can be found...  The above pager outputs only the results to a file - which is preferred over tee.  

  \P more

Pager = More: Now I can press space to jump a page, CTRL-Z if I want to jump back to the Unix prompt (fg to return to the mysql session - this works whether you use more or not), CTRL-C quits the SELECT command but not the mysql session... Another pager:

  \P less

Pager = Less: Now you can use d = page down, u = page up, r = skip, q = quit, 100g = jump to line 100, g = jump to first line, G = jump to end line, '=' = tells you how big the results are and where you are in that i.e 85%, /pattern = search forward for regex pattern, ?pattern = search back for pattern and so on.

  \P less -I -p "headline"

Pager = Less (-p highlight text) Now that's pretty cool... on all mysql output, the word 'headline' is highlighted (-I = case insensitive).. useful if I am trying to look out for fields that contain a particular word or phrase... 

  \P less -S

Pager = Less (-S = no wrap) stops wrapping of lines in the results, but if fields contain carriage returns then they do drop to the next line - you can use the left and right arrows to view columns that are off-screen... (or you can use \G instead of \g to run your SELECT statement ( SELECT * FROM table \G ) to view rows as a single column.

A more complex version (from the MySql pages) of cat -> tee -> less can log to two different files at the same time and output to less:

  \P cat | tee /tmp/file1 | tee /home/user1/file2 | less -niSFX

  \P /tmp/grep_cmd

Pager = grepping (found on the SQL Performance Blog) this requires creating a file in /tmp which I am calling grep_cmd with the following text -:
#!/bin/sh
grep -A 1 -B 1 -i --color 'headline'
You could add a pipe into less (" | less ") after 'headline' or add the pipe to the \P command above to page the output... Then make this an executable using chmod a+x /tmp/grep_cmd - Now once the pager is set, mysql will only print out the record with a match, and a single record above and below it.  Matches will be highlighted or coloured.  You could just put the grep command in the pager.. but the script could be built on.


  \P cat > /dev/null

Pager = (hide output) This hides the record output from view.  You can see the number of rows returned and number of seconds to run the query.   Useful for comparing sets of queries, where you aren't interested in the output.


  \P vim -

Pager = vim  see Daily Vim - I don't use vim - but this might be of use to those who do.  I imagine it's useful to throw the results directly into a text editor...


  \P tr -d '`'

Pager = trim backquotes (one backquote surrounded by single quotes)- This was posted by Giuseppe Maxima here.  This can be used to strip out characters from your result set.  His example (above) is to strip the backquotes from a ( SHOW CREATE TABLE table1 \G ) statement.  I found that you can add different characters between the single quotes and it'll strip them away too.. even whole words like 'NULL'.  It can also strip out the vertical lines from a table result set ('|')...

Finally... for anyone who gets this far... log into mysql using the first line... and then call the second.  (I saw this tip on Parvesh Garg's blog Optim MySQL )


  mysql databasename --xml -uroot -p 
  \P cat | tee /home/user1/output.xml | less -niSFX

This outputs the results to an XML file and to the screen.  The XML file output is well-formed too.


Friday, 3 February 2012

PDF Printing in Google Chrome: Bug? or should I worry?

I just received a PDF in my email ... and thought I'd view it and print it out.

First report ok.. my client's report looked fine.  Second report... er... The letters in their logo were scrambled and replaced with other letters.

The report was generated in MS Access... an Access Report that I originally created for my client.  It includes their logo as a BMP.  My client prints the report to a PDF, using something like CutePDF or pdf995.  He then emails the reports to my GApps.

I click on View next the the PDF.  And the Print.  I can then see the standard PDF print dialog.  So far the document looks ok to me.

However on the hard copy the text from the Logo has changed:


So I closed the PDF in the browser window, went back to my email, clicked on View again and re-printed... and all was fine.

Anybody want to hazard a guess what is happening?  Thoughts...
  • Is Google OCRing my [private] PDF, when it attempts to convert to a printable file?
  • The printer driver on my computer is doing it?  How does it know that I am printing letters in the PDF?
  • A virus?
  • If Google is putting the PDF through an OCR so that I can search it within Google Docs... then should I be worried about that?  
I think I will stick to using the Download option in future.  And print via Adobe Acrobat Viewer... Google Docs might be convenient, but I'm not sure I can trust the Chrome/Docs print service with confidential PDFs, until I know why this logo was not printed wysywig...


Wednesday, 1 February 2012

Crystal Reports: Sorting

I have a complicated Crystal Reports report - Management Report.   The report is based on a single table, which has been built up in Visual Studio, within my VB.NET Project.  The table pulls in data from about 7 different tables, with inner and outer joins... It contains all the fields that I need to calculate the sorting, as well as the display fields, and other fields I will use to calculate display fields.

For example,  ItemUidT1, ItemUidT2 are GUIDs from two tables and ItemRefT1, ItemRefT2 are strings from those two tables.  These two tables link to a main table by their respective ItemUids.


But I have one column in the report for printing ItemRef.  I want to be able to sort the whole table into all values from Table1 and then all values from Table2... but I also want the user to click a button on the form to change the sort order to an Index or Count value for all items irrespective of their Table.  Take it that the schema for Table1 and Table2 are very different, which is why they should not be stored in the same table with a 'flag' field.

This is not about building such a table... but using it in Crystal Reports.  The table could look like this:


fyi:
SELECT MainTable.MainTableUid,
               MainTable.ItemUidT1,
               Table1.ItemRefT1,
               MainTable.ItemUidT2,
               Table2.ItemRefT2,
               MainTable.OtherData
FROM Table2 RIGHT JOIN
             (Table1 RIGHT JOIN MainTable ON Table1.ItemUidT1 = MainTable.ItemUidT1)
                      ON Table2.ItemUidT2 = MainTable.ItemUidT2;
In the report I have created formula fields for displaying... so Formula: {@ItemRef} = [note: code is in VB Syntax not Crystal Syntax]
If Not IsNull({QueryMain.ItemUid1}) Then
    formula = {QueryMain.ItemRef1}
Else
    If Not IsNull({QueryMain.ItemUid2}) Then
        formula = {QueryMain.ItemRef2}
    Else
        formula = "n/a"
    End If
End If
My actual report has 8 sort fields.

SortFields(0):  Not linked to an Item Table

On one report I would like to move all the Items in the list which are not linked to an Item Table down to the bottom of the list.  To do this I create a new Formula called {@IsNotInItemTable1} =
If IsNull({QueryMain.ItemUid1}) And IsNull({QueryMain.ItemUid2}) Then
    formula = 2
Else
    formula = 1
End If
This is added to Report -> Record Sort Expert - sorted Ascending.

SortFields(1):  Alphabetical List of ItemRef

From the first sort, we have two groups of records... this in the Item Tables and those not.  I would like to sort by ItemRef next... the formula is the same as for {@ItemRef} above, but call it {@ItemRef1} for reasons that will be clear below.  And
formula = {@ItemRef}


SortFields(2):  OtherData

I first tried to add {QueryMain.OtherData} as a sort field on its own... but I ran into problems with it.  If I want to assign this field to SortFields(0) in my code, then CrystalReports keeps on throwing an error:

System.Runtime.InteropServices.COMException was unhandled
  ErrorCode=-2147213305
  Message="The sorting already exists"
  Source="RptControllers.dll"
  StackTrace:
       at CrystalDecisions.ReportAppServer.Controllers.SortControllerClass.Add(Int32 IndexToAdd, ISCRSort Sort)
       at CrystalDecisions.CrystalReports.Engine.SortField.set_Field(FieldDefinition value)

I'm not sure how to get around this to allow for assigning random fields... I can't seem to remove one field from the sorting so that I can add it elsewhere in the collection.  Maybe, using Reflection... My workaround however works by creating rearranged sets of SortFields for each sorting.  To prepare for the workaround, create a simple formula: {@SortOtherData1} =
formula = {QueryMain.OtherData}
SortFields(3-7) .. 

Other fields sort on other fields not listed... PriorityOrder1, IsGreen1, TotalScore1, .. etc.

In my code I load up the report...
daMain.Fill(rds.QueryMain)
Dim rpt As New ManagementReport
rpt.SetDataSource(rds)
rpt.SetParameterValue("Param1", paramString1)
rpt.SetParameterValue("Param2", paramDate2)
CrystalReportViewer1.ReportSource = rpt
I have toggle buttons on the form, to select different sort orders:
Sort 1 - is the default sort order.
Sort 2 - By Item Ref
Sort 3 - By Highest Score
The issue I was having was that when I assigned FormulaFieldDefinition {@ItemRef1} to SortFields(0) I would get the COMException (as above) from CrystalReports.  The answer was to make an exact copy of {@ItemRef1}'s code and save as a new formula {@ItemRef2}.  Repeat this for all SortFields.  Now the reason for not using FieldDefinitions for sorting, and converting them to FormulaFieldDefinitions becomes apparent...

If you have assigned a FieldDefinition to a SortField, you cannot assign it to another SortField without removing it first.  But if you create a FormulaFieldDefinition based on the field, then you can have copies of the FormulaFieldDefinition and assign them without the clash.  You simply have to make sure you replace all SortFields in one go...  Something like the following resorts the loaded report without having to reload the data... works like a charm... :-)

[Note: All the SortFields assigned by default end with the number, 1.  And assuming only 5 fields assigned.]


Sub Sort2ByItemRef()
            rpt = CType(CrystalReportViewer1.ReportSource, ManagementReport)
            Dim thisSort As SortFields = rpt.DataDefinition.SortFields
            thisSort(0).Field = rpt.DataDefinition.FormulaFields.Item("ItemRef2")
            thisSort(1).Field = rpt.DataDefinition.FormulaFields.Item("SortOtherData2")
            thisSort(2).Field = rpt.DataDefinition.FormulaFields.Item("IsNotInItemTable2")
            thisSort(3).Field = rpt.DataDefinition.FormulaFields.Item("SortPriority2")
            thisSort(4).Field = rpt.DataDefinition.FormulaFields.Item("SortHighestScore2")
            CrystalReportViewer1
.ReportSource = rpt 
End Sub
Sub Sort3ByItemRef()
            rpt = CType(CrystalReportViewer1.ReportSource, ManagementReport)
            Dim thisSort As SortFields = rpt.DataDefinition.SortFields
            thisSort(0).Field = rpt.DataDefinition.FormulaFields.Item("SortHighestScore3")
            thisSort(1).Field = rpt.DataDefinition.FormulaFields.Item("SortPriority3")
            thisSort(2).Field = rpt.DataDefinition.FormulaFields.Item("IsNotInItemTable3")
            thisSort(3).Field = rpt.DataDefinition.FormulaFields.Item("SortOtherData3")
            thisSort(4).Field = rpt.DataDefinition.FormulaFields.Item("ItemRef3")
            CrystalReportViewer1.ReportSource = rpt
End Sub

I've got it working... Added a new Sub called Sort1Default .. to revert to default sort order (by assigning sort fields ending in '1' in the default order...

And those were the simpler reports... now onto the massive Detailed Customer report...  It's taken a few hours to get my head around these SortFields and dynamically changing them ... no doubt someone is going to tell me I could have done it a simpler way... Do let me know... As it stands, these reports were being run from Access and that was fraught with difficulties because first you have to find the most up-to-date MDB... then check it works with the most up-to-date backend MDB... and then check to see if the queries are up-to-date...  That's many hundreds hours saved in the long term.

Thursday, 3 November 2011

old Compaq nx9005 - RIP

I was working on my nx9005 last night, taking some study notes... when there was the sound of a small tick and then a smell of burning electronics. I unplugged it from the life support system (power supply) and removed the battery.

The fan had been overworking for many a year.  I had performed surgery on the laptop several times to unclog the arteries within the fan unit from dust... but this was not enough... the multiple surgeries on the machine led to several further side effects due to aging of joints, such as limb failure (TouchPad) and front panel failure (power/wifi/BT indicator leds).

I pronounced my nx9005 dead at 5:30am 2nd Nov 2011 at the ripe old age of 8 1/2 years.



RIP.

The hard disk, WiFi card, optical reader and power supply were offered for donor parts.  All other parts are scrap.



The nx9005 had received a fair old innings as a development machine, media machine, word processing and spreadsheets, remote desktop support ... but spent its last year or two retired for general lap warming and as a TV guide / general browser duties...


[Edit 14:25 - old habits die hard:


Here's a photo after a few minutes of post-mortem... There's a good HD, Fan Unit, DVD Writer, Floppy, HD Caddy, AMD Processor, RAM PC2100 2x 512MB and a set of screws for the nx9005 (less one that is stuck in the casing)




[Edit 03:33 - I've had a Eureka moment...


A long time ago when I was (probably) cleaning the fan, I remember a small component fell off.. but I could not place it.  The PC worked so I simply ignored it.


As I was taping all the screws into a nice ordered file, ready for salvaging for spare parts... The other grey square component fell off - again I didn't notice where it came from.. But I have just realised I could download a photo of the motherboard from Google, and compare mine with a new one... The circled area is missing a component!  (Now it is missing both - so I could have simply compared it with this picture I took earlier.)  And the smell of burning is strongest around this area... I wonder what these components are for.. Could I attach a couple of new ones and get the old laptop working again?   I would, of course, have to fish the battery, and other bits and pieces out of the bin... nah... I don't think I can be bothered...   


For anyone who want a service manual, I found this:
        http://www.hp.com/ctg/Manual/c00246219.pdf
It covers nx9005, nx9000, nx9008, nx9010 and the ze series, and a few Presarios...


There's a handy list of POST Codes and Beep codes too... and diagrams of how to take your nx9005 to pieces... 


Having looked around eBay there are plenty of people selling old parts... even faulty motherboards... I think I might have a go to see how much money I can make from scrap ... than I could selling it as a faulty whole... 



Wednesday, 28 September 2011

Visual Studio 2008 and the corrupt (ADO-based-only) Dataset Editor

I have been struggling with VS2008 and the DataSet Designer for the last .. nearly 24 hours.  I've got one project with 5x ADO Datasets and one Dataset that is not attached to a database via a connection string.  I've not had this project open for a while... during which the following events have happened:

1) SQL Server 2005 Security Update for SP3 (KB2494113) failed because I had to catch a train - leaving SQL Server 2005 Standard in a corrupt and un-runable state... I managed to attach the database I was working on into SQL 2008 Express - so I didn't lose much in time... I have left SQL 2005 in that state since today and successfully installed SQL 2005 SP4 which has revived my corrupt SQL Server and the database is still attached and working... (now to update it with changes since then)

2) Several VS2008 Post SP1 Updates - namely: KB2538241, KB2251487, KB971092... It looks like I have installed them about 10 times each... this was down to what I think was a fault with WindowsUpdate in that it kept on offering me the same updates over and over - even after a successful install.... I managed to fix those and some recurring Office 2007 Updates with the automated FixIt from: http://support.microsoft.com/kb/971058

So... now my VS2008 projects open, compile and run perfectly well... all except from trying to open them in the "DataSet Editor" (right click the DataSet and choose Open With... you'll see a list of options.  It's a poor design because despite the great amount of control you have over add-ins and developing for VS you aren't shown what actions are taken when you click on any of the items in this list.  My guess is that you have to check the registry...

I select DataSet Editor from the list and I get this helpful error message:

"Load DataSet Error:  Failed to load dataset because of the following error:  Illegal characters in path"

Er... what path?  Click ok and the panel is filled... "To prevent possible data loss before loading the designer, the following errors must be resolved: Illegal characters in path.  Show call stack:"

at System.IO.Path.CheckInvalidPathChars(String path)
at System.IO.Path.IsPathRooted(String path)
at Microsoft.VSDesigner.Data.Local.ConnectionStringConverter.ToRunTime(Project project, ConnectionString csToConvert)
at Microsoft.VSDesigner.VSDesignerPackage.AppSettingsHelper.AddServerExplorerConnections(IServiceProvider serviceProvider, IList connections)
at Microsoft.VSDesigner.VSDesignerPackage.GlobalConnectionService.Microsoft.VSDesigner.VSDesignerPackage.IGlobalConnectionService.GetConnections(IServiceProvider serviceProvider, Project project)
at Microsoft.VSDesigner.DataSource.DesignConnection.GetConnectionFromAppSettings(String objectName, String propertyName, Project currentProject)
at Microsoft.VSDesigner.DataSource.DesignConnection.GetConnectionStringObject(Project targetProject)
at Microsoft.VSDesigner.DataSource.DesignConnection.get_ConnectionStringObject()
at Microsoft.VSDesigner.DataSource.DbSource.set_Connection(IDesignConnection value)
at Microsoft.VSDesigner.DataSource.DesignDataSource.SetConnectionProperty(Source source)
at Microsoft.VSDesigner.DataSource.DesignDataSource.ReadXmlSchema(DataSourceXmlTextReader xmlReader)
at Microsoft.VSDesigner.DataSource.DesignDataSource.ReadXmlSchema(TextReader textReader)
at Microsoft.VSDesigner.DataSource.Designer.DataSourceSerializationService.DeserializeToDataSource(String filePath, Object serializationData)
at Microsoft.VSDesigner.DataSource.ProjectDataSourceDescriptor.LoadDataSource()
at Microsoft.VSDesigner.DataSource.ProjectDataSourceDescriptor.Init(IServiceProvider provider, IVsHierarchy primaryHierarchy, UInt32 primaryItemId, Object primaryDocDataObject, UInt32 docCookie, IVsInvisibleEditor invisibleEditor, IDesignerHost host)
at Microsoft.VSDesigner.DataSource.ProjectDataSourceStorage.EnsureInvisibleEditor(ProjectItem dsProjectItem, Boolean ensureWritable, Boolean createInvisibleEditor, Boolean getUIInfo)
at Microsoft.VSDesigner.DataSource.ProjectDataSourceStorage.GetDataSourceInternal(Object caller, ProjectItem dsProjectItem, Boolean ensureWritable, Boolean createInvisibleEditor, Boolean getUIInfo)
at Microsoft.VSDesigner.DataSource.Designer.DataSourceDesignerLoader.HandleLoad(IDesignerSerializationManager serializationManager)


Ok,, I get there's a problem... I created a new project, and a new dataset using another database, a different driver (SQL not Jet), the designer loaded and I added a few tables... close the designer... re-open the designer and the same error message appears...  so it's not something in the ConnectionString - because I can add tables to a new DataSet in the Designer... and it's not to do with the Designer because I can still create DataSets...

I have another DataSet that has some hand-built tables... none of the tables in the Dataset are from databases... and this DataSet loads into the Designer as expected... no problems...

A further curious addition to this problem... Double click on DataSet1.xsc (View All Files must be checked to see the auto-generated .XSC file)... I can see the XML, but now another message pops up:

"MS Visual Studio:  Package Load Failure
Package 'Microsoft.VisualStudio.XsdDesigner.Package.DesignerPackage' has failed to load properly ( GUID = {20AAF8FA-14C0-4897-8CA0-4D861E2B1212} ).  Please contact package vendor for assistance.  Application restart is recommended, due to possible environment corruption.  Would you like to disable loading this package in the future?  You may use 'devenv /resetskippkgs' to re-enable package loading."  Yes/No

No, thanks...   But there's a GUID.. before closing that message.. open Regedit... HK_Local Machine.. Software.. Microsoft.. Visual Studio.. 9.0 .. look down the list, I see Packages.. and 20AA ->

CodeBase = C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.XsdDesignerPackage.dll
InProcServer32 = C:\Windows\system32\mscoree.dll
MinEdition = Standard
ProductName = XML Schema Designer
ProductVersion = 1.0

Looks ok to me.. the file exists in that location - version 9.0.30729.1 - 30/07/2008.

I see people suggesting starting devenv with switches such as 'devenv /resetsettings' 'devenv /resetskippkgs', 'devenv /setup' ... I tried them all... I even ran 'devenv /log' to create a log of the problem... but the log doesn't show the right level of detail around the event... there are warnings about loading SpecExplorer, CodeRush and another third-party add-in... Refactor?.. but none of these should interfere with the Dataset Designer...

I have now tried, right-clicking on a dataset and choosing to "Run Custom Tool" ... but the custom tool, MSDataSetGenerator, throws the same 'Illegal characters in path' error and this leaves my project with over 100 errors... most of which are now: "Type 'SurveyDataSet' is not defined" "Type ttt is not defined"  - the first error is "Custom Tool Error: Failed to generate code.  Illegal characters in path" ...

Because I tried to open the XSC file and it played with the XsdDesigner.. I'm also getting this:

Warning  104  The 'urn:schemas-microsoft-com:xml-msdatasource:DataSetUISetting' element is not declared. C:\Data\Projects\Test1\Datasets\DataSet1.xsc

I can ignore that .. because once I press compile it'll all go away... Nope.. it didn't go away... I'll try restarting VS2008 - hmm still all 'not defined'... Check the recycle bin - and the DataSet1.Designer.vb file is in there!!  Restore, refresh the Solution Explorer and include DataSet1.Designer.vb in project... and all back to normal...  well to whatever 'normal' is defined as today at least...

So.. where is the problem?  It must be something the Designer is loading?  Because the designer loads, and only fails to continue loading if the database links to ADO... It's trying to read the XML Schema.. which then has to get the connection string.. it's getting the connection string from AppSettings... and then failing...

When I load app.config - I receive the above Package Load Failure - for XsdDesigner ... and now the error messages are picking up on schema information:

Message  Could not find schema information for the element 'userSettings'. C:\Data\Projects\Test\app.config

Message  Could not find schema information for the element 'Test.My.MySettings'. C:\Data\Projects\Test\app.config
[..... and so on... for 'setting' 'name' 'serializeAs' 'value' ... until the end of the file...]

One of the updates was a new XmlEditor file... MS11-049 Security Update for VS2008 SP1: June 14, 2011 (KB2251487).  This includes a new Microsoft.XmlEditor.dll ... no other supporting files... or changes to the Designer.. MS11-049 is really about XML throughout the Operating System... it affected SQL Server, VS and MSXML...  If the Editor were at fault, then I would have a problem with ALL datasets?

-------------------  FIXED -------------------
To cut this long story short... I fixed it... I decided to download the last Service Pack.. To re-install VS2008 SP1.  The Microsoft.XmlEditor.dll file above is still there, so it may not have overwritten newer files... but it has sorted out whatever was corrupted in the files, registry or oledb_services... I can now edit DataSets again...

In order to re-install VS2008 SP1... I had to clear out 4GBs off my hard disk.. SP1 requires about 5.6GB free space... and it's left me with 4.3GB free (there's half a gig in a folder called 'Microsoft Visual Studio 2008 SP1' in my temp folder.. I might just copy that to my spare disk - just in case..)

At least this exercise has introduced me to VS Packages, how they work... I've fixed my broken SQL Server 2005 Standard install... and had a few ideas about moving on... (upgrading projects to VS2010, moving VS2008 to a VirtualMachine, or having one VirtualMachine with VS2008 or VS2010 per client... and all their individual projects... I may only have bought myself a few more weeks... this Lenovo 3000 is nearing it's 'Use By' date anyway...

Back to work...

Saturday, 11 June 2011

Orphaned Mailboxes and Users after migration from SBS 2003 to SBS 2011

I got a call today from a colleague doing a migration from SBS2003 to SBS2011 ... Exchange 2003 to 2010.

Mailboxes had been copied and he had decommissioned the old server to find that the mailboxes were not there... they were not showing up in the new server... had deleting them removed them from both servers?

At that stage you will have disconnected the connector between the two servers...

First .. go to the disk and check the size of the Exchange Store on the disk... The new store should be the same number of Gb as the old one...

Second.. open the Exchange Mgmt Console and type

  • Get-MailboxStatistics -Server servername
This should list all the mailboxes on the server.  You need to add a little bit to get more details... 
  • Get-MailboxStatistics -Server servername | select DisplayName, DisconnectReason, LegacyDN, ItemCount, MailboxGuid, Database
Moved mailboxes all had a LegacyDN that contains 'first adminstrative group' - this is normal and there's no need to spend hours, as I did, thinking it was an error and trying to correct it... Apparently that doesn't matter...

What really mattered was time... wait...  The mailboxes we had transferred over were large - around 2-4GB... they were neither disabled nor anything... the new server simply had not finished processing them.  I came back to the problem about 12 hours later and they were showing up... perhaps it took less time, but they eventually showed up... in the meantime, I had created some problems for myself...

Users were showing up in AD Users and Computers, but not showing up in SBS Console - I tried remedying that using the 'Change User Roles' trick   But that just created a second mailbox that started collecting emails ... and didn't connect to the old mailbox...  Worry about users not showing up in SBS Console AFTER the mailboxes show up.  When all your users are connected to their mailboxes then run the 'Change User Role' trick.

If you have created a duplicate mailbox, the ItemCount has increased and you really don't want to lose a single email, try connecting via OWA - you might be able to hook up the 'Archive' function and archive those emails out for later retrieval...  The mailboxes I created only picked up 1 or 2 emails and so I disabled the mailbox and used the Get-DisconnectedMailbox username | Remove-DisconnectedMailbox code from Mike Pfeiffer to get rid of the newly created mailbox.

Soon.. all mailboxes were showing up - they appeared in Disconnected Mailboxes in Exchange Manager.  So I selected the mailbox and tried to connect them to a user... but the user was not showing up... The mailbox name was correct - but Exchange could not see the users in Active Directory.. strange...
  • Get-User
Very simple... it produces a list of users and their RecipientType.  The users that Exchange could not see had a type of 'User' but those Exchange can see have a type 'UserMailbox'....  how to enable them?
  • Get-User | where-object{$_.Name -eq "User's Name"}   - this should list one user (just to check before changing anything...)  if ok, run this:
  • Get-MailboxDatabase -Server servername     - this gets the name of the database to use in this:
  • Get-User | where-object($_.Name -eq "user's name") | Enable-Mailbox -Database "database name"
Now run Get-User and check the user has changed RecipientType to UserMailbox.

Now you can go back to Disconnected Mailboxes in Exchange Manager and run Connect to connect them to their mailbox... (if it didn't do it for you when you ran Enable-Mailbox).

Once you have connected all your users up.. go to SBS Console -> Users and Groups -> Users... and run the 'Change User Roles' task - select 'Standard User' in the roles and below select 'Add Role to Users' (NOT 'Replace' - then you are not changing anything).  On the next page you click the checkbox at the bottom 'Show all users from AD' and select all the users (one to start with to test) who you don't see in SBS Console...  run it all through and refresh the view.. all the users should now show up.

One last thing I forgot... and perhaps a trick to get around this issue too... when you run the 'Change User Roles' task each user is given an email address based on the current 'Email Address Policy' ... this is in Exchange Manager.. under Organization Configuration -> Hub Transport -> E-mail Address Policies -> Windows SBS Email Address Policy ... unfortunately 'First Name Only' is NOT an option.. duh!  But we can get around that...
  1. Start -> Run -> adsiedit.msc  <- take care with this... if you get this far you probably are fine...
  2. right-click on AdsiEdit -> Connect To... -> Select a Well-known Naming Context -> Configuration
  3. Select Configuration in the console left panel -> then Configuration -> Services -> Microsoft Exchange ->  servername -> Recipient Policies
  4. In the right-hand panel for Recipient Policies - right-click Windows SBS Email Address Policy select Properties
  5. Click the Filter button and choose to show only attributes that have values
  6. gatewayProxy has a value of SMTP:%m@mydomain.com chang
  7. Click gatewayProxy and Edit - change to SMTP:%g@mydomain.com - %g is FirstName
  8. click ok and exit out of AdsiEdit.msc
And finally .. a warning if you have Blackberry Enterprise Server running... I think I read somewhere there was a knowledgebase article from RIM about what to do in the migration.. .. it was for Exchange 2003 to 2007.. but best to take heed of any advice before attempting to migrate...

Monday, 6 June 2011

BES Hell and the Case of the Missing Window

I was called on Friday... BES Express server down... numskull pulled the plug out of the wall... possibly during a SQL write... pages broken... help!

BESX - version 5.0.2 (Bundle 14)

Where do I start?

Logged into SQL Manager and ran "dbcc checkdb" on all the databases.... consistency errors in some of the tables in BESX... ran "dbcc checkdb (<dbname>, repair_allow_data_loss)" ran "dbcc rebuildindex <tablename>" on the tables... 12 consistency errors fixed...  I accept some data loss in this...

BESX Administration Service - "cannot find the requested page" or "Internet Explorer cannot display the webpage." - the same goes for Web Desktop Manager.  The joy of tying up all of your software's capabilities into a single jvm.dll based web UI... you can't be blamed if it doesn't load up....

So what is to blame?  I don't know.. I search high and low... In the end I uninstalled BESX.  To my regret.

One step back... I wanted to repair install BESX.  So I ran the installer - it stopped - error 2803.  I stopped all the services and tried again.  This time to install BESX "over the top".  I got through to the "Use Existing Configuration Database" .. cool... I can simply install this over the top...

Too soon! "The BlackBerry Configuration Database that you specified is associated with a previous installation of the BlackBerry Enterprise Server or BlackBerry Professional Software. You must create a new BlackBerry Configuration Database for BlackBerry Enterprise Server Express or specify a database that is associated with a previous installation of BlackBerry Enterprise Server Express."

I got fed up with it here - it IS a Config DB for BESX not BES - what are RIM talking about with this error message?... time was running out and I it had to be ready for Monday morning... so I uninstalled BESX.  I regret.

Oh joy... I bet this has something to do with AVG... (lol... I did check but I think AVG was acting normally... it had 58,124 "Virus Found FakeAlert" messages that took forever to not delete.. so when I came back much later a) the program had crashed and b) they had not been deleted ... i so love AVG - not)... 

I found somewhere online mention that I should check that the user BESADMIN has "Allow Log on Locally" as a right before I install BESX (on a side note - I checked through the Release Notes for BESX 5.0.3 (Bundle 12) and decided to download that - in case they'd fixed the 'configuration database is associated with BES and not BESX' error message (bug)... so .. Local Security Policy... er... what's going on here?
MMC could not create the snap-in
MMC could not create the snap-in The snap-in might not have been installed correctly.
Name: Group Policy object Editor
CLSID:{8FC0B734-A0E1-11D1-A7D3-0000F87571E3}
Darn it... something messed up with secpol.msc... Apparently we need gpedit.dll and gptext.dll... they are in System32 folder... and they are registered.. ("regsvr32 gptext.dll" worked but gpedit.dll threw a wobbly...) ... But that didn't solve it... I also need FrameDyn.dll from the wbem folder... it's there... and the program has to find that on the environment variable, PATH

Right... System Properties -> Advanced -> Environment Variables -> PATH= ... er... "...C:\System32;C:\System32\wbem;..."  WTF?!  Where has the "\Window" bit gone?  It goes to show that Windows Server can survive, just about, with this missing ... if you search around online for "c:\system32\wbem" it should not exist ... but it does exist - in one place someone uses it in a solution for the FrameDyn.dll ..  we are pointed to this kb http://support.microsoft.com/?kbid=826282  - be careful with implementing the solution... check that you don't just have a missing 'Window' next to the wbem path.

I wonder now... in retrospect, whether this missing Window was actually the cause of BESX not being able to load the Admin Service or Web Manager.   It can't check the security principals etc... It can't find WMI... 

BESX installed... we couldn't restore the old database over the top.. or copy data from the old db to the new... so we have had to wipe all the users' Blackberrys and reload them... thanks RIM...

The night was so long I can't remember if that was all there was... Space was an issue... an old server, so of course the Windows\installer folder was taking up several gigabytes which can't be removed safely... and the size of the system drive was only 12GB... from the days of small disks...  time for a complete re-install perhaps... 

I doubt anyone who reads this will have exactly the same problem .. this is a Blackberry Enterprise Server Express 5.02 SP1 issue I think.. plus the misfortune of a power failure (or a corrupted BESMgmt SQL DB from any other cause)... together with a malformed PATH variable... you have to be pretty unfortunate to have exactly the same symptoms... :)

I did wonder if it was a recent Windows Update that wrote the PATH variable incorrectly...  it appears to be somewhat common... I don't think people write "C:\System32\wbem" .. but someone has written: "%SYSTEMDRIVE%\system32\wbem" instead of "%SYSTEMROOT%\system32\wbem"

Let me know if that's the work of a virus ... that's the one thing I didn't bother to look into...

Friday, 3 June 2011

Paint.NET - can't update or remove 3.5.5

I appear to have been having problems updating Paint.NET.

I have version 3.5.5 and every time the installer runs to update I get an error about a missing MSI file in
C:\Program Files\Paint.NET\Staging.  Filename: PaintDotNet_753582080.msi.

Perhaps the Paint.NET team introduced the Staging folder after 3.5.5... who knows... some suggestions on forums:

  • Uninstall completely - does not work because you cannot uninstall it...
  • Hack the registry - I guess that might work, that would have been my last option :)
  • Rename one of the existing MSI files in the Staging folder - it only works if the MSI is the same version as the version that is installed.
  • Use the Windows Installer Cleanup Tool - now called the 'Patch Registration Cleanup Tool'? - you could ... but I have a cleaner solution...
How to update Paint.NET when asked for a Staging MSI:
  1. Find out the version that is installed. - Mine is version 3.5.5
  2. Go to File Hippo and download your current version.
  3. You need to unpack the MSI from the downloaded EXE... run from a cmd.exe window (or Start Run):
    Paint.NET.3.5.5.Install.exe /createMsi CHECKFORBETAS=0 DESKTOPSHORTCUT=0
  4. Open the folder created on your desktop, PaintDotNetMsi, and rename the file PaintDotNet.x86.msi to PaintDotNet_753582080.msi or whatever filename Windows Installer is asking for.
  5. Copy the MSI to C:\Program Files\Paint.NET\Staging
  6. Re-run the Paint.NET update - or uninstaller.
Mine has just finished updating itself... and I now have 3.5.8 --- albeit after weeks of hoping that each next installer would sort itself out :) .. finally I have got round to fixing it myself ...

Monday, 25 April 2011

Windows - No Disk - unhelpful Error Help messages

Windows - No Disk
Exception Processing Message c0000013 Parameters 75b6bf9c 75b6bf9c.


I am trying to run a QuickBooks QBFC 10.0 C# application and every time it tries to BeginSession I get this error...  Continue / Try again / Cancel...

I presume the "No Disk" error could indicate that there's a link to a file missing... nothing has changed...

Whilst searching for a solution I discovered www.wiki-errors.com - a good idea I thought - but 1) it took this meaningless error and threw a load of meaningless rubbish back at me... I am no wiser why the problem occurred and I have now spent another 10 minutes reading something that didn't help... 2) I can't edit the Wiki at Wiki-errors.com ... doesn't that defeat the purpose of a wiki?  I can't see how I can sign up and edit it either...  a truly beautiful social solution would be to allow lots of technical minded people look up an error and add our experiences to the solution... I want to edit that page and tell my solution...

but no.. I have now added yet another blog post to the massive number of blog posts about the "Windows - No Disk" error that is probably not very useful to anyone unless they happen to be developing QBFC10.0 in C# and one day their install goes tits up...

Quick solution:  If you're using a third-party library and developing software... just reinstall the software... see if that helps...

Actually I am not sure that was the answer now... there's a property on the referenced Interop.QBFC10lib.dll

  • Embed Interop Types = True / False - I changed this from True to False as well as re-installed the underlying library... so either change could have resolved the problem...
[Edit]
Just when I thought it was all fixed up... I now get the error again... it's gone from working to not working in the space of a blog post.

Well on further reading through the internet sludge... I have switched back to debug again... when I press Continue my program does actually run... it was not obvious at first because the program returns no data on first run at the moment, whereas it would have done a week ago, I forgot...  so stepping back through the pages, I can actually see data.  But I get the No Disk error every time I begin a session with QuickBooks.

I've got a couple of USB storage devices plugged into this laptop: an external USB HD and my printer has a card reader.  When I disconnect my printer, the error goes away.  When I connect my printer the error returns.  The external HD makes no difference.

Recap.. my printer's card reader is throwing an error in my C# QBFC10lib project when I try to create a session... because there is no sd/cf card in the printer.  That's crazy... How on earth do I prevent this on user's computers... I am calling the BeginSession with a blank field... that's supposed to find the QB file that is currently open.  So the QuickBooks SDK  is calling a Windows function, that is returning a 'No Disk' error... shouldn't QuickBooks deal with that?

Why provide us with a function that will bomb out randomly?

New Solution:   Don't let QBFC10lib search for the file you need to access.  Specify it.

Now to fix this inconsistent accessibility error (compiler error CS0051)...
Inconsistent accessibility: parameter type 'type' is less accessible than method 'method'

Resolved... seems that if you declare a public method, then all the types used as parameters must be declared public too... like selling a DVD of a film to everyone and only allowing the film to be played by DVD players in the right region...  or like distributing a software library which will bomb out randomly under certain unhandled circumstances...

Tuesday, 21 December 2010

Google Apps Migration

I added a new Page - to my blog - Google Apps Migration Checklist - a checklist of all the Google services that I had been using / or that one could use... and how I manage to transfer data from the standard accounts to the Apps account.

I did have a google Profile... but I can't access it anymore... it links to my Picasaweb which I also can't access...  It's said that there are no Profiles or Buzz yet in Apps - so my only task would be to delete that profile and free the profile name?

The trouble was that I had a Google Apps domain - oliverslay.com.  I already had a standard account @gmail.com ... When I tried to use Picasa or Profiles or other.. using my main email address, which was now in my Apps account, Google created a standard account with my oliverslay.com email - a third account! - through which I could access services not in Apps at the time.

When they expanded the services for Apps users this month, I had to give the account tied to my main Apps user, a different email address... and I gave it another address within my oliverslay.com domain..... I think... but now I cannot access that account.  The Profile has in the URL, oliverslay ... and Picasa has my name on it... I would like to use them...

I used Profile to send myself an email... the address on the profile sent a message to me.. and I received an email saying the message was sent... aha... it was sent to a different domain attached to my oliverslay.com Apps account... that means I can log in and transfer data across... phew!...

An AdWords account can have any user attached to it... and any number of users to administrate it... but a single email address cannot be attached to more than one AdWords account.  That needs to be understood when switching accounts around.  If you log into AdWords it will open a new account... so now, no-one can make you an administrator of their account.  I had to create a new user... give them administrator access to my new account, grant them access... then log in as them and terminate my own access to that AdWords account... just so my email address was now free to be attached to my client's account.

Trouble is, I discovered there's something called My Client Center - where you should be able to add various accounts in order to manage them...  http://www.google.com/intl/en/adwords/myclientcenter/  - So now I will have to terminate my access to my clients account and try again...

I was lucky with YouTube... YouTube had their own accounts before Google took them over.  I had a YouTube account and one day I associated that account with my standard GMail login... I found that I could disassociate it from my account, log in using the old YouTube account (the username and password of which you have to be able to remember) and then associate with my Apps account.  My brother was not so lucky... he never had an original YouTube account - and would be forced to re-upload his videos to his new Apps address and he'd lose his YouTube nickname...

Google Apps must be causing a lot of people a lot of headaches... it's not straightforward what can be done and what can't .. and nowhere is it made easy...

Sunday, 28 November 2010

old HP nx9005 - Win7

Finally I have Windows 7... installed on an old nx9005 - perfectly good laptop with a working OS... bit worn around the edges.. but why should I throw it?  The only thing that I've had to do with it in the past is install a new HD.. cos the Fujitsu one in there before developed the strange clicking problem... and I lost everything on it.. or perhaps I didn't .. I'm keeping it just in case, but I reckon it's got about 5 seconds of read time left if it ever does boot up because of my insistence on taken things apart .. :)

Maybe i can just replace the read head with an exact same disk.. ?  I'm sure there's a disk recovery place somewhere in Ireland or Wales that can retrieve data from clicking drives.. I read a review once...

Anyway.. drivers.. Conexant AC97 - wouldn't work in Win7... and HP are rubbish, they won't even develop anything for the nx9005... which is really really stupid... because the solution I found on MSDN Social Forum is merely a change in ONE LINE...  why on earth HP can't simply re-package the driver as Win7, with a single line edit (like I reckon MS used to do with DLLs between major Window's versions) .. Is it just down to Windows Compatibility signing?  My system didn't seem to care...

The solution is on here... by Mr. Raven...
http://social.technet.microsoft.com/Forums/en-US/itprovistahardware/thread/2857c5ef-bc13-49ce-bdd8-99bddb7d6b10/

It simply involves downloading the driver from HP - unpack and don't install:
http://h10025.www1.hp.com/ewfrf/wc/softwareDownloadIndex?softwareitem=ob-31530-1&lc=en&cc=us&dlc=en&product=1816346&os=228&lang=en

Then edit the INF file... find the [Conexant] section and add a new line with the PCI bus enum that Win7 has assigned to your sound card... can be found in System Properties -> Device Manager -> open Sound Device -> Details tab -> Hardware Ids from the drop-down.  Mine now looks like this:


[Conexant]
%*WDM_AMCAUD.DeviceDesc%=WDM_AMCAUD,PCI\VEN_1002&DEV_4370&SUBSYS_3091103C
%*WDM_AMCAUD.DeviceDesc%=WDM_AMCAUD,PCI\VEN_10B9&DEV_5451&SUBSYS_0024103C

So I wonder could you do that with most drivers?  I guess you could try... Download the WindowsXP driver, find the INF file.. find the manufacturer section [Conexant] ... and add the new line...

Only a few things change drastically between versions of Windows... and then they're re-marketed...

DrWatson was really quite useful in Windows 3.0... Windows 3.1... Windows for Workgroups... and then Windows 95 came along.

As I installed it, I was told that Windows 95 now comes with new! Dr Watson which would handle crashes...  rubbish... Windows Server 2003... comes with DrWatson....

Windows XP: [system32]\dwwin.exe 10.0.5815.0 - Microsoft Application Error Reporting - Original file = DW.exe
and DrWtsn32.exe - which has a user interface... for reading dumps... I couldn't find a dump to read...

Microsoft were originally going to call this Sherlock...  wonder why they didn't... maybe they couldn't get it past their legal team...

Apparently DrWatson has now been replaced by Problem Reports and Solutions...  but you can still type DrWatson into Start->Run (WinKey+R) ... or dwwin ...

Friday, 26 November 2010

Quickbooks SDK and Quickbooks Pro 2005 (UK)

I seem to have dived into the deep end... there are many versions of Quickbooks... and many versions of qbXML... many versions of QBFC ... and QBXMLRP ... slowly I think I might be getting my head around these ...

I've just got my code to open, begin, end and close a session with an open copy of QB Pro 2005 (UK) .. only to spend hours struggling to find out why I am getting all these "Unrecognised qbXML Version".. or "qbXML Version not supported"...

After every possible combination of SessionManager.CreateMsgSetRequest("", _maxQbXmlVer, _minVer)

Finally someone has talked some sense... QBFC10 DOES NOT SUPPORT UK3.0 ... ah... that's why I get "Country Code Incorrect".  Ok .. what does?  Hmm it appears that QBFC5 might be the only one that ever supported UK3.0...

One blogger, Doug Vanderweide, laments: "the quickbooks SDK, one of the sorriest, worst-documented excuses for a programming tool I've ever encountered." - I totally agree... I've been sitting here for 5 hours at least, and I've got so little done compared to nearly every other SDK I've ever used (perhaps apart from one mapping COM component - an early version of CadCorp).

Is it worth me plodding on?  The handy QBFC10 functionality is not available to QB2005... the client will be upgrading to 2010/2011 in the next 6 months... Let's first see if I can squeeze some functionality out of QBFC5... then have a quick go at using the QBXMLRP...(qbXML Request Process - basically XML-SOAP)

Success - QBFC5 did it! it works with values ("UK",3,0) if anyone is looking for that detail - unlikely but then I was... 6 hours to populate a spreadsheet with Customer details from QuickBooks... 24 rows... I could have typed that in a few minutes!  Their other database has 20,000+ records... So let's move one step at a time...

If I could used QBXMLRP then I'd have access to version 4.0?  Or is that just the US version?  I think the UK version is still UK3.0...  Ok... well it's good to know for future reference, that we're quite limited in what we can do if the client has a version less than QuickBooks 2008/2009 (UK) (qbXML v6).  QuickBooks 2010 UK supports up to qbXML Specification version 8.0. (US versions support up to 10.0)

right.. now to move the whole thing from Excel to Visual Studio.NET 2010... maybe fill some entities instead of the spreadsheet...

there are two QuickBooks SDK integration tools available that take all the pain from using the SDK - by RSSBus and n/software... but the one thing lacking from their websites was any indication of whether it would work with my version of Quickbooks... or any version... I think that should be made more obvious... I wasted enough time with the SDK... on top of that I wasted more time messing around with trial software that just wouldn't work on my version... I don't even know what versions those tools work on... it's near misleading, given the number of versions of Quickbooks still in the wild...  and these tools AND the SDK would help us out a great deal if it said - "Error: this SDK WILL NOT work with your version of Quickbooks in your country"

Saturday, 20 November 2010

Macs - Entourage - Split DNS - SBS2003 - Cisco 1841

Here's a question...

In this client's domain, there are a couple of servers.  Both SBS2003.  It is set up with an internal mydomain.local address.

The server has an external name - mail.mydomain.com.

The Macs have been set up with WebDAV and Entourage... and point to mail.mydomain.com... so on the SBS2003 DNS Server, mail.mydomain.com has to be defined as the 192.168.0.2 address of the server.  If it is not then the request for mail.mydomain.com is forwarded off to external DNS servers, which returns the address of the external interface of the Cisco 1841 router...

Clients on the outside can see mail.mydomain.com ... but they often open a VPN connection to the Cisco 1841 router... the router gives them a DNS of something.. it's own DNS proxy perhaps?

So the client has a network connection somewhere in the world... with DNS local to that ISP... they connect to the VPN and are given an IP address of 192.168.0.x ... and DNS is something...

but they can no longer connect to mail.mydomain.com ...

Is there an easy answer?   My only answer so far is to look up CCNA courses nearby... :)  The company who should look after this router want £NNN for a solution they can't guarantee will work... And it's not a client we want to mess around with... it has to work or not.