Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Programming for Microsoft Windows Vista and Server 2008 (Windows 7)

4.46/5 (30 votes)
19 Apr 2009CPOL8 min read 63.9K   672  
This article exposes the Microsoft Vista and Server 2008 (and Windows 7) exclusive features that can be programmed using .NET languages like C#. It includes UAC, the Vista Bridge control library, and the Windows Search Provider.

Introduction

In this article, I will discuss on what you need to know about developing applications for Windows Vista and Windows Server 2008, and the upcoming OS Windows 7, and how to implement these from .NET (C#) applications. The accompanying downloadable application contains all you need to start off immediately. It includes the Vista Bridge runtime, its CHM Help file, and the Windows Search Interop assemblies. But, to keep yourself updated with changes from Microsoft, you should probably get yourself the updated runtimes from the Microsoft site.

The topics that will be covered here are:

  • Vista Bridge
  • User Access Control (UAC)
  • Directory structure
  • New controls and dialogs
  • Windows Search

Vista Bridge

Vista Bridge is a new API introduced by Microsoft that wraps a lot of the native calls to the Windows Vista OS. This enables the exciting features in Vista like Glass forms, new dialogs, etc. We would keep our discussion to the very basic and general features exposed by this API.

User Access Control

UAC is a feature exclusively introduced from Windows Vista and Windows Server 2008. Although it has its issues, the feature has made Windows Vista and Server 2008 much more safer than their predecessors. Think about a situation where a user gets the Administrator feature and installs a trojan horse and destabilizes the system. The UAC feature has reduced the chances of that. A general user logged in as an Administrator will have to go through the UAC prompt to perform an action that requires an elevated permission. Thus, we infer that an Administrator logged on to the system doesn't get an administrative privilege on Windows Vista.

To provide Administrative privileges, select "Run as Administrator" from the context menu. This section adds the application compatibility flags to the Registry at HCU\Software\Microsoft\Windows NT\Current Version\AppCompatFlags\Layers with the value of RUNASADMIN.

How to get the UAC prompt and run an application at an Elevated permission?

To get an Elevated permission for your application, just follow these steps:

  1. Add a Manifest file to the application project. The application manifest is named app.manifest, by default.
  2. Open up the manifest file and edit the level attribute of requestedExecutionLevel in the XML to a value that represents the Execution privilege of the application.

The Execution privilege values are requireAdministrator, highestAvailable, and asInvoker. The value highestAvailable means that the application gets the privileges the user has-but only after getting the consent from the user. The value of requireAdministrator requires Administrator privileges. If the user is not logged in as Administrator, a login dialog appears where the user can log in as an Administrator for the application. The value asInvoker means that the application is running with the security token of the user.

The uiAccess attribute specifies if the application requires input to a higher privilege level window on the desktop. An example code for app.manifest for Administrator privilege from UACAdminPrompt is:

XML
<asmv1:assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
      xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" 
      xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0">
  <assemblyidentity version="1.0.0.0" name="MyApplication.app">
  <trustinfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedprivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        
        <requestedexecutionlevel level="requireAdministrator" uiaccess="false">
      </requestedexecutionlevel>
    </requestedprivileges>
  </security>
</trustinfo>

</assemblyidentity>

Shield icon

When the user clicks on a control with Shield icon, an elevation prompt is used. Elevation prompts would be different depending on the type of application that is elevated:

  • Windows needs your permission to continue. This elevation prompt is shown for applications that are delivered with Windows.
  • A program needs your permission to continue. This elevation prompt is shown with applications that contain a certificate to provide information about the publisher.
  • An unidentified program wants access to your computer. This elevation prompt is shown with applications that don't contain a certificate.

Directory structure

The directory structure has changed a lot from Windows XP to Vista. There's no more a directory of the form c:\Documents and Settings\<username> and had been replaced in Vista by c:\Users\<username>. Windows XP defines a subdirectory My Documents for storing user-specific data, but Windows Vista defines c:\Users\<username>\Documents. To retrieve the folder path, use the SpecialFolder enumeration as:

C#
string folderName = Environment.GetFolderPath(Environment.SpecialFolder.Personal);

Some of the folders defined by the SpecialFolder enumeration are described in the following table:

ContentSpecialFolder EnumerationWindows Vista default Directory
User specific documentsPersonalc:\Users\<user>\Documents
User specific data for the roaming profileApplicationDatac:\Users\<user>\AppData\Roaming
User specific data that is local to the systemLocalApplicationDatac:\Users\<user>\AppData\Local
Program FilesProgramFilesc:\Program Files
Program Files that are shared among different programsCommonProgramFilesc:\Program Files\Common
Application data common to all usersCommonApplicationDatac:\ProgramData

An example code that retrieves the Vista directories using the above enumerations is highlighted in the application DirStucture project.

DirStructure Project

Windows Search Provider

Before we begin, let me state that the Windows Search service must be enabled for this to work. Disabling the Windows Search service will cause the query to fail and return an error. Open a C# project, and create a Windows Forms application named, say, VistaSearch. Open the Windows form in designer mode and place these following controls in it:

  • TextBox named tbSearch
  • Button named btnSearch, Text: SQL Search
  • Button named btnClassicSearch, Text: Search
  • ListView named lvResult, Detail mode.

The Windows Search provides a DSO for querying the Windows Search engine with a SQL query. The DSO is named Provider=Search.CollatorDSO.1;EXTENDED PROPERTIES='Application=Windows'. Open this provider using an OLEDB connection and pass the SQL query into it to get the result.

So, we have it. Now, let's see how to use this DSO in our application. Open the source code of the event handler corresponding to the button name btnSearch, and write:

C#
try
{
    lvResult.Clear();
    string indexConnectionString = "Provider=Search.CollatorDSO.1;" + 
           "EXTENDED PROPERTIES='Application=Windows'";
    OleDbConnection connection = new OleDbConnection(indexConnectionString);
    connection.Open();
    OleDbCommand command = connection.CreateCommand();
    command.CommandText = tbSearch.Text;
    OleDbDataReader reader = command.ExecuteReader();
    DataTable schemaTable = reader.GetSchemaTable();

    foreach (DataRow row in schemaTable.Rows)
    {
        lvResult.Columns.Add(row[0].ToString());
    }
 
    while (reader.Read())
    {
        ListViewItem item = new ListViewItem(reader[0].ToString());
        for (int i = 1; i < reader.FieldCount; i++)
        {
            item.SubItems.Add(reader[i].ToString());
        }
        lvResult.Items.Add(item);
    }
    connection.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message, "Error", 
      MessageBoxButtons.OK, MessageBoxIcon.Error);
}

The application must also include the following line:

C#
using System.Data.OleDb;

The above code the following output:

SQL Search

This should be fairly easy to understand for those who have a knowledge of using using SQL search queries on a database.

Advanced Query Syntax (AQS)

Now, let us focus on the second part of the problem. The above search query included the SQL, but would you like your application user to provide a SQL directly into the Search textbox? I guess the answer is no. So, the workaround is to use the COM based AQS helper built into Vista to do our work. To do so, we must first implement the COM callable wrapper as follows:

tlbimp "c:\Program Files\Microsoft SDKs\Windows\v6.0\Lib\SearchAPI.tlb" 
       /out:Interop.SearchAPI.dll

If the path does not exist, then an alternate is:

tlbimp "c:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\SearchAPI.tlb" 
       /out:Interop.SearchAPI.dll

The output will be a DLL Runtime named Interop.SearchAPI.dll. Add a reference to this COM wrapper DLL from our project and then add the following line in the source code:

C#
using Interop.SearchAPI;

Then, we would write out a function named GetSql where we would only pass in the search keyword and it would generate the SELECT SQL call statement which we would pass as SQL statement in the above written code.

C#
private string GetSql(string aqs)
{
    CSearchManager searchManager = new CSearchManager();
    CSearchCatalogManager catalogManager = searchManager.GetCatalog("SystemIndex");
    CSearchQueryHelper queryHelper = catalogManager.GetQueryHelper();
    return queryHelper.GenerateSQLFromUserQuery(aqs);
}

Now, we could open and modify the source code of the btnClassicSearch click event as follows:

C#
private void btnClassicSearch_Click(object sender, EventArgs e)
{
    try
    {
        lvResult.Clear();
        string indexConnectionString = "Provider=Search.CollatorDSO.1;" + 
               "EXTENDED PROPERTIES='Application=Windows'";
        OleDbConnection connection = new OleDbConnection(indexConnectionString);
        connection.Open();
        OleDbCommand command = connection.CreateCommand();
        command.CommandText = GetSql(tbSearch.Text);
        OleDbDataReader reader = command.ExecuteReader();
        DataTable schemaTable = reader.GetSchemaTable();

        foreach (DataRow row in schemaTable.Rows)
        {
            lvResult.Columns.Add(row[0].ToString());
        }
     
        while (reader.Read())
        {
            ListViewItem item = new ListViewItem(reader[0].ToString());
            for (int i = 1; i < reader.FieldCount; i++)
            {
                item.SubItems.Add(reader[i].ToString());
            }
            lvResult.Items.Add(item);
        }
        connection.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", 
          MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

For source code, view the VistaSearch project available as download with this article. A demo output is:

Vista Search with Keyword

Aero Glass Windows Forms

To design an Aero form, just open a C# Windows Forms application, and add reference to VistaBridgeLibrary.dll and VistaBridgeControls.dll to your application. Add the following lines to your source code:

C#
using Microsoft.SDK.Samples.VistaBridge.Dialogs;

Now, derive your Aero Form (to be) class from the GlassForm super class. Then, modify the Form1_Load, that is the Load event, and add the following lines to enable AERO for the form:

C#
this.IsGlassEnabled = true;

A sample AERO form is shown below:

AERO Form

Command Link

Command Link controls are an extension to the Windows Button control. A Command Link control contains an optional icon and a note text. This control is often used in task dialogs and wizards. To use the Vista controls, add the following line to the Windows Forms source code:

C#
using Microsoft.SDK.Samples.VistaBridge.Controls;

Now, add a private variable to the Windows Forms class as follows:

C#
private CommandLinkWinForms commandLinkDemo = new CommandLinkWinForms();

Now, modify the Windows Forms constructor to add the Command Link to our Windows Forms as follows:

C#
InitializeComponent();
commandLinkDemo.NoteText = "This is the Note Text on the Windows Vista type Button";
commandLinkDemo.ShieldIcon = true;
commandLinkDemo.Text = "This Command Link control is a part of Vista Library";
commandLinkDemo.UseVisualStyleBackColor = true;
commandLinkDemo.Location = new Point(20, 20);
commandLinkDemo.Size = new Size(300,100);
commandLinkDemo.Click += new EventHandler(this.OnCommandBtnClicked);
this.Controls.Add(commandLinkDemo);

Thus, we see above that a Click event handler is also added to the project which is handled as:

C#
protected void OnCommandBtnClicked(object src, EventArgs ev)
{
    MessageBox.Show("Command Link button clicked.", 
      "Vista command Link Demo", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

The source code is taken from the VistaCommandLink project, the output of which is:

Vista Command Link

File Dialogs

Windows Vista has replaced the classic file dialogs with its new dialogs that have an inherent Windows Search built into them to ease file opening and saving. To display the file open dialog, use the following piece of code:

C#
CommonOpenFileDialog dlg = new CommonOpenFileDialog();
dlg.Filters.Add(new CommonFileDialogFilter("All Files.", "*.*"));
CommonFileDialogResult result = dlg.ShowDialog();

The output of the above code is:

Vista Open File Dialog

The file save dialog is shown using the following piece of code:

C#
CommonSaveFileDialog dlg = new CommonSaveFileDialog();
dlg.Filters.Add(new CommonFileDialogFilter("All Files", "*.*"));
CommonFileDialogResult result = dlg.ShowDialog();

The output of the above code is:

Vista Save File Dialog

Task Dialog

The task dialog is a next generation dialog that replaces the old message box. The task dialog is a part of the new common controls. It is accessed in Vista using the TaskDialog class. The following code displays a simple task dialog:

C#
TaskDialog.Show("This is a Simple Task Dialog");

The output of the above code is:

Simple Information Dialog

The following code sets the member properties of a task dialog namely, Caption, Content, StandardButtons, and MainIcon:

C#
TaskDialog dlg = new TaskDialog();
dlg.Caption = "Title";
dlg.Content = "This is some information in the Task Dialog.";
dlg.StandardButtons = TaskDialogStandardButtons.OkCancel;
dlg.MainIcon = TaskDialogStandardIcon.Information;
TaskDialogResult result = dlg.Show();

The output of the above code is:

Information Task Dialog

With the task dialog, you can also set command links. So, let's write another piece of code as follows:

C#
TaskDialog dlg = new TaskDialog();
dlg.Caption = "Title";
dlg.Content = "This is some Content Information in the Task Dialog.";
dlg.StandardButtons = TaskDialogStandardButtons.YesNo;
dlg.MainIcon = TaskDialogStandardIcon.Shield;
dlg.ExpandedText = "This is the Expanded text.";
dlg.ExpandedControlText = "This is the Expanded Control text in the Task Dialog.";
dlg.CollapsedControlText = "This is the content of the collapsed control text.";
dlg.ExpansionMode = TaskDialogExpandedInformationLocation.ExpandFooter;
dlg.FooterText = "This is the footer text.";
dlg.FooterIcon = TaskDialogStandardIcon.Information;
TaskDialogResult result = dlg.Show();

The output results in a single dialog that has two forms:

Image 10

Image 11

A task dialog can also contain other controls. In the following code snippet, we would create a task dialog and add two radio buttons, a command link, and a marquee control.

C#
TaskDialog dlg = new TaskDialog();
dlg.Caption = "Title";
dlg.Instruction = "Sample Task Dialog";

TaskDialogRadioButton radio1 = new TaskDialogRadioButton();
radio1.Name = "radio1";
radio1.Text = "One";
dlg.Controls.Add(radio1);

TaskDialogRadioButton radio2 = new TaskDialogRadioButton();
radio2.Name = "radio2";
radio2.Text = "Two";
dlg.Controls.Add(radio2);

TaskDialogCommandLink commandLink = new TaskDialogCommandLink();
commandLink.Name = "link1";
commandLink.ShowElevationIcon = true;
commandLink.Text = "Information";
commandLink.Instruction = "Sample Command Link";
dlg.Controls.Add(commandLink);

TaskDialogMarquee marquee = new TaskDialogMarquee();
marquee.Name = "marquee";
marquee.State = TaskDialogProgressBarState.Normal;
dlg.Controls.Add(marquee);

TaskDialogResult result = dlg.Show();

The output of the above code is:

Control Task Dialog

GUIVistaDialog Project

This project combines all the Vista dialogs shown in this article. It has a main AERO form as:

Vista Dialog

Note: To use the Vista library and Vista dialogs, you must add the following lines of code:

C#
using Microsoft.SDK.Samples.VistaBridge.Dialogs;
using Microsoft.SDK.Samples.VistaBridge.Library;

So, that is all to know for heading off with a Windows Vista based visually enhanced project. Signing off.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)