Chapter 5

Visual Studio and XIDE

X# developers have the luxury of having two very good IDEs at their disposal: Visual Studio and XIDE. The latter may be well known to the majority of X# developers coming from VO, the first is the major development tool in the Microsoft world for more than 20 years. Both are very good choices although with different "target groups".

In this chapter, I will give you a short overview of the Visual Studio extension for X# that is part of the X# installation and some basic operations within Visual Studio like adding files to a project and setting the version number for the application assembly. Although it's possible to install X# without the Visual Studio extension, there are only a few reasons to choose this option.

A short overview of XIDE concludes this chapter.

Which Visual Studio version is the best?

Usually, I recommend the latest version because we can assume that it contains the smallest number of bugs, offers the best performance, etc. This would be Visual Studio 2022. It's the first 64-bit version of Visual Studio (some users including me were waiting for nearly 20 years for this important feature).


Upgrading from an older version like Visual Studio 2017 to the latest version is usually nothing to worry about. It will take usually only a few minutes, but you may have to clean the C-drive first because you might need 10-12 GB of free space minimum. Since the project file format hasn't changed for a long time, a project in which files were saved with an older version of Visual Studio can be loaded with the latest version with no problems at all. There is not even a need for a project converter.

The most important circumstance is of course, if the X# extension works with a specific version of Visual Studio. That means, if you are working with an older version of Visual Studio and X#, please make sure by visiting the X# forum first if there are any known problems. It can be very time-consuming (and frustrating too) to fix these kinds of installation problems.



The fact that the X# team announced that they won't support older versions of Visual Studio is one more reason not to stay too far behind.


NOTE: One disadvantage of using the Community Edition of Visual Studio is, that you can go back to the previous version. You cannot go back to the older version because the download is not provided by Microsoft. Choosing an older version like 16.9 is only possible with a Professional or Enterprise license.


Although one could be tempted to buy a license of Visual Studio 2022 Professional, the free Community Edition contains all I ever needed even for some fairly large projects. There is also an Enterprise edition with some extras for (really) large corporations (that I have never even installed).

Please to go http://www.visualstudio.com for a complete overview of the available editions and their features. And please don't confuse Visual Studio with Visual Studio Code. The latter is a completely different kind of application. And don't think that Visual Studio also runs on an Apple Computer. Visual Studio for the Mac is also something completely different (yes, the author is a big fan of Monthy Python too)

if you install Visual Studio for the first time, try not to become overwhelmed by the huge number of choices. Whereas in the beginning, Visual Studio was the IDE for C# and Visual Basic.Net only, the current version supports plenty of languages (even Python) and plenty of platforms. You can even write games in C++ for Linux for example. And everything is free. But installing every feature available could add up to 25 GB of disk space or more.

.NET desktop development is the only option you will need for X# development. And you can de-select options like ML.NET Model Builder or Blend for Visual Studio if you don't need them at the moment. This will save you some space on the C-drive. And you can re-install any feature later without any problems.

Choosing a template

The first step for creating a new project is selecting one of the many project templates (19 if I have counted them correctly). A project template is not a requirement, but a convenience since it creates the minimum of files necessary to build the project, presets a few settings and creates the project file that contains these settings and references to all project files. Choosing a template is purely a convenience and not a requirement. It should always be possible to create any kind of X# application no matter what template has been chosen. And, as already shown, you could completely do all the work without Visual Studio although this is not recommended.


Important: If you would try out .Net core applications, please make sure that .Net 7 is already installed. Otherwise, a recent version of the .Net Framework has to be installed first. If you forget to install a .Net runtime, you will get no hint or warning but a lot of error messages instead.


Alt Choose the right template for a new X# project Fig 5.1: The first step is to choose a project template

Choosing the project directory

The next step is to choose a name for the project and the project directory. This is the directory where all project files will be stored.

It is always a good idea to place the solution file (the one with the sln extension) in the same directory as the other project file (the one with the extension xsproj). Choose the latest version of the .Net Framework (4.8) until there is a reason to choose a specific version of the .Net Framework.

Choose Create to set up the project directory.

Alt Configure your new project just means giving it a name and choosing a directory Fig 5.2: Project configuration means choosing a project name, a project directory, and the version of the .Net Framework

The content of the project directory

The project directory contains both the solution file (extension sln) and the project file (extension xsproj). Whereas the solution file can be easily recreated by creating a new solution and adding the project file later, the project file itself is more important. If it gets deleted for some reason the whole project must be set up again and all the files (that still exist) and the references must be added again and any project settings had to be set again too. So it's always important to keep the project file and the solution file too although it does not contain any important settings.

Alt The project directory of the newly created project Fig 5.3: The content of a project directory

The solution explorer

The solution explorer (Projektmappen Explorer in German and not "Programmenmappenstrukturbetrachter") shows the content of the solution, the projects, and their files and references. There is a little catch. For some reason, the solution explorer hides certain files. I recommend making all files visible by clicking Show all files in the toolbar. Another catch can be the distinction between the project view and a folder view that shows the solutions of the current file system folder.

Alt The solution explorer contains the logical view of the project directory *Fig 5.4: The Solution Explorer shows a (simplified) view of the project`s content *

Alt Not all files in the project directory are shown by default Fig 5.5: Show All files makes the output directory and other files visible in the Solution Explorer

The project settings

The menu command Project| properties open the project settings. All the settings are organized in eight tabs. The most important tabs are Application, Language, Dialect and Debug.

Tab Purpose
Application Contains several important settings like the application name, the default namespace, the target framework, the output type, and the dialect. In many cases, you can leave the default settings.
Language Contains several general compiler switches like case sensitivity.
Dialect Contains several special compiler switches used for achieving compatibility.
Build Contains some important settings like the target platform and the path of the output directory. The preprocessor variable DEFINE is predefined here. Another important setting is the generation of XML document files which is not set by default.
Build events Setting up pre- and post-build actions like copying files that are not part of the project to the output directory.
Debug This is the place for providing command line arguments.
Resources Every application can contain an XML-based resource file for bitmaps and other artifacts that will compiled into the assembly file as embedded resources.
Settings Every application can contain a config file that will be placed in the user profile directory. In contrast to the application config file, this config file is writeable.

Tab 5.1: The project setting tabs and their purpose

References

Handling references with Visual Studio is easy but there are a few pitfalls. One of them is that a referenced assembly must match the platform target. More on this later. Another pitfall can be a dependency of a .Net assembly to another library that has to be referenced too. And here is one more: In rare cases, a .Net assembly (managed code) can have a dependency on a dll file that is written in C++ for example (so-called unmanaged code). In this case, the dll file cannot be included as a reference but must be copied (through a build event for example) into the output directory.

I won't cover Nuget packages in this chapter.

For the following discussion about project references I will set a simple task for the readers: Turn the console application example from chapter 3 DbQueryXs.prg into a Visual Studio project.

Step 1: Create a new project and choose "console application" as a template.

Step 2: Remove the default file program.prg.

Step 3: Add DbQueryXs.prg to the project.

Step 4: Switch the dialect to VO. This is not necessary and is only done for demonstrating purposes.

The compiler can't compile the source code because three references are missing:

  • XSharp.Core.dll
  • XSharp.RT.dll
  • System.Data.SQLite.dll

Alt When switching to the VO dialect a reference to two X# assemblies is necessary Fig 5.6: Switching to the VO dialect requires references to two X# assemblies.

Step 5: Add the references to the project. There are several ways to do this. One is by choosing Add Reference... after right-clicking the References entry in the solution explorer.

Alt Adding a reference to the project Fig 5.7: Adding references through the Solution Explorer

You have to locate each assembly either in the GAC (.NET tab) or in its directory. If the reference had already been added before, you might find it in the Recent section.

Alt Choosing a dll file as a reference Fig 5.8: One option is to select each dll file from its directory

It is always a good idea to check the references in the solution explorer after a reference has been added to the project. Check for each reference the location of the DLL file and the version number displayed in the properties window.


The CopyToLocal property is usually set to True so that each Dll will be copied into the output directory.


Alt The properties of each reference is shown as usual in the property window Fig 5.9: The property window shows the properties of the selected reference like the version number

Since the CopyToLocal property is set to True by default, the assembly file will be copied into the output directory during the build process. So it doesn't matter where the file originally came from.

Although all assemblies are referenced, the sample project still does not compile.

This kind of error can be a little hard to detect. Fortunately, the error messages explain everything. The namespace Sqlite does not exist in the namespace System.Data. Are you missing an assembly reference? Of course, missing this reference I am.

Alt The error is a result of a missing reference Fig 5.10: The reference to the System.Data.Sqlite.dll assembly is still missing

Assuming the file System.Data.Sqlite.dll has already been downloaded from the project site (more on this in chapter 16), it's just another reference that has to be added to the project.

But after another build attempt, the error persists. But it's another one this time. Although the warning (it's not an error) message itself may sound a little "scary", it has a simple explanation.

Alt Its important to reference an assembly that matches the platform target of the project Fig 5.11: The platform target of a referenced assembly does not always match the platform target of the project

The platform target in the project settings is set to "Any CPU", and the assembly file is targeted to x64 explicitly. I recommend using the great tool IlSpy for checking all the details about an assembly including the target platform. There are three options:

  1. Choose another assembly with "AnyCPU" as its architecture.

  2. Set the platform target to x64 in the project settings.

  3. Install System.Data.Sqlite as a Nuget package. This is my recommendation because you are very likely installing the right dll.

For this example, I will use the latter option and set the platform target to x64. Although changing the platform target sounds like a simple task, it can be a little challenging if you do this the first time. Not only there are several locations for setting the platform target within Visual Studio, but you will also have to create a new target although you just want to apply an existing target like x64 in the Configuration Manager (which had been a source of confusion for me from the first day I started using Visual Studio).

Platform Meaning
x86 Loads the assembly as a x86 assembly. Will not load from an x64 process.
x64 Loads the assembly as a x64 assembly. Will not load from an x86 process. Same as AMD64.
ARM64 Loads the assembly with byte code for an ARM CPU. Will not load on an AMD or Intel CPU.
AnyCPU Loads the assembly either as an x64 or x86 assembly, depending on the invoking process.

Tab 5.2: Short overview of the platform options for a Visual Studio project


NOTE: The fact that you can set an “Any CPU” configuration inside Visual Studio, and still have projects inside that configuration that are targeting x86 or x64 has been a source of constant confusion for me the last 20 years.


From my experience, the easiest way to achieve this goal is to change the platform target in the build category of the project settings and not somewhere else.

Alt Setting the target platform in the project settings Fig 5.12: Setting the platform target should be accomplished in the project settings if it's necessary at all

The application should compile now. But it will not run because the SQL statement results in an error. This has something to do with the fact that if the SQLite provider cannot find the database file that is referenced in the connection string, it will create a new file. Since this file does not contain any tables, the SQL query will fail. End of story. The reason for this is that although the db file is already part of the project directory, by default it will not be copied into the output directory where it has to be because of the relative path in the connection string.

This time there are two options for making Visual Studio copy a file into the output directory during each build process:

  1. By using a copy command in a pre- or post-build event in the project settings.
  2. By adding the file to the project and setting the CopyToOutputDirectory property to either "Copy always" or "Copy if newer".

Option 2 is usually much simpler. Right-click on the project entry in the solution explorer and choose Add, Existing item, and the file to be added to the project. Since it's part of the project, it has some properties to set in the properties window after the file has been selected in the solution explorer. One of the properties is CopyToOutputDirectory. Usually Copy always is the best option to choose.

Alt Setting CopyToOutputDirectory to 'Copy always' or 'Copy if  newer' Fig 5.13: To have a project file in the output directory the CopyToOutputDirectory property must be set

Now the application not only compiles but will also deliver the expected result (a few book titles that appear in the console window). You will notice that the application window closes immediately. The only way (I know) to keep it open is to add aConsole.ReadKey()statement at the end.

Alt The sample application finally compiles and runs because all the references had been set correctly Fig 5.14: Finally the sample application compiles and runs and the windows do not close


NOTE: When you add references in Visual Studio, the build system will automatically include a /noconfig switch when calling the X# compiler. Therefore references to assemblies such as System.Core and System.Data had to be set explicitly.


Editing the project file

A Visual Studio project file is always an XML file in the (well-documented) MsBuild format. Although it is not recommended, it's possible of course to edit the file within Visual Studio. Right-click the project in the solution explorer and choose Edit the project file. Visual Studio will unload the project and show the content of the project file in an editor window. After the editing is done, reload the project by choosing Reload the project in the context menu of the project entry in the solution explorer.

Setting the version number of the application

The version number of the application is not part of the project settings. It has to be set in a source code file. Although this could be any prg file, usually it is a file called AssemblyInfo.prg in the Properties subdirectory:

[assembly: AssemblyVersion("1.0.*")]

[assembly:] is a so called attribute target (in the namespace System.Reflection). It specifies that an attribute applies to the assembly itself. The file contains several other attributes for setting things like a title, description, or copyright note. it also contains a GUID (Global Unique Identifier) which is optional.


NOTE: When the version number ends with a *, each time you recompile the assembly a new version number is generated. That means that dependent assemblies also have to be recompiled.


Debugging

Debugging is such a huge topic with so many options that I will discuss only a few selected topics. If you are coming from a C# background the only difference is that the "debugging experience" with X# is not on the same level yet. But the X# team is working on it. And C# expression can be used everywhere where expressions are evaluated like in the immediate window.

The immediate window

The immediate window is still the most important "debugging tool" for many developers from the early days on. It does not only allow the evaluation of any valid expression (either in X# or C# syntax) but also executing methods and even lambdas. However, the output is usually not sufficient. And is not possible to declare variables though or use variables that either have not been declared or a not in scope.

The immediate window is usually only visible during a debugging session. Otherwise, you will find it under Debug->Windows->Immediate or Ctrl+Al+I. It used to be "C# syntax only" in the early days of X# but the X# development team has improved its capabilities with each version so that X# expressions can be evaluated as well like expressions with Self: or with VO functions like

Left(kennzahl,1) + "1" + SubStr(kennzahl,3)

But case sensitivity is still important.

There are two more points to keep in mind during debugging:

  1. For VO-Arrays the index has to be always current index - 1 (eg. aBilanz[i-1, 4-1])
  2. After an exception variables at a class level might not be accessible anymore (so it's better to set a breakpoint before the exception occurs).

Alt The immediate window allows expression evaluation and executing methods during debugging Fig 5.15: The immediate window allows expression evaluation and executing methods during debugging

The context menu

Use the context menu during a debugging session for an overview of the most important "commands" like "Goto Definition", "Set next statement", "Show next statement" or "QuickWatch".

Alt The context menu during a debugging session contains many important commands Fig 5.16: The context menu during a debugging session contains many important commands


TIP: One of the many tips for debugging with Visual Studio is the keyboard shortcut Ctrl - which sets the cursor to the last edit location.


Breakpoints

Using breakpoints so that the program execution "breaks" when the source code line with the breakpoint is reached is, besides the immediate window, the most important debugging technique for ages. Visual Studio handles breakpoints mostly the same way as any other IDE. The F9 key is used for switching a breakpoint at a source code line on or off. Breakpoints can be disabled temporarily or attached to a condition so that breakpoints will only be hit when the condition is met.

Using breakpoints is simple but not always. Sometimes a breakpoint disables itself immediately after the application starts. The breakpoints appear a little "strange" (empty instead of full) in the source code editor.

Alt If the breakpoint circle is drawn empty the breakpoint will not be hit

Fig If the breakpoint circle is drawn empty the breakpoint will not be hit after the application starts

One reason can be that the source code, for whatever reason, is different from the original version. To prevent this situation, one of the many debugging options has to be deactivated. Another option deactivates the diagnostic tools you usually don't want to see during debugging.

Alt Deactivating an option in the Visual Studio options prevents that a breakpoint will be deactivated

Fig Deactivating an option in the Visual Studio options prevents a breakpoint will being deactivated after the application starts

The QuickWatch window

The QuickWatch window is a very helpful feature that I use a lot during debugging. It not only shows the current value of an expression, but it also allows modifying the expression while evaluating another expression. This is a really big time saver. Another nice feature is provided by the Add Watch button that turns the current expression into a watch expression that can be watched in a watch window. One way to show it during a debugging session is to mark the expression and press Shift+F9.

Alt The QuickWatch windows allows evaluation of any expression that is evaluable in the current context Fig 5.17: The QuickWatch windows allows the evaluation of any expression that is valuable in the current context

Please beware that the QuickWatch window is case-sensitive. If a variable is declared with the name rowVorInst but the name in the expression is rowVorinst for example, the QuickWatch window will not evaluate anything. One more argument is to keep variable names consistent.

Alt No evaluation because of the different spelling of a variable name Fig 5.18: No evaluation possible because of the "wrong" spelling of a variable name

Evaluating arrays

Evaluating the value of a VO-style array is a little cumbersome especially if it's a two or multidimensional array. It's always necessary to click through a hierarchy to finally see the values. I recommend using the QuickWatch window because it offers the best overview.

The QuickWatch and its limitations are one of the few weak points of the Visual Studio support for X#. All it would take is that "someone" writes a better visualizer which is not so difficult at all. It's probably on the list with a low priority.

Alt Evaluating an array is a little cumbersome with X# 2.x Fig 5.19: Evaluating an array is a little cumbersome with X# 2.x

Settings bookmarks

Since most projects become large, setting bookmarks is something that helps me find the part of the source code where something important is happening. Although the search function is fast and convenient, I use bookmarks a lot.

Open the bookmark window through the window menu (or press Ctrl+K+W) and create a bookmark for the currently selected line. And don't forget to change the name to something that describes the location.

Alt Setting bookmarks makes finding important parts of the source more convenient Fig 5.20: Setting bookmarks makes finding important parts of the source more convenient

Printing source code

Printing source code is one of the few weak points of Visual Studio since the very first version (I would even bet my "Windows 98" pen that this function has never changed since then). So, I usually copy the source code in Notepad2 or Notepad++ and use the editor for printing. Don't forget to check if the option Selection is selected in the standard printing dialog if you want to print only the selected source code (otherwise the printer might spit out a couple of hundred pages).

Building and deployment

I almost forgot the most important topic of this chapter. All the information in this section only applies to the .Net Framework and not to .Net 7 or later versions that are based on the .Net Runtime and use packages instead of single dll files.

Building a project in Visual Studio is easy. Either by pressing F5 or another shortcut like Ctrl+B. Both have the effect that all files needed for running the application will be copied into the output directory, usually bin\debug if the project was built using the debug configuration.

There is no difference between an X#, a C#, or a Visual Basic project.

If the application needs any file that is not referenced, it has to be copied separately. Either by including it in the project and setting the CopyToOutputDirectory property or by creating a post-build event in the project properties that use the copy command.

So, running the project on the developer's machine is very easy. It will always work. The so-called "deployment" can be a little harder (for clarification: deployment means copying all files needed by the application, including the exe, into a directory on the computer where the application should run later).

If an application app.exe needs another assembly lib1.dll as a dependency, both files need to be copied of course. If lib1.dll has dependencies on its own, they have to be copied too. The complete .Net Framework runtime has to be installed separately. All the needed assemblies are part of the Global Assembly Cache (GAC for short) which is just another directory (usually C:\WINDOWS\assembly).


TIP: For finding out what dependencies any assembly has, the excellent ILSpy tool is a great help.



NOTE: From my experience, the version of the .Net Framework on the target machine does not have to match the version number on the developer machine when it comes to the minor version numbers. An application developed with .Net Framework 4.7.1 will run on a computer with .Net Framework 4.8 installed and vice versa. Except of course, when the application might use a method that is only part of a later version of the .Net Framework. I always would use the latest version of the .Net Framework (which is 4.8.1) but no version before 4.6.2 (this version brought finally the support for path names longer than 260 characters).



TIP: The free .Net version detector from asoft.be (dotnetver.exe) is a great tool for getting a list of all .Net versions installed on a computer.


Creating a classic setup program

Visual Studio (or Microsoft in general) offers no tool for creating a classic setup program (that would create an MSI package). One tool I can recommend is Advanced Installer (https://www.advancedinstaller.com). It offers all the functionality you will ever need. Although the Pro version has a certain price tag (there used to be a free version many years ago), for professional projects it's worth the money. Although there is a free alternative, an MSI package creator called WiX toolset (https://wixtoolset.org/), I haven't tried it and would not waste too much time and energy on finding a "free" alternative for my professional projects.

The "poor man version" for a setup program would be a little script (besides PowerShell you could use AutoIt which makes building a GUI easy) that copies all files in a given directory and creates a shortcut either on the desktop or in the start menu or both.

Making sure the expected version of each assembly exists

To make sure that the expected version of each required assembly file is on the "customer computer", I use a simple technique. First, I create a simple text file that contains the name of each assembly and the expected version number separated by a comma:

Assembly,Version
Nlog.dll,4.4.5422
Oracle.ManagedDataAccess.dll,4.122.19.1
XSharp.Core.dll,2.14.0.4
XSharp.RT.dll,2.14.0.4

Second, I use a nice PowerShell command for the comparison:

import-csv -Path .\libcheck.csv | Where-Object { (Get-Item -Path $_.Assembly).VersionInfo.FileVersion -ne $_.Version}

libcheck.csv is the name of the text file. The command lists the names of all assemblies whose version does not match the expected version number in the text file. As always, you can use any version of PowerShell and upper/lower case does not matter.

You don't have to start Notepad and type in the name and version number of each assembly that is contained in the output directory of the project. PowerShell will save you from this tedious task too.

The following command goes through all DLL files in the current directory, takes the name and the version number of each (assembly) file, and writes both into a text file with a header line that contains the name of the two properties separated by a comma:

dir *.dll | Select-Object @{n="Assembly";e={$_.Name}},@{n="Version";e={$_.VersionInfo.FileVersion}} | Export-CSV -Path libcheck.csv -NoTypeInformation

Although I recommend using PowerShell 7. x because of the option of suppressing the quotes around the names, the built-in Windows PowerShell will accomplish this task too.

Visual Studio and the command line

Although the complete development cycle is controlled through the IDE, from time to time it might be convenient or even necessary to use a command line window. Don't start the PowerShell or Commandline window from the start menu, use the special developer prompt for Visual Studio instead. Although you will see the same blue or black window, there is a small but important difference: All the environment variables are already set, so you can run any Visual Studio tool or a tool from the .Net Framework SDK directly without worrying about in which directory it may hide. Remember: You will find the developer prompt in the Visual Studio folder in the start menu. I recommend choosing Developer Powershell for VS 2022 because it offers more comfort, but the regular Command prompt will work as well.

Alt The Developer command prompt is started from the Start menu

Fig The Developer command prompt is started from the Start menu

Options

There are hundreds of options that can be changed but only a few are important.

The options dialog is always opened by Tools->Options (there is no shortcut set).

It's important to note that in the text editor section, every language has its subcategory with options specific to that language.

So, there is an X# option too with at least 8 subcategories. The most important is Formatting because it contains the settings for handling the case sensitivity. Whenever you choose Edit->Advanced->Format document to reformat the current source document, the settings in this subcategory define how the cases are set.

Alt The Keyword Case Synchronization settings define how Visual Studio handles the uppercase and lowercase for keywords Fig 5.21: The Keyword Case Synchronization settings define how Visual Studio handles the uppercase and lowercase for keywords

Visual Studio and Git

Using git as version control software for any kind of software project seems like a "no-brainer" today. There used to be a time not too long ago when there were actual choices (anybody remembers Visual SourceSafe?) It's astonishing to me that even Microsoft gave up its own product Team Foundation Server (TFS) in favor of git. Probably to avoid any confusion with Microsoft Teams;)

According to a StackOverflow survey from 2022, an overwhelming number 93.9% of all developers named git as their favorite version control. So, git is an excellent choice and I would be probably the last person on earth who would be able to find anything that the git development team could have done better.

Although Git is not difficult to use, I won't even attempt to give a short overview. The git integration in Visual Studio got better with each version. With the current version 2022, it's really good. Most of the git actions happen both in the git menu and in the git changes window.

There is one small tip I would like to mention because it might be not so obvious. Every project needs a .gitignore file that contains all the file extensions and subdirectories that should not be tracked and pushed (like the obj directory for example). This file can be easily created and edited in the Git Repository Settings under Tools -> Options -> Source Control -> Git Repository Settings. Otherwise, the file would have to be added like a regular text file or created in the command line.

For X# the file is currently empty, but I am very optimistic that it's just a matter of time until there will be a full template like the one for C#.

Alt Adding a .gitignore file to a project Fig 5.22: Adding a .gitignore file to a project

A word about signing an assembly

Any assembly is "signed" which means that it will become a strong name. A strong name consists of four parts:

  1. The assembly name (without the file extension)
  2. A version number (e.g. 1.0.0.0)
  3. A culture name (usually neutral)
  4. A public key token

Since this is all described in epic length in the Microsoft documentation and many other places, I will keep this section as short as possible.

A typical strong name of an assembly will look like this:

Microsoft.SqlServer.Smo, Version=17.100.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91

Usually, there is no need to sign an assembly (either exe or dll). The one exception for the .Net Framework is when the assembly should be placed in the GAC. All the "official" assemblies, like the ones from a component vendor, are always signed and therefore have a strong name. And since these assemblies are always signed with the same public/private key pair, the public key token is the same.

There are two alternatives for signing an assembly:

  1. Inside the Build property page of the project properties by providing an existing key file
  2. With the command line compiler xsc.exe and the /keyfile switch and the path of a key file

In both cases, a key file is needed. The easiest way to create such a key file is using the command line tool sn.exe:

xsc .\test.prg /keyfile:EF-Test.snk

Another option is to create a new C# project and choose "New..." in the project settings (this is not possible for an X# project). Just to make it clear (and by taking the risk of offending some readers), the key (file) is completely independent of a project type or programming language (of course).

But again, there is no real benefit in giving an assembly a strong name.

There is another "flavor" of signing that can lead to some confusion (and it did confuse me recently). An assembly can also be signed with a certificate (that is suitable for code signing). This has nothing to do with the strong name. It means that the file contains a digital certificate that contains information about the company and is part of a so-called "trust chain" if the publisher of the certificate is a trusted entity. Signing an assembly with a certificate cannot be done within Visual Studio. This is done with the tool Signtool.exe from the .Net Framework SDK (the version number does not matter). It might not be in the path even in the developer command window, so you will have to locate it and add the path to the Path environment variable.

A small benefit of signing an assembly with a certificate is that any changes in the file's content will be detected. The application will still start, but the certificate is destroyed because the hash values do not match anymore. And it's possible to use a simple PowerShell command to list all the assemblies with a "bad certificate".

Transferring a project to another computer

Although it just means copying the complete project directory to the new computer, it can be a lot more work and it can cause some unexpected troubles.

The following tasks had to be done manually:

  1. Updating all references
  2. Checking if Microsoft Office Interop assemblies are still embedded or loaded as a file
  3. Updating the license information by reinstalling certain assemblies through an installer (otherwise you will experience an lc.exe error during the build)
  4. Checking if the right target .Net Framework is installed
  5. Registering COM-Components with regsvr32.exe
  6. Updating absolute paths in the source code

Without going into any details, I recommend not doing all these steps in a rush and expecting that the project can be rebuilt without any further actions, but planning 1-2 hours for the rebuild.

XIDE

XIDE was the VO development environment for many years. Now it's available as a 100% .Net IDE for X# development.

XIDE is developed by Chris Pirgas, one of the members of the X# team. It's not an open-source project. The current version is 1.33.

It's the perfect IDE for typical Windows Applications with a "VO coding style focus" that consists of a single project. All the console applications in this book can be run with XIDE by loading the prg file and pressing F5. There is no need to create a project or set up an application first. This is only necessary if an example needs additional references or if you like to start developing a WinForms application.

XIDE can be installed as part of the general X# installation or separately.

The regular installation directory is C:\XIDE. If you include this path in the path environment variable, a prg file can be directly opened in the command line:

xide .\test.prg

XIDE is the IDE for most of the X# developers

Fig 5.23: XIDE is the IDE for most of the X# developers

Since working with XIDE is mostly self-explanatory for any experienced developer, I will not go through the details.

If you are new to XIDE the workflow can be a little confusing (at least it was for me).

The first step is to either "create" an empty project to be able to load several PRG files independently of each other or to create a new project.

Alt Creating a new XIDE project

Fig 5.24: Creating a new XIDE project

Choose New, give the project a name, or use the default name, press OK and then Select to open the new project. A project folder will be created in the XIDE project directory and a project file with a xiproj extension.

A project is just an empty shell with no real content. What we need is an application. Right-click on the project name in the project explorer on the right side and choose New Application.

Now, XIDE comes to life and presents a lot of interesting templates from the application gallery. There are templates for creating a VO MID application, a WPF application, and a system service and there are even some C# templates. Choose "Basic x# Form application" for example and give the application a name.

Alt Creating a new XIDE application

Fig 5.25: Creating a new XIDE application

XIDE creates the files with the appropriate content for a WinForms application. You can use a very good Windows Forms designer by double-clicking on "BasicForm" in the Project Explorer.

Run the application with F5. If the application will be compiled with F9 without any errors, the exe file is in the bin folder of the project and not of the application (which does not exist anyway).

From now on, the "rest" should be self-explanatory.

Alt XIDE offers a nice WinForms designer

Fig 5.26: XIDE offers a nice WinForms designer