Friday, July 17, 2009

Hexagon v3: Building my new PC

Sorry for the lack of updates in the last time, but first I needed to get X-Setup Pro 9.2 out of the door and after that I had my three weeks summer holiday.

Soon after I got my new BMW K1300S which causes me to drive around like crazy. If you are interested, have a look at my tracks.

Back to computer, I have a new project: My new custom build PC called Hexagon v3. See the next post for the introduction.

Hexagon v3: Part 1 - Components

This is a post about my new custom build PC. See the other posts as well:

Part 1 – Main Components
Part 2 – Case fans
Part 3 – Case assembly
Part 4 – Full assembly
Part 5 – Over clocking

 

My custom PCs are always named HEXAGON or OCTAGON (that’s because there are some weeks where I use them both and Windows does not like equally named computers within the same network). Each new build gets an version number because I’m a programmer and I like version numbers :-).  I’m writing this on OCTAGON v2, so the new PC will be HEXAGON v3.

Hexagon v3 Main Components

image

CPU: Intel Core i7 920 (Bloomfield)

I like the features it has like the integrated memory controller (although this idea is stolen from AMD) with the triple channel interface. As it looks like, you can overclock the 920 very good so I hope I can each 3.2 GHz with it. I know that new Core i7 “Lynnfield” are on their way, but they will no longer have the triple channel for the memory.

 

image Main board: Gigabyte GA-EX58-UD4P 

UPDATE As it seems this is EOL, replaced with Gigabyte GA-EX58-UD5

X58 chipset (not that you have a choice for the i7…), with Intel Controller Hub v10 RAID (ICH10R). I plan to use RAID 1+0 (Mirroring and Stripping) and the ICH10R will allow me just that. Also, it comes with EasyTune a software normally designed to over clock from Windows but I want to use it to read the current temperatures, voltages etc. directly from the board. It has Dual Bios so if flashing the production BIOS fails, you can still access the board. Great if you were stupid enough to flash a board during a storm…

 

image CPU Cooler: Scythe Kabuto

A top blower cooler, which should help cooling the components around the CPU. With a 120mm fan and a airflow of about 74 CFM (cubic feet per minute) it should operate silent but also keep the CPU cool.

 

imagePSU: Cooler Master Silent Pro M600

Very silent, very good efficiency in low to medium workloads and very good protection against surges, bursts etc. Its 600 watts should be enough since I don’t plane to build a SLI system (two or more graphic cards). If you want build a pure gaming PC with SLI, there are better PSUs for that.

 

image Memory: Patriot Viper Series DDR3 6GB (3 x 2GB) PC3-12800 Low Latency DIMM Kit (PVT36G1600LLK)

It is on the list of supported memory modules from Gigabyte and DDR3-1600 MHz speed will give me enough bandwidth when I try to overclock the CPU. And if overclocking fails: They look good too.

 

image Hard disks: Samsung EcoGreen F2 HD103SI (four times)

932 GB is more than I need, but it’s good to know that I never ever get the “HD full” message again. Beside this, this is a 5400 rpm (rounds per minute) drive and still has a performance of 105-121 MB/sec. This looked to me like the ideal compromise between silent operation and good performance. The switch between slower/silent and faster/louder will be explained in a different post.

 

image Case: Antec Twelve Hundred

This case has three 120 mm fan on the front, two 120 mm on the back and a 200 mm fan on the top. This should allow a very good cooling and (with good fans) a very silent operation. If you think I choose it because of the “cool” blue fans it has: No, since I will replace all (except one) of them.

Saturday, April 18, 2009

Xteq GetOSVersion 3.1 available

We have just updated Xteq GetOSVersion (XQGetOSVer) to Version 3.1, now supporting also Windows 7.

XQGetOSVer returns a number for each detected OS (Windows 95 up to Windows Server 2008 and Windows 7) and can therefore easily be used for batch files where you want to execute special commands depending on the OS in use. It is released as freeware, so you can use it right away.

Thursday, April 16, 2009

Removing Live Search from Internet Explorer 8

This week, we had to prepare an Internet Explorer 8 rollout at a customers side. This customer had very strict requirements which Accelerators, Links and Search providers should be installed.

We thought this should be no problem with the Internet Explorer Administration Kit (IEAK) so we created a package with it. We added the search providers, accelerators and links the customer wanted to have and imported them with IEAK to the package we wanted to created while also activating the option that no default items should be added.

Using VMWare Workstation we then tested our package (did I mentioned which great invention Snapshots are?) and everything looked quite good except that the search box beside the address bar still showed Live Search (not as default, but anyway) like this:

After several tests we are sure this wasn't a failure inside the package, but instead some "by design" issue. Tracking this down inside the registry we found that IE8 get's the list of Search providers from
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\SearchScopes.
However, it also checks
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\SearchScopes
and if it finds a search provider there that is not already shown, it will simply display it as well. And Live Search did come from this HKLM key.

We resolved this issue by NOT adding any search provider inside the package and executing two batch files after the installation of IE.

IESearchProvider_UserSet.bat will remove Live Search from the HKCU SearchScopes, add Google (from IESearchProvider_GoogleSearch_User.reg) and make this the default.

IESearchProvider_ComputerSet.bat will remove Live Search from the HKLM SearchScopes, add Google (from IESearchProvider_GoogleSearch_Computer.reg) and make this the default.

Both scripts work identically, except one check HKCU and the other HKLM. Both check if the Google search provider is already installed (we have created our own GUID for this) and if not it will be added, set as the default and finally deleting the Live search provider.

We have added these commands to the Internet Explorer GPO (..UserSet.bat to the user scripts, ...ComputerSet to the computer scripts). And don't worry: This script will work even if IE8 is not rolled out, IE7 can use the Google search provider as well.

You can download all files here.

Tuesday, April 7, 2009

A script for fixing WMI problems

The last two months, I was helping a client to get his network running smoothly again. One of the topics were strange errors within various applications and problems with machines that did not received any update from the central Windows Server Update Services.

To cut a long story short, this all was caused by the WMI (Windows Management Instrumentation) service not working correctly. One very often rolled out image was broken in that area so 70% of all computers had a broken WMI installation.

After some research, I created a WMI Fixer batch file that was able to fix the WMI installation of nearly all machines (>400), except three we were forced to reinstall.

I took the idea from a script of David H. Lipman from this forum post, added some checking logic and also added some code from the WMI Isn't Working page.

Enjoy!

 

@cls
echo off
Rem
Rem Original by David H. Lipman:
http://www.pcreview.co.uk/forums/thread-1898592.php
Rem See also: http://www.microsoft.com/technet/scriptcenter/topics/help/wmi.mspx
Rem

SET WMIRoot=%windir%\system32\wbem
SET Rep_Bad=Repository_bad

echo WMI Fixer Batch v1.2
echo Copyright (C) 2008 Xteq Systems
echo
http://www.xteq.com/
echo.

echo Setting TEMP as current directory
cd /d %TEMP%

if exist %WMIRoot% goto Stop_Services
echo WMI doesn't seem to be installed here! Starting WMICore.exe...
wmicore /s
echo Creating folder WBEM 
mkdir %WMIROOT%

:Stop_Services
echo Trying to stop service...
net stop winmgmt /y

echo Using kill switch to make sure WMI has stopped...
winmgmt /kill

echo Switching to %WMIRoot%
cd /d %WMIRoot%

echo Checking if folder %Rep_Bad% exists and delete it if necessary
if exist %Rep_Bad% rd %Rep_Bad% /s /q

echo Moving current Repository to %Rep_Bad%..
rename Repository %Rep_Bad%

echo Registering all DLL files...
echo on
@for %%i in (*.dll) do RegSvr32 -s %%i
@echo off

echo Registering all EXE files...
for %%i in (*.exe) do call :FixSrv %%i
REM for %%i in (*.mof,*.mfl) do Mofcomp %%i
Rem not used

net start winmgmt
echo Done!
goto Ende

:FixSrv
if /I (%1) == (mofcomp.exe) goto SkipSrv
if /I (%1) == (wmic.exe) goto SkipSrv
if /I (%1) == (wbemcntl.exe) goto SkipSrv
if /I (%1) == (wbemtest.exe) goto SkipSrv

echo on
%1 /RegServer
@echo off
:SkipSrv
goto LongTail

:Ende

pause
exit 0

:LongTail

Wednesday, March 4, 2009

Creating a self-signed certificate for SSL

In case you want to secure an internal web server with an SSL certificate you normally can get a certificate from your PKI Administrator.

However, if you only want to test something a self-signed certificate will also do the trick. The only drawback: Since it's self-signed, user will get a certificate warning when connecting to the server. For test environment however, this should be okay.

I'm using the MAKECERT.EXE command from Visual Studio for this. The command to create the cert is as follows:

"%ProgramFiles%\Microsoft Visual Studio 8\SDK\v2.0\Bin\makecert" -r -pe -n "CN=my-server.corp.acme.com" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12



@echo.

@echo Now start mmc.exe, add the snap-in "Certificates" and

@echo acceess the certificate store of the local computer.

@echo Below "My certificates" the newly create certifcate will be located!

@echo.



pause


Once this command has completed, open MMC.EXE, add the "Certificates" snap-in, select "Local computer" as the scope and the newly created certificate will be inside the "My certificates" folder.

Enjoy!

Thursday, February 26, 2009

Adobe Flash Player Update

Once again, there is a security hole in Adobe Flash and everyone should update to version 10.0.22.87 (open Flash Player Version Display in case you want to know the version of your Flash Player).

Home users can easily go to the Get Flash page from Adobe and update their player. No big deal.

However, in a company with more than 500 computers, users are normally not allowed to install any software and any ActiveX/XPI download is blocked. Means: All these users can't update their flash player; it must be installed by the IT.

Normally this isn't a big problem at all since the Flash player for Internet Explorer is just an OCX file that you can easily replace. Starting with version 10, Adobe patches the security ACL for this file and denies the user EVERYONE the access to write the attributes for the OCX. Before they do this, they set the attributes of the file to READ-ONLY.

Boink, you can't copy the new OCX file because it's marked READ-ONLY. ATTRIB –R does also not help, because the ACL on the file prevent you from doing this. To make a long story short: In order to update Adobe Flash manually you need to perform the following steps.

  • Get a new Flash OCX from Adobe. Easiest way possible is to use one machine that is directly connected to the internet and update Flash from the Get Flash Page page.
  • Copy the Flash OCX from C:\WINDOWS\system32\Macromed\Flash\Flash10b.ocx to a network share where all machines have access to.
  • Use the following batch file which will first delete the old Flash OCX, then patch the ACLs on the file, which will allow us to change the attributes using ATTRIB (remove READ-ONLY) which ultimately allows us to copy the OCX file.

SET FOLDER=%SYSTEMROOT%\system32\Macromed\Flash

SET OLDFILE1=%FOLDER%\Flash10a.ocx

SET NEWFILE=%~dp0flash10b.ocx
SET NEWFILE_DEST=%FOLDER%\Flash10b.ocx


IF NOT EXIST %FOLDER%. GOTO ENDE


IF EXIST %OLDFILE% DEL %OLDFILE1%

CACLS %NEWFILE_DEST% /E /R Everyone
CACLS %NEWFILE_DEST% /E /R Jeder
echo j|CACLS %NEWFILE_DEST% /E /G Users:F
echo y|CACLS %NEWFILE_DEST% /E /G Users:F
echo j|CACLS %NEWFILE_DEST% /E /G Benutzer:F
echo y|CACLS %NEWFILE_DEST% /E /G Benutzer:F

ATTRIB -R %NEWFILE_DEST%

COPY %NEWFILE% %NEWFILE_DEST% /Y /V

regsvr32.exe %NEWFILE_DEST% /S

:ende


Please note: This script will not install Flash, it will just update it. And it only updates Flash for Internet Explorer, not for Firefox or any other Browser. That every call to CACLS is duplicated is simply due to the fact that we also have German machines which expect "J" for JA instead of "Y" for YES.

Wednesday, February 4, 2009

.Net DateTime vs. TickCount compare operations

Yesterday, a friend of mine called me. He is writing a small program for a client and this program should execute simple operations at a given time. These operations don't take very long, but there will be a lot of checks in a second to make sure that the operation starts (nearly) exactly at the given time.

My friend has concerns that a simple "TriggerDate>DateTime.UtcNow" would take to long so he started to use Environment.Ticks. The Ticks operation is for sure faster, because this is only a simple addition and comparsion. However, the ticks will go from Int.MinValue to Int.MaxValue in about 49 days, when the counter will flip back to Int.MinValue. This caused him a lot of headache.

I first tried to improve his code, when I realized I first need to determine how much slower is a DateTime comparison. So I wrote the following small test code:

private void CheckDateTime()
{
DateTime dtStart = dtNow new TimeSpan(0, 0, 5);
long iCount = 0;

DateTime dtNow = DateTime.UtcNow;

for (; DateTime.UtcNow < dtStart; iCount )
{
}
PrintResult(dtNow, iCount);

}

private void CheckTicks()
{
int iTick = Environment.TickCount & int.MaxValue;
int iTickStart = iTick (5 * 1000);

long iCount = 0;

DateTime dtNow = DateTime.UtcNow;

for (; (Environment.TickCount & int.MaxValue) < iTickStart; iCount )
{
}
PrintResult(dtNow, iCount);

}

private void PrintResult(DateTime starttime, long Operations)
{
DateTime dtNewNow = DateTime.UtcNow;

TimeSpan elapsed = starttime - dtNewNow;

textBox1.Text = "Time: " elapsed.TotalSeconds.ToString() "\r\n";
textBox1.Text = "Operations: " Operations.ToString() "\r\n";

}


The result: On a standard 1.8 GHz Intel Core 2 machine (E2160), I had 192 million DateTime comparisons in about 5 seconds and 593 million TickCount comparisons. This means: My computer is able to do a whopping 39 millions DateTime comparisons/second and 120 million TickCount comparisons/second.

Conclusion: Yes, DateTime is slower than checking Ticks, but given these figures you really don't need to care about this difference.

Monday, February 2, 2009

Calculating when an integer identity column will be exhausted

Last week, we had an interesting discussion with a client which data type an identity column on a table should have. We are working with this client on a redesign of an in-house LOB.

In particular, we were discussing one table that we expecting to have one to two new rows per second each day. The customer wanted to define the identity as bigint, while we said that integer (int) is enough and faster for sure. What would you think how long it takes until an integer column as identity will "explode" on this table? Two Month? Three Years?


Well, if we calculate with three changes per second it would actually take 23 years!


In case you find this Excel file useful, you can download it here.

Friday, January 30, 2009

IF EXIST for directories

Sometimes you simply need to use batch files, although they are something from the past. In a current project, a custom made service wanted to copy a given file using a batch file. This didn't worked on all machines, because the customer has started to roll out MUI installations where the userprofile folder differs:

Default Windows XP (German) profile folder: C:\Dokumente und Einstellungen\
Default Windows XP (MUI) profile folder: C:\Document and Settings\

The solution (seems) rather simple:

IF EXIST "%SYSTEMDRIVE%\Dokumente und Einstellungen" GOTO DEUTSCH

Well, this doesn't work because IF EXIST can only check for files, but not for folders. The trick is to append "\." at the end because every folder contains this "virtual file". Therefore, the batch would look like this:

IF EXIST "%SYSTEMDRIVE%\Dokumente und Einstellungen\." GOTO DEUTSCH

GOTO ENGLISH





:DEUTSCH

echo German XP

goto ende



:ENGLISH

echo English or MUI XP

goto ende



:ende

pause

Wednesday, January 21, 2009

DHCP Error: Service provider could not loaded or initialized

I just had to fix a Windows XP machine that displayed the following error message in event log:

Event Type: Warning
Event Source: Dhcp
Event Category: None
Event ID: 1006
Description:
Your computer was unable to automatically configure the IP parameters for the Network Card with the network address XXXXXXX. The following error occurred during configuration: The requested service provider could not be loaded or initialized.

The computer did not receive any DHCP address and instead always used a automatically assigned one (169.x.x.x). Trying ipconfig /renew also resulted in the exact same message:

An error occurred while renewing interface Local Area Connection. The requested service provider could not loaded or initialized.

This has happened after the removal of an UMTS (3G) Network card. The solution is rather simple: Just enter

netsh winsock reset catalog (More information)

inside a command prompt After that command, the computer was back to normal.

Monday, January 12, 2009

Amazon A9 gone mad

Normally Amazon finds what I'm looking for. But searching for a "Fritz! Box", a router with WLAN, VoIP options etc. in Black (schwarz in German) resulted in these three results.

The first result one is okay, result two is not really what I was searching for but the last result is really insane: Swimmies!

Tuesday, January 6, 2009

Please replace the non-existent hard drive

I just love HP ProLiant Servers. I think I have set up nearly 100 of those in my carrier, and exactly one really failed every (main board broken). You get great support and even new drivers for servers that are out of production for three years.

However, the following message I received yesterday was just so funny:



BTW: Yes I know the message comes from the fact that the drive I added had still some array information on it. But it's funny anyway.

Monday, December 22, 2008

RPO and RTO

As soon as you start to deal with backup strategies, you will come across two abbreviations you need to deal with: RTO and RPO.

Recovery Time Objective (RTO) simply means the time in minutes until a crashed system is up and running again. For example, if your backup server is able to restore your entire file server within 60 minutes, you have a RTO of 60.

However, this does not say anything about if the data you have restored were from one hour ago, yesterday or from last year. This is defined by the Recovery Point Objective (RPO).

A quick example: You save your file server every night at 20:00 (8pm). One day, all data on this server is lost at 11:00 (11am). You then do the restore and everything is up and running again at 13:00 (1pm).

In this example, you had an Recovery Time Objective (RTO) of 120 minutes (11:00 - 13:00). The Recovery Point Objective (RPO) was however 15 hours (20:00 - 11:00).

Dealing with these values can be quite challenging, but sometimes the biggest problem is not to confuse RTO with RPO.

I simply remember RTO as "Ready to gO" (after a crash) so RPO means how old the backup can be.

Friday, December 19, 2008

Fixing the local Live Mesh client

In case you are also playing with Live Mesh from Microsoft, you might end up that the synchronization between your local Live Mesh client and the server goes havoc.

In my case, I didn't had any folders in my mesh but my local client still showed several folders as being available inside the mesh. Trying to delete them from the "Live Mesh Folders" resulted in this nice error message:

Request to MOE failed with status code
404 Resource not found

If this happens to you, simply should down the Live Mesh client, then search the your computer where MOE.exe is located. On my Vista box, it was C:\Users\TeX HeX\AppData\Local\Microsoft\Live Mesh\GacBase\.

Inside that folder, you will find a folder called Store. Simply delete it and start the client again. Although it will have forgotten all settings, the "Zombie" folders are gone as well.

BTW: In case the client does not accept a folder inside the "Synchronize folder with this computer" (Error 400): Check if the folder is not on a removable medium (USB Stick, SD Card). Live mesh seems to accept hard drives only at this time.

Tuesday, November 18, 2008

Fable 2 bug collection

Don't get me wrong: Fable II is a great game and I enjoyed playing it. However, sometimes the engine just fails badly. But it funny anyhow....

Grilled chicken


Flying dead body


Dog wayfinding (sort of)


Fancy lady twins

10.000G - Finally

After playing for three years, I was finally able to pass 10K of "G" points on XBOX Live. Yeah!

Tuesday, November 11, 2008

SSIS XML Destination

Today, I needed to create a transmogrification that reads from a SQL Server table and creates a XML file.

The destination format included 98% mandatory fields and only two percent of data from the table. Easy: Read the data from SQL Server into a very simple XML file and then use a XSLT style sheet to transform it into the destination XML format.

First problem: SSIS does not have a XML destination. Fortunately, I found the following code that you can use inside a destination script component (Create a new data flow, drop a script component on it, select “Destination” as type and then copy and paste this code into the component, overwriting any existing code).


Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports System.IO
Imports System.Reflection

Public Class ScriptMain
Inherits UserComponent

Private rootElement As String = "Root"
Private rowElement As String = "Row"

Private targetFile As String
Private xmlWriter As StreamWriter
Private columns As Integer()
Private columnames As String()

Public Overrides Sub AcquireConnections(ByVal Transaction As Object)
targetFile = CType(Me.Connections.Destination.AcquireConnection(Nothing), String)
End Sub

Public Overrides Sub PreExecute()
xmlWriter = New StreamWriter(targetFile, False)
xmlWriter.WriteLine(FormatElement(rootElement))

Dim input As IDTSInput90 = ComponentMetaData.InputCollection(0)

ReDim columns(input.InputColumnCollection.Count)
columns = Me.GetColumnIndexes(input.ID)

Dim column As IDTSInputColumn90
ReDim columnames(input.InputColumnCollection.Count)

Dim counter As Integer
counter = 0

For Each column In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
columnames(counter) = column.Name
counter = counter 1
Next

End Sub

Public Overrides Sub PostExecute()
xmlWriter.WriteLine(FormatElement(rootElement, True))
xmlWriter.Close()
End Sub

Public Overrides Sub ProcessInput(ByVal InputID As Integer, ByVal Buffer As Microsoft.SqlServer.Dts.Pipeline.PipelineBuffer)

While Buffer.NextRow()
xmlWriter.Write(FormatElement(rowElement))

Dim counter As Integer
counter = 0

For Each index As Integer In columns
Dim value As Object = Buffer(index)
xmlWriter.Write(FormatElement(columnames(counter).ToString()) value.ToString() FormatElement(columnames(counter).ToString(), True))
counter = counter 1
Next

xmlWriter.WriteLine(FormatElement(rowElement, True))
End While
End Sub

Private Function FormatElement(ByVal elementName As String) As String
Return FormatElement(elementName, False)
End Function

Private Function FormatElement(ByVal elementName As String, ByVal closingTag As Boolean) As String
Dim returnValue As String

If closingTag Then
returnValue = "</"
Else
returnValue = "<"
End If

returnValue = elementName ">"
Return returnValue
End Function

End Class


Please note: I ripped this code from somewhere on the internet but I was not able to find out the original author.


Using this code, you will get a very simple XML file that you can transmogrify using XSLT. Because this should happen within SSIS, the best way to use a command-line XSLT processor and the best one I was able to find was nsxlt2.

Just drop an “Execute process” component to launch nsxlt2 and configure the arguments like this:

\\srv\test\Source.xml \\srv\test\SimpleXML2Destination.xslt -o \\srv\\test\DestFormat.xml

And you are done.

Wednesday, November 5, 2008

For more information: Go 404

Update found, for more details go to "File not Found". Great Symantec!

Sunday, November 2, 2008

No Flatrate + Boy + XBOX = Lots of trouble

Got a call from a friend of mine. He was complaining that he must have a Trojan horse on his computer since his ISP told him he had downloaded more than 4 GB of data (he only has a 500MB/month rate).

After checking his computer for some time and didn't find anything, I suddenly heard a sound I knew: It was Castle Crashers on XBOX.

So I got to the room of his boy, saw a XBOX 360 and opened the downloads:

So much for my "You must have a unknown virus" theory...

Wednesday, October 22, 2008

Eee PC 901 SSD and SD card performance/benchmark

Because I take my Eee PC 901 always with me, I'm pretty sure it will be broken in less than two years. The last Subnotebook I had had was broken because it fell down a stairway. That's when I decided I will never carry a 1k € notebook with me anymore, and use a Netbook in the future.

Knowing that, I wanted to store my user profile on a disk that I can easily detach from the EEE when it's broken. The C:\ SSD is build-in so no chance to detach is. Only solution left: Either the D:\ drive (the 12 GB SSD) or a Secure Digital card. Because I have a lot of different SD cards around here, I have done some performance test with CrystalDiskMark. The list below shows the results, sorted by Random Write 4 KB (bigger values are better).



I now have my user profile on a Kingston Ultimate 133x disk and so far everything works fine.

Tuesday, October 14, 2008

ImageCodr.org Update

I just made some changes on ImageCodr.org.

Some bug fixing: We had a typo inside the footer which is now corrected. Also, the example picture we were using is no longer licensed under a CC license, so clicking on the example link resulted in an error. We are now using a new photo which is also just looking great.

Finally, some people wanted to have a tooltip when hovering over the image or the CC license button (currently we only fill the ALT tag for screen readers). ImageCodr does now also fill the TITLE attribute which will cause Firefox and other browsers to display a tooltip as well.

No idea what ImageCodr does? See this example!

Wednesday, October 8, 2008

MySQL Administrator Backup Error 2003 (10061)

I just tried to use MySQL Administrator to make a scheduled backup. As instructed, I created a backup project and saved the connection info.

Using the GUI the Backup worked, but executing the command line (that is run with Scheduled Tasks) didn’t work. It simply log the following to the event log:

Can't connect to MySQL server on 'localhost' (10061) (Error 2003).

I looked at the command it generates and couldn’t find an error:

"C:\Program Files\MySQL\MySQL Tools for 5.0\MySQLAdministrator.exe" "-UDC:\Documents and Settings\Administrator.ACME\Application Data\MySQL\" "-cROOT-LOCAL" "-bpFullBackup" "-btD:\MySQL5\backup\" "-bxFullBackup"

Until I realized that the extra “-“ inside my saved connection “ROOT-LOCAL” might confuse MySQL Administrator. I renamed this connection info to "ROOTLOCAL" and change the parameter in the command line: Bingo, everything is working.

Great, even today argument parsers are causing trouble…

Thursday, September 25, 2008

Wednesday, September 17, 2008

Windows Search Server (SharePoint): An unexpected error has occurred.

I have a sort of a „Love/Hate“ relationship with SharePoint. I like the product because I think it offers a lot you can do with it, but I hate it when it comes to troubleshooting.

This time, I have setup Windows Search Server 2008 and it works just perfectly on our site. I then gave the URL to somebody else from a different site and he only got An unexpected error has occurred. Great, here we go again.

The first thing is to turn on real error messages, not this stupid “Something went wrong, but I won’t tell you”.

To do so, open the web.config file for your site. For a default installation, this file will be located at C:\Inetpub\wwwroot\wss\VirtualDirectories\80. Open it in Notepad and search for customErrors mode="On". Replace it with customErrors mode="Off". To get more details, we will also turn on the call stack (in which procedure the error is actually happening). Search for CallStack=”false” and change it to CallStack="true" (this is in the SafeMode section).

Once we have done this, we were getting (somewhat) more detailed error messages:

Object reference not set to an instance of an object.

[NullReferenceException: Object reference not set to an instance of an object.] Microsoft.Office.Server.Search.WebControls.CoreResultsWebPart.OnLoad(EventArgs e) +94 System.Web.UI.Control.LoadRecursive() +65

On another machine we were getting this error:

Object reference not set to an instance of an object.

[NullReferenceException: Object reference not set to an instance of an object.] Microsoft.Office.Server.Administration.SqlSessionStateResolver.System.Web.IPartitionResolver.ResolvePartition(Object key) +77

The server was also now logs a lot of ASP.NET errors 1309 into the Application event log. Somehow I cam across a post from Chinmay Vartak showing the same error message (but for a different problem) and the steps he pointed out were the solution.

The problem was that on the remote site the name of the server was resolvable, but pointed to a wrong IP address. Although we were using a FQN (http://servername.site.acme.com instead of just http://servername) to access the server, internally WSS was not using the FQN but just the server name. So, all you need to do is to tell SharePoint to always use the FQN.

To do this, go to the Central Administration of the server and select Operations -> Alternate access mappings

Click on Edit Public URLs and change the entry for Default to be a FQN and click on Save.

In case you want to use SSL (https) also, you will need to create an entry for this also by using Add internal URLs and enter the https FQN URL for this server. When you have done this also, Alternate access mappings should show a list similar to this one:

Now all this stupid errors should be gone and everyone can access your server with either http or https.

Enjoy!

Friday, September 12, 2008

SideBySide Event Log Error

Just came across a computer that was going havoc and displayed this funny error message in the system event log (Rough translation of the original version in German):

Dependend assembly "Microsoft.VC80.MFC” could not be found. “Last Error”: The references Assembly is not installed on this computer.

After search a little bit around, I finally found out that VC80 stand for Visual C++ 2005 (internally 8.0). And because Microsoft installs all newer Visual C++ runtime files as side by side assemblies into C:\WINDOWS\WinSXS, you don’t get the normal “DLL not found” but this message.

Well, the solution is easy: Just download and install the Visual C++ 2005 Redistributable Package from here

http://www.microsoft.com/downloads/details.aspx?familyid=200B2FD9-AE1A-4A14-984D-389C36F85647&displaylang=en

Please note that there is also a new package available (Visual C++ 2008 Redistributable Package) but this will install the files for Microsoft.VC90. Also note that you need to download and install the version that matches your computer. If you are using a 64bit Version of Windows, you will need to download the x64 version, not the x86 one I linked above.

And for your reference:
Visual C++ 2003 = Version 7.0
Visual C++ 2005 = Version 8.0
Visual C++ 2008 = Version 9.0

Thursday, September 4, 2008

Mozilla Firefox in "Jelly mode"

In case your are using a Netbook with an Solid-state drive (SSD), like the Asus EeePC 901, you will notice that Firefox 3 from time to time behaves like being in "jelly mode": it stops responding for a few seconds and simply freezes. Although this "jelly mode" will only last a few seconds, it will drive you mad if you try to use it for more than five minutes. Fortunately this can be fixed with some easy tricks and less than 10 minutes of time.

We got reports about this issue from several users of X-Setup Pro and they all asked us if there is a way to make Firefox faster and get rid of this jelly mode. Since we couldn't explain why this would happen, and we wanted to test X-Setup Pro on a netbook anyway, we bought a EeePC 901. After doing the typical "original setup, driver download and install, Windows Update check" procedure we installed Firefox 3.01 and within the first five minutes we were experiencing the jelly mode as well.

With the help of Process Monitor, DriveGLEAM, Wikipedia and mozillaZine we are pretty sure what this is causing. While using Firefox, it will perform a lot of small write operations to several SQlite databases (e.g. urlclassifier2.sqlite or places.sqlite) and other files like configuration files of add-ons or files for the cache. While this is fine with a normal HD, this causes a lot of stress for an SSD. SSDs are fast when reading data but very slow when writing. Although Firefox will only perform small write operations the SSD is not fast enough to perform this in time and causing Firefox to wait. And this is exactly what we are calling the "Firefox jelly mode".

The solution is quite simple: Move the Firefox profile (where all these write operations take place) to a location that is faster. But: The EeePC 901 only has two SSDs (C: and D:) plus an SD slot, meaning that there is no fast location available. This means, the only solution that is left is a RAM disk. The people at My Digital Life have written about this some weeks ago and made a package we can use right away.

Download the package and extract it to a folder on your HD (SSD), e.g. C:\ProgramFiles\RamDisk. From there, start RAMDISK.exe and click on the right on Install Ramdisk.

After a few seconds, the controls on the left will be selectable and we can choose which size this RAM disk should have. Since the 901 I'm using has 2 GB of memory, I selected 128M (128 MB) for size, if you netbook as only 1 GB, you might want to use 64 MB. All other settings (Drive: R:, Fixed Media) remain unchanged. Click OK and the program should report Success.

The next thing we need to do is to prepare the RAM disk, since it is currently set to use FAT instead of NTFS. Create a new Batch file in the same folder where RAMDISK.exe is located and name it Setup.bat. This batch will create some folders and save the image (with the folders) to the registry. Since we are using a RAM disk, rebooting the computer will wipe the entire contents of the R: drive. With the batch, we are creating an image of the drive and store it to the registry. When the computer is booted, the RAM disk is re-created from this image automatically.

@echo off

echo This will setup the RAM Disk
pause

format /FS:NTFS /Q /V:RamDisk /A:512 R:
chkdsk /L:2048 R:
CACLS R:\ /G Administrators:F

MKDIR R:\TEMP
MKDIR R:\FFCache
MKDIR R:\IECache
MKDIR R:\Stuff

rdutil R: registry

pause

Execute the batch. Press return to get things rolling, then enter RamDisk to confirm you want to format the R: drive, confirm the format again (Y) and once again (Y). If you now open Explorer, you should have an R: drive with several folder in it. Please note: If you ever change your mind about the size of the RAM disk and change it using RAMDisk.exe you need to execute this batch again!

Next, we need to create a profile in Firefox that will be stored on the RAM disk. Using Explorer, open R:, change to the folder Stuff and create a new folder named RamDiskProfile. Now open a command prompt (Start - Run - cmd.exe) and change to the path where Firefox is installed, e.g. cd "c:\program files\Mozilla Firefox". Execute firefox.exe -ProfileManager. Click on New profile and enter as name RamDiskProfile. As folder, select R:\Stuff\RamDiskProfile. Back in the profile selection, click Start Firefox.

If everything works as expected, you should see the Welcome to Firefox page. Notice: Do not, repeat, DO NOT copy your existing profile! At least on my 901, several files inside the profile had direct likes in it (e.g. C:\Documents and Settings\TeX HeX\...). If you simply copy your existing profile you will end up having some of the files will be written on the SSD again.

What we now need to do is to change the location where this Firefox profile will put the cache files to. In the address bar, type about:config and confirm the warning that appears. Right-click anywhere in the list and select New -> String. As name of the new value type browser.cache.disk.parent_directory. As value for it, type R:\FFCache. Close Firefox.

Now we will create a backup of this profile to the SSD. Use Start -> Run again and type %APPDATA%, which will display the folder where your personal data is normally saved. Open the folder Mozilla, then Firefox and then Profiles. Copy the folder R:\Stuff\RamDiskProfile there.

Okay, we are almost there. Create a new batch file that is used to start Firefox with the profile from the RAM disk. It will copy the files from the RamDiskProfile (from %APPDATA%) to the R: drive, wait for Firefox to exit (= you are done with browsing) and copy then any files that were changed back to %APPDATA%.

@echo off
echo.
echo Launching Firefox from RAM disk...
echo.

IF NOT EXIST R:\Stuff\RamDiskProfile\. mkdir R:\Stuff\RamDiskProfile

REM The xcopy command is one line until the "cd" command
xcopy "%APPDATA%\Mozilla\Firefox\Profiles\RamDiskProfile\*.*" "R:\Stuff\RamDiskProfile" /S /I /Y /H /Q
cd /D "R:\Stuff\RamDiskProfile"
attrib -a *.* /S

echo.
echo Firefox launched, this window will close when Firefox is closed
start /wait "Firefox from RAM disk" "%ProgramFiles%\Mozilla Firefox\firefox.exe" -profile R:\Stuff\RamDiskProfile

echo.
echo Copying files back from RAM disk...
REM The xcopy command is one line
xcopy "R:\Stuff\RamDiskProfile\*.*" "%APPDATA%\Mozilla\Firefox\Profiles\RamDiskProfile" /S /I /Y /H /Q /M

Now you also know why we have changed the location of the cache files earlier on: Because the cache files are now longer part of the profile (but instead on R:\FFCache), they don't need to be copied back. Of course, if you want to have your cache persistent, you can easily delete the browser.cache.disk.parent_directory from about:config and the cache files will be copied as well.

Start the batch file and give it a try, I'm pretty sure you will think you have just got a new computer. No more jelly mode, and the speed is what you were expecting from Firefox.

To verify that everything has worked, type about:cache into the address bar and look at the two cache directories, both should be pointing to R. One thing you need to keep in mind: In case you install an add-in or a theme, Firefox is offering to restart it with a single click. Don't do this since the batch will close when Firefox exists. Simply close it manually and restart it again using the batch.

Some other things you can do with the RAM disk: There is already a folder called TEMP so you can simply reconfigure your environment variables TEMP and TMP to use this folder. And finally, the folder IECache can be used to put the temporary internet files there.

Enjoy!

Monday, August 25, 2008

Automatically generating PowerShell *.Types.ps1xml and *.Format.ps1xml

I helped a friend of mine a lot with this, so I thought I should share this. He currently works at a customer's site to create a PowerShell snap-in for administrating the customer its home-grown LOB. It's quite an application, used by 5000+ users and supported by about 20 administrators.

So far, the administrators are freaking out because administration this LOB is a snap with the cmdlets he has written. As more and more administrators use the PowerShell to administrate the LOB, more features requests are coming in and a lot of them are about how the objects are displayed inside PowerShell (see http://msdn.microsoft.com/en-us/library/cc136149(VS.85).aspx for more details).

The PowerShell needs two files to format the returned objects proberly: [NAME]. Types.ps1xml (general information) and [NAME].Format.ps1xml (table based output). These are very simple structured XML files but keeping these files manually in sync with your development and the feature requests can be a pain.

Because it was my idea that my friend should design a PowerShell snap-in instead of the originally planned COM interfaces, I searched for a solution. Since I found none, I wrote it myself (surprise!).

The good: The solution works as expected and my friend is happy. The bad: The code has no unit testing, works by using string constants and string.Format() and has some limitations (e.g. only a single Alias per property while the PS could support 100+ alias for the same property). However, you can use the code a starting point for your own solution.

My solution is based around the custom attributes [xPSObjectAttribute], [xPSPropertyAttribute] and [xPSSortPropertyAttribute]. During development, you simply decorate an object that is returned by a cmdlets with [xPSObject]. Oh, BTW: the xPS simple stands for "PowerShell Extension".

Within the object you then decorate a property with the [xPSProperty] attribute and define several properties on it. For example:

[xPSProperty(Default = true, Alias = "FullName")]

public string Name

When you later on run the PSTypeXMLFormatXMLGenerator:

xPSXMLOutput output = PSTypeXMLFormatXMLGenerator.GetPS1XML(typeof(TestClass));

You will get a type XML (some parts have been omitted):

<Type>

<Name>TestApp1.TestClass</Name>

<Members>

<MemberSet>

<Name>PsStandardMembers</Name>

<Members>

<NoteProperty>

<Name>DefaultDisplayProperty</Name>

<Value>FullName</Value>

</NoteProperty>

<PropertySet>

<Name>DefaultDisplayPropertySet</Name>

<ReferencedProperties>

<Name>FullName</Name>

...

<AliasProperty>

<Name>FullName</Name>

<ReferencedMemberName>Name</ReferencedMemberName>

</AliasProperty>

You can also change in which sequence the properties should be listed by PowerShell:

[xPSProperty(Default = true, Sequence = 10, Alias = "FullName")]

public string Name

[xPSProperty(Sequence = 20)]

public int Size

The result XML:

...
<Name>DefaultDisplayPropertySet</Name>

<ReferencedProperties>

<Name>FullName</Name>

<Name>Size</Name>
...

To provide on which properties the PowerShell should sort a list of this object, use the [xPSSortProperty] attribute (can be applied to several properties):

[xPSSortProperty(SortID = 1)]

public string Name

[xPSSortProperty(SortID = 20)]

public int Size

XML:

<Name>DefaultKeyPropertySet</Name>

<ReferencedProperties>

<Name>Name</Name>

<Name>Size</Name>

</ReferencedProperties>

For the table based output, PSTypeXMLFormatXMLGenerator does also generate a format XML.

[xPSProperty(Default = true, Sequence = 1, Alias = "FullName", ColumnWidth = 30)]

public string Name

[xPSProperty(Sequence = 2, ColumnName = "Size (K)", ColumnRightAligned = true, ColumnScript = "[int]($_.Size / 1024)")]

public int Size

Resulting XML:

<View>

<Name>TestClass</Name>

<ViewSelectedBy>

<TypeName>TestApp1.TestClass</TypeName>

</ViewSelectedBy>

<TableControl>

<TableHeaders>

<TableColumnHeader>

<Label>FullName</Label>

<Width>30</Width>

</TableColumnHeader>

<TableColumnHeader>

<Label>Size (K)</Label>

<Alignment>Right</Alignment>

</TableColumnHeader>

...

<TableRowEntry>

<TableColumnItem>

<PropertyName>Name</PropertyName>

</TableColumnItem>

<TableColumnItem>

<ScriptBlock>[int]($_.Size / 1024)</ScriptBlock>

</TableColumnItem>

...

I guess you are getting the basic idea how this class works. For your reference, here's a screen shot what the [xPSProperty] Attribute supports:




Once again, this class is not fully tested and should be seen as a basis for your own solution. If you use it, you would make me happy to leave a comment or provide a back link. Download the source and a sample application here.

Enjoy!

Friday, August 22, 2008

SQL Server string filter and replacement function

Often when I need to transmogrify data in SQL Server, I create custom stored procedures or update statement that filters incoming data. For example, a raw data import includes part numbers with letters while the system where this should go only allows 0-9 and “_”.

For a current project, I had to filter a lot of data so I decided to write a reusable function that NOT defines what is NOT allowed but simple the other way around: Define what you want.

I came across a interesting forum discussion that about such an function, but none of the solutions was exactly was I wanted. The main reason was that I wanted the function to be used as a filter and replacement at the same time. I give you a quick example.

Suppose you need a replacement that allows numbers only:

Input is “a12345abc”, replacement character is “*”, return should be “*12345*”. Please note that a single replacement character (“*”) is at the end, although the string ends with three non-numeric characters.

Now the same as a filter: Input is “a12345abc”, replacement character is “” (empty) , return should be “12345”.

I ended up by creating my own function “funcFilterString_ASCII” (roughly based on a solution in the forum by Peter Larsson from Helsingborg, Sweden). Usage is rather simple: @Source is the string that should be filtered, @Filter is the regex like filter and @Replacement is the character any no match should be replaced with (or empty if no matches should be removed).

Some examples:

print dbo.funcFilterString_ASCII('John Doe - 12345 New York _10', '[0-9]', '')
-- returns 1234510

print dbo.funcFilterString_ASCII('John Doe - 12345 New York _10', '[0-9]', '*')

-- returns *12345*10

print dbo.funcFilterString_ASCII('John Doe - 12345 New York _10', '[0-9_]', '')
-- returns 12345_10

print dbo.funcFilterString_ASCII('John Doe - 12345 New York _10', '[23]', '*')
-- returns *23*

print dbo.funcFilterString_ASCII('John Doe - 12345 New York _10', '[^0-9]', '*')
-- returns John Doe - * New York _*

To use it, simply copy the source below to a query window, change to the database where you want to have it and execute the SQL. Enjoy!



Here is the source:


CREATE FUNCTION [dbo].[funcFilterString_ASCII]
(
@Source VARCHAR(max), -- the string that contains characters to be replaced
@Filter VARCHAR(max), -- the regex what should be filterd
@Replacement VARCHAR(1) -- replace anything that does not match @Filter with this char (set to '' to remove non-matches)
)
/*
Example

declare @s varchar(500)
print '--Test string ---'
select @s='John Doe - 12345 New York - YYY_XXX - No 10 USD$' CHAR(13) CHAR(10) 'New Line'
print @s
print '--Results---'
print dbo.funcFilterString_ASCII(@s, '[0-9]', '') -- returns only 12345
print dbo.funcFilterString_ASCII(@s, '[0-9]', '*') -- returns *12345*
print dbo.funcFilterString_ASCII(@s, '[0-9_]', '') -- returns only numbers and "_" = 12345_10
print dbo.funcFilterString_ASCII(@s, '[0-9a-zA-z]', '') -- returns the entire string but without any special chars
print dbo.funcFilterString_ASCII(@s, '[0-9a-zA-z]', '*') -- returns the entire string but any special chars have been replaced
print dbo.funcFilterString_ASCII(@s, '[^' CHAR(13) CHAR(10) ']', '_') -- replace CR/LF with _
print dbo.funcFilterString_ASCII(@s, '[^' CHAR(13) CHAR(10) ']', '') -- remove CR/LF
print dbo.funcFilterString_ASCII(@s, '[e]', '*') -- returns only *e*e*e*e
print dbo.funcFilterString_ASCII(@s, '[^e]', '*') -- entire string, but all "e" are "*"

*/

RETURNS VARCHAR(max)
AS
BEGIN
-- Created by TeX HeX of Xteq System
-- http://www.texhex.info/

DECLARE @Index int
SET @Index = DATALENGTH(@Source)

DECLARE @dest varchar(max)
DECLARE @curr varchar(1)
DECLARE @last_add varchar(1)

SET @DEST=''
SET @last_add=''

-- Pass #1: Replacement
WHILE @Index > 0 BEGIN
SET @curr=SUBSTRING(@Source, @Index, 1)

-- collate is only needed for VARCHAR types
IF @curr COLLATE Latin1_General_BIN LIKE @Filter BEGIN
-- no replacement, copy from source
SET @DEST=@DEST @curr

SET @last_add=@curr
--SET @last_add_ignored=0
END ELSE BEGIN
-- do replacement. If @Replacement is empty, do not add anything
IF @Replacement!='' BEGIN
-- check if the last char we added was @Replacement
-- if so, do not add it again
IF @last_add!=@Replacement BEGIN
SET @DEST=@DEST @Replacement

SET @last_add=@Replacement
END
END
END

SET @Index=@Index-1
END

-- Pass #2: Reverse the string, because we build @Dest from reverse
SET @DEST=Reverse(@Dest)

-- Pass #3: Remove any left over spaces
SET @DEST=RTRIM(LTRIM(@Dest))


RETURN @DEST
END

Friday, August 15, 2008

Thanks for the eh, "detailed" description

The 100.000$ question: What does this error message mean?

A) Nothing!

B) Go figure!

C) Enterprise NX-01 hull breach!

D) Maybe something went wrong, but I won't tell you!


Thursday, August 7, 2008

Improving the SGH-i780

After nearly three years with a Palm Treo 650, I decided to buy a new mobile Email machine. Because I now have a full Exchange account, I needed to get a Windows Mobile Device this time.

Evaluating several devices (HTC S730, Motorola Q9, Palm Treo 750) I thought the phone that best suits me would be the Samsung SGH-i780. Especially because it has no D-Pad, but instead a touch pad that is easy to use and makes handling a snap.

However, as soon as you want to scroll down a longer email, or viewing a normal website there is one thing were the touch pad sucks: Scrolling. Because of the mouse-like handling you always have to move the cursor to the scrollbars and click on it. This is just plain time consuming. After a short while you will miss a simple D-Pad desperately.

Good: The SGH-i780 has a two buttons on the left side (Volume Up and Down) and another button on the right side (Short press: Mini Media Player, Long press: Camera) that could be used to simulate Up/Down and Enter. Bad: You can't reconfigure these buttons with the normal settings Samsung offers.

... until you get AE Button Plus from Alexander Eltsyn which allows you to reconfigure any (yes, really any) key your device has. You can even double and triple (!) assign any key.

With this software for just 8$ I simply reconfigured the three button to be up, down and Enter (Long press on the Camera key is still the camera) and now I can work on my emails without using the touch pad.

Monday, July 28, 2008

HTML code for Flickr images – made easy

Flickr currently hosts more than 75 million images that are licensed under a Creative Commons license, and a lot of them can be used even on commercial pages (depending on the exact Creative Commons license).

If you want to freshen up your homepage and want to link to some images from Flickr, you need to take some steps. You need to find out the correct URL of the photo and it must be linked back to the photo page; you must give the author proper credits and link back to the authors profile page; show that the photo is licensed under a Creative Commons license and finally include describing text on the image for people using screen readers.

After doing this several times, I got tired of it and created a small website that automates this process: ImageCodr.org. You simply pass it the URL (as seen in your browser) of the photo page and it will generate ready to use HTML code. Here is an example of the result.

A small link that you can drop on your browser’s toolbar is also available on the Get code! page, so you can simply click this when viewing an interesting photo.

Enjoy!

Tuesday, July 8, 2008

GTA IV: Stupid AI driver

Yes, the AI in GTA IV is sometimes far from perfect...


Wednesday, June 18, 2008

Digital Photo Display Feed

Surfing the Internet while searching for picture for my digital photo display, I came across two brilliant artists I would like to share with you.

First is Tom Wilcox at deviant ART which makes stunning 3D pictures, a little bit like Ryan Bliss from Digital Blasphemy. If you have a look at the works of art Tom designs, you will easily notice that you can look at them for hours and still notice new details you didn't saw until then. Just brilliant!

Second is Hamad Darwish, a photographer that makes simply beautiful landscape photographs, the ones you stare at and won't believe this is still planet earth. Two pictures of him are even included as Wallpaper within Windows Vista, but the entire set contains much more pictures. More pictures can be found at his Gallery.

Monday, June 2, 2008

Army Of Two: Game bug

And yet again I'm hit by a invisible wall...


Sunday, June 1, 2008

Asterisk Dialer

Once you have an Asterisk based VoIP PBX (for example TrixBox) running for more than one hour, you will have a great need for a possibility to dial directly from Office Outlook. You might also know this as TAPI for Asterisk.

I have tested several options and programs that allow you to do this, and the best I found so far is the Asterisk Outlook Dialer (Freeware!).

It contains of a small PHP file you install on the Asterisk server and a local extension that integrates into Office Outlook (tested successfully with Office Outlook 2007). Entering a number into the box and hitting Dial will call the PHP file which in turns informs Asterisk to call your phone and connect you.

You only need to change the PHP file (originate.php) to include a context, username and password that can perform the actions on Asterisk. For example:

$sContext = "from-internal";
$UserName="AstTapi";

$Password = "D1QdC1xbkJ";

Once you have installed the extension, you need to configure it directly in Outlook using Tools -> Options -> Asterisk Dialer

The only glitch I have found was that non numeric chars inside the number (e.g. “+49..”) will cause the call to fail. Therefore you should patch the PHP file a little bit more.

Replace the part where you need to enter the context, username and password with the following:

//Number patching
$sNumber = preg_replace("/[^\+0-9]/", "", $sNumber);
$sNumber = str_replace("+49", "00", $sNumber);
$sNumber = str_replace("+", "000", $sNumber);
//User information
$sContext = "from-internal";
$UserName="AstTapi";
$Password = "D1QdC1xbkJ";

This line will strip out any chars that are not either numbers or the “+” sign. That way a number like “+49 (6232) 3987-x312” will become “+4962323987312”.

The next two lines will change the number as required by the backend PBX. A call from Germany to Germany needs to be initiated with “00”, a call to any other country needs to be initiated with “000”. You might need to change these two lines to meet your requirements.

In case you wish to mass deploy this extension, simply perform a normal installation on a given computer and enter the URL of the PHP file directly inside the setup (e.g. http://trixbox1.corp.acme.com/originate.php). Once setup has finished, copy “AsteriskDialer.dll” and “AsteriskDialer.ini” to any network folder. Inside that folder create a batch file with the following content:

md "%ProgramFiles%\AsteriskDialer"

copy "%~dp0AsteriskDialer.dll" "%ProgramFiles%\AsteriskDialer" /Y
copy "%~dp0AsteriskDialer.ini" "%ProgramFiles%\AsteriskDialer" /Y

regsvr32.exe "%ProgramFiles%\AsteriskDialer\AsteriskDialer.dll" /s

reg add HKLM\Software\AsteriskDialer /v IniFilePath /t REG_SZ /d "%ProgramFiles%\AsteriskDialer\AsteriskDialer.ini" /f


And that’s it!

Wednesday, May 7, 2008

Removing lines from the output of a command line program

In case you need to deal with command line programs, you sometimes face the following challenge: the programs return too much data!

For example, Xteq Systems offers GetOSVersion which returns the current Windows version you are using. However, it also contains an header line so the complete example output is this:

Xteq GetOSVersion 3.0 - Copyright (C) 2008 Xteq Systems - http://www.xteq.com/

You are using Windows Vista (6.0) with Service Pack 1, return code is 9
(PlatformID 2; Major: 6; Minor: 0; Build: 6001)

Not that big deal if you (as an human) reads that but in case you want to export this data into a text file with the following command:

XQGetOsVer.exe /B >%TEMP%\result.txt

you will also of course get the header line you do not want to have. However, these is an easy solution for this: the FOR command. I won't get into the details what you can do with it (a lot and if you are interested use "help FOR" inside the command shell), but to solve the current problem we can simply use these two lines:

del %TEMP%\result.txt
for /F "skip=3 delims=" %%i in ('XQGetOSVer.exe /B') do @echo %%i >>%TEMP%\result.txt

First, we delete the file RESULT.TXT and then we execute the FOR command with two special parameters: SKIP=3 indicates that the first three lines from the output of XQGetOSVer.exe should be skipped and thus, the header is removed. The option DELIMS= indicates that we do not have delimiters so we get every line as is.

The part of DO indicates what we want to do with the remaining lines and use the ECHO command to write them to RESULT.TXT. We are using >> to indicate that we will append to this file (hence the DEL command first) to make sure we get all lines, not just one.

The result is exactly what we wanted:

You are using Windows Vista (6.0) with Service Pack 1, return code is 9
(PlatformID 2; Major: 6; Minor: 0; Build: 6001)

No header, just the the data.