Some members of our team, including myself, have attended a small, half-day workshop on Microsoft Embedded Technologies. Here's how the agenda looked like:
TIME
TOPIC
12:30
Registration and light lunch
13:00 – 13:05
Welcome speech
13:10 – 13:30
Introduction: Why use Embedded? What are the benefits?
13:30 to 15:00
Module 1: Windows Embedded Standard – Development Suite, Tools and Utilities.
Module 2: Embedded Enabling Features.
15:00
Tea/Coffee Break
14:30 to 16:00
Module 3: Demo: - Building an image using File Based Write Filter Module 4: Componentization of 3rd Party Drivers.
Module 5: Demo: - Creating Custom Components in your image.
16:00 - 16:30
Q & A
16:30
Closing and thank you
It was held at the local Microsoft office (not Microsoft Office, but the actual place where like, people work). The office was pretty boring by the way - no huge Bill Gates portaits, no sacrifices etc ... maybe they clean up when they know strangers will be present.
Anyway, the topic was mostly about how to assemble your own embedded OS from parts of dismembered Windows XP or Windows Embedded Standard etc. Basically, if I know exactly what peripherial devices will my hardware use, I can only include drivers for these devices, hugely reducing the size of the OS. Also, I may choose to cut out other elements of the OS - I may get rid of the whole explorer shell altogether. They mentioned that the smallest OS they have actually seen used by one of the clients was about 8MB in size. Quite impressive compared to the standard XP footprint of about 1.9GB.
As they said, the goal of the workshop was to show the participants that the process of assembling your own OS is not as complicated as people usually think. Can't say they succeeded - looked fairly complex to me so far ...
P.S. I have no idea why blogger inserts so many empty lines before the table ... will try to fix it later.
After a bit of thought, I decided what would be the easiest and the most convinient way to run my small application that helps to convert projects from VSS to TFS.
I will start the command line tool passing them together with parameters to cmd.exe application, and run cmd.exe with the -k parameter to prevent the command window from closing after the tool exits. I will keep the ID of the process that runs cmd.exe. Next time I run the cmd.exe, I will check if there is ID present, and if yes, I will kill the process, and then start a new one. This way the user's computer will not be littered with command windows.
So, the small class that would take care of process management looks like this
public class ProcessFactory { private static int _currentProcessID = -1;
private static Process _cmdProcess;
private static ProcessStartInfo _startInfo;
public static ProcessStartInfo StartInfo { get { if (_startInfo == null) { _startInfo = new ProcessStartInfo(); } return _startInfo; } }
public static void RunProcess(string filename, string args, string workingdir) { try { if (_currentProcessID > 0) { Process processToClose = Process.GetProcessById(_currentProcessID); if (processToClose != null) { processToClose.Kill(); } _currentProcessID = -1; }
I was not too loaded with work recently so I decided to write a small application that would help to automate the process of converting existing Visual SourceSafe projects to Team Foundation Server. The idea is to get some information from the user first, and then spare him from some manual tasks - running tools like ssarc, ssrestor or VSSConverter, manually creating and editing XML files etc.
When the application starts, the user needs to provide (or just check) the following information:
A folder where Visual SourceSafe is installed
A folder where Visual SourceSafe database is located
The name of the Visual SourceSafe project to be converted
A folder that will be used during conversion to restore VSS database, keep XML files etc.
SQL Server that will be used by the converter
A name of the TFS and the port number
A name of the project on the TFS where the converted files will go
A significant chunk of the application functionality is just wrapping the calls to command line tools so that the user does not have to bother with manually locating them, typing the correct parameters etc.
For that purpose, the .NET class Process is quite handy. Here is the example: To archive the VSS project MyProject which is in the VSS database located on MyServer into the archive file called MyArchive.ssa I need to run the following from the command line:
To run this command from the C# code I can use the following code:
ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "ssarc.exe"; startInfo.Arguments = @"-d- -i -yadmin,password -s\\MyServer\ MyArchive.ssa \$/MyProject\"; startInfo.WorkingDirectory = @"C:\Program Files\Microsoft Visual SourceSafe"; Process process = Process.Start(startInfo);
This is quite self-explanatory.
There are a couple of things that I had trouble with however. First thing is logging. It would be nice to log the errors and messages that the process generates. This is possible, according to the MSDN article.
Standard input is usually the keyboard, and standard output and standard error are usually the monitor screen. However, you can use the RedirectStandardInput, RedirectStandardOutput, and RedirectStandardError properties to cause the process to get input from or return output to a file or other device. If you use the StandardInput, StandardOutput, or StandardError properties on the Process component, you must first set the corresponding value on the ProcessStartInfo property. Otherwise, the system throws an exception when you read or write to the stream.
However, if I redirect standard output to the text file, for example, the user is unable to see it. And some of the tools used required interaction with the user. So it looks like I either interact with the user, or log the messages somewhere.
Also, when the process completes, it closes the window where it was running. So, if there is a message shown by the process when it exits, the user does not have time to read it. It might be frustrating when the process exits with an error message and the user does not know what exactly the error was. And it can not be logged because the output can not be redirected somewhere - the user needs to see it on the screen.
I will still be looking for the 'elegant' solution for this, but so far I found a workaround: rather than starting the process itself, I can start the command line using the "cmd.exe" and pass the whole tool together with the parameters as a parameter to cmd.exe.
The trick is that specifying the /k parameter prevents the command window from closing after the process exits. Here is how the previous code will look like when changed according to my workaround:
ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "cmd.exe"; startInfo.Arguments = @"/k "C:\Program Files\Microsoft Visual SourceSafe\ssarc.exe" "-d- -i -yadmin,password -s\\MyServer\ MyArchive.ssa \$/MyProject\""; Process process = Process.Start(startInfo);
I will be looking for a better solution when I have time to improve this application.
I had to write a small Windows Forms application today. It just gets some user input, creates an XML file, sends it to the webservice, gets the response, parces it and shows the results to the user. Good thing is that I had to remind myself how to use two simple things.
1. Saving and retrieving values using the app.config file.
If I want to get some values from the app.config file, I can keep them in the appSetting section and the whole app.config file for the small application can be as simple as that
To read the values I need to do just the following (after I add a reference to System.configuration to the project):
It is useful to know that this would not work at debug time, though - it will not throw an exception, but the values would not be updated too. I spent a few minutes trying to find out why it does not work before I understood that this behaviour is expected.
2. Creating the XML document.
Of course, for the purposes of my application, where the whole XML is maybe 10 to 15 elements, I could go with the following:
The code would actually be shorter than the "proper" XML handling, take less time to write and maybe even will work faster (especially if I use a StringBuilder to concatenate strings). I did it the "proper" way, however - for practice.
Now that I have the TFS installed to play with, my next task is to come up with the process to transfer existing projects from Visual Source Save. Since the current VSS database is fairly huge, and we do not want to transfer the whole thing at once, I came up with the following process:
Select project(s) to be transferred from VSS database
Back up project(s) and restore them to the new VSS database
Fix the issues in the new VSS database with the Analyze tool
Run the VSSConverter tool in analyse mode
Get the TFS ready for migration
Prepare the migration settings file
Run the VSSConverter tool in migration mode
Verify the results of the migration
This may look rather lengthy and complex, but it makes sure that the current VSS database remains untouched, which is quite important for obvious reasons.
Here is how I migrated a small project from VSS to TFS in a few more detail:
Select project(s) to be transferred from VSS database
Let's say we want to transfer MySmallProject which is located in $/MyMiscProjects/MySmallProject in a large VSS database.
Back up project(s) and restore them to the new VSS database
Microsoft has two utilities for backing up and restoring VSS projects, SSARC and SSRESTOR. Their parameters are described in detail here:
They usually can be found in the SourceSafe folder (i.e. C:\Program Files\Microsoft Visual SourceSafe)
First, I create a new VSS database (VSSTransfer) where I'm the admin. Next, I need to have admin rights in the initial VSS database and, of course, to know where it is located. Then I can run the SSARC command like that:
This backs up the MySmallProject with default parameters, without deleting files from the old database "MyHugeVSSDB", into the CodeProject.ssa archive file.
Next, I restore the project into the new empty database I created.
To run the VSSConverter, a settings file has to be prepared first. Here is the sample:
(if we need to transfer multiple projects, there can be multiple 'Project' elements under 'ProjectMap')
Now I save the file as settings.xml and run the VSSConverter tool (which is located in drive:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE ):
VSSConverter analyze settings.xml
(An important note, though - the VSSConverter should be the one that comes with TFS SP1. I tried to use the tool from the original TFS install and got troubles with history - it was not migrated at all).
Two files will be created, Analysis.xml and UserMap.xml
Get the TFS ready for migration
First of all, create the target project, i.e. MyTFSSmallProject. Then, look at the UserMap.xml. It lists all VSS users who performed action in the database. It looks like this:
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
To map users properly, we need to add them to TFS. If the user no longer exists, he can be mapped to any user - TFS admin or his team leader, for example. So the UserMap.xml will end up looking like this:
Modify the settings.xml file to specify the SQL Server that is going to be used for the migration process and Team Foundation Server, the users map file and the destination project on the TFS as follows and save it as migration_settings.xml. The SQL server does not have to be the one where TFS database are located, and the user performing the migration need to have CREATE DATABASE permission in the SQL Server.
Run the VSSConverter tool in migration mode
Run the VSSConverter tool in migration mode as follows:
VSSConverter Migrate migration_setting.xml
A report file called VSSMigrationReport.xml will be created if the migration process runs successfully. A log file called VSSConverter.log will contain information messages about the migration process.
Verify the results of the migration
Log in to TFS, go to the project's Source Control Explorer, check the files, history etc. Get the latest version, build it. Have fun.
Okay, so today the TFS was finally installed. Unfortunately, I cannot tell for sure what the exact thing that fixed it was, because we changed more than one thing. Firstly, the reporting services were uninstalled completely from the data tier. Secondly, we found some information on slipstreaming the SP1 for TFS 2008 and applied it to the installation package.
And lastly, we ran the installation from the beginning ... again. I personally think that removing the reporting services from the data tier did it. We'll need to have reporting services on the data tier later, we'll see if installing them back will break TFS or not. But for now, this weight is off my shoulders.
I got a response from the Microsoft support person, who have told me earlier that he was able to reporoduce our error.
So, according to what he told me, he looked up some internal documentation and found out that the particular configuration that we are trying to use (Windows Server 2003 on application tier, Windows Server 2008 on data tier) may not have been properly tested. So far, the recommendation is to install reporting services on the application tier. (Later, he said, we will be able to move them to the data tier).
There were a few issues because of the Sharepoint that was not completely removed from the application tier before we started the reinstallation of the TFS, but the most interesting was the "Error 29000.The Team Foundation databases could not be installed. For more information, see the Microsoft Windows Installer (MSI) log."
That was a bit tricky, because both admin and service account for the TFS had all possible permissions on the data tier. Some log file reading and some searching, and I found out that this is the issue with analysis services permissions.
The account should be a member of the “Server Role is used to grant server-wide security privileges to a user” under analysis services->properties->security option should be the TFS Service account. (There is no need to add the TFS Setup account or the TFS Report account here).
Now, the question was ... what error would come up next?
Next one was the Error 28805.The setup program cannot complete the request to the server that is running SQL Server Reporting Services. Verify that SQL Server Reporting Services is installed and running on the Team Foundation app tier and that you have sufficient permissions to access it. For more information, see the setup log.
OK, that was our mistake. The reporting services were removed from the data tier and installed on the app tier, but the databases were never created. Even the SQL Server was not installed yet on the application tier.
With that fixed, we moved forward just to finally hit the wall.
"Error 29112.Team Foundation Report Server Configuration: Either SQL Reporting Services is not properly configured, or the Reporting Services Web site could not be reached. Use the Reporting Services Configuration tool to confirm that SQL Reporting Services is configured properly and that the Reporting Service Web site can be reached, and then run the installation again. For more information, see the Team Foundation Installation Guide."
And what happens here remains a mystery for me so far.
This is what I see in the installation log:
"Setting database connection...
Verifying the configuration of SQL Server Reporting Services... SQL Server Reporting Services status Name: ReportServerVirtualDirectory Status: Set Severity: 1 Description: A virtual directory is specified for this instance of report server. SQL Server Reporting Services status Name: ReportManagerVirtualDirectory Status: Set Severity: 1 Description: A virtual directory is specified for this instance of report manager. SQL Server Reporting Services status Name: WindowsServiceIdentityStatus Status: Set Severity: 1 Description: A Windows service identity is specified for this instance of report server. SQL Server Reporting Services status Name: WebServiceIdentityStatus Status: Set Severity: 1 Description: A web service identity is specified for this instance of report server. SQL Server Reporting Services status Name: DatabaseConnection Status: Set Severity: 1 Description: A report server database is specified for this report server. SQL Server Reporting Services status Name: EmailConfiguration Status: NotSet Severity: 2 Description: E-mail delivery settings are not specified for the report server. E-mail delivery is disabled until these settings are specified. SQL Server Reporting Services status Name: ReportManagerIdentityStatus Status: Set Severity: 1 Description: A report manager identity must be specified. SQL Server Reporting Services status Name: SharePointIntegratedStatus Status: NotSet Severity: 2 Description: The report server instance supports SharePoint integration, but it currently runs in native mode. If you want to integrate this report server with a SharePoint product or technology, open the Database Setup page and create or select report server database that can be used with a SharePoint Web application. SQL Server Reporting Services status Name: IsInitialized Status: OutOfSync Severity: 3 Description: The report server is not initialized.
Verifying SQL Server Reporting Services configuration status failed.
Error: ErrorCheckingReportServerStatus.
Configuring SQL Server Reporting Services failed."
But why? I have no idea. Here is what happens:
I open Reporting Service Configuration Manager, go to "Database Setup" and notice that the "Server Name" is pointing to the data tier, and the "Initialization" shows a grayed cross against it. So I point it to correct server, Press "Connect", "OK", "Apply" and enjoy a lot of green ticks in the "Task Status" and a grayed cross being changed to grayed tick.
Voila! Reporting Services configured properly and initialized. I can go to http://localhost/reports and see the proper "SQL Reporting Services Home Page".
So I switch back to my error and press "Retry". The installer thinks for a while, but then the error is displayed again.
So I start the Reporting Service Configuration Manager again, go to "Database Setup" and notice that the "Server Name" is pointing to the data tier, and the "Initialization" shows a grayed cross against it!
Why does the installed does it to me? I have no idea so far and could not find any good information.