Thursday, October 18, 2012

Windows 8 SmartScreen

When you are downloading some application from Internet and starting to install it in Windows 8, it is being checked with the help of special utility called Windows Smart Screen. If application doesn't have digital signature and sometimes even if it has it, you may receive the following warning:

Windows protected your PC
Windows SmartScreen prevented an unrecognized app from starting. Running this app might put your PC at risk.

To continue installing you should click More Info link and then Run Anyway button.


The information about application is being sent to Microsoft servers by Windows SmartScreen for analysis if user can run the application without harm for his or her system or not. There are security concerns related to sending application details to Microsoft outlined here:

http://log.nadim.cc/?p=78

The Windows SmartScreen check is enabled by default but you may disable it through Control Panel -> System and Security->Action Center. 


Tuesday, September 25, 2012

.NET Framework in Windows 8

The only version included in Windows 8 by default is .NET Framework 4.5 which is new version of .NET Framework just appeared in 2012. The only version which you can install on Windows 8 machine is .NET Framework 3.5. What about earlier versions of .NET Framework and applications based on them?

.NET Framework 1.1 is considered fully deprecated in Windows 8, it can't be installed and applications with it can't be used any more - it should be OK since it is really deprecated long ago.

.NET Framework 2.0 and .NET Framework 3.0 is a different case. Since they are parts of .NET Framework 3.5, the applications which use them can be run successfully on Windows 8 but you should install .NET Framework 3.5 instead of 2.0 or 3.0. You can install .NET Framework through installer or you can enable it through Control Panel, more details are here:

http://msdn.microsoft.com/en-us/library/hh506443.aspx

Installers for .NET Framework 2.0 and 3.0 were removed from Microsoft site.

In one of our previous posts we described a function in Inno Setup installer which could check .NET Framework 3.0 presence on the machine, now it should be updated in such a way:
[CustomMessages]
en.dotnetmissing=Our program needs Microsoft .NET Framework 3.0. Would you like to download and install it now?
[Code]
function InitializeSetup(): Boolean;
var
    ErrorCode: Integer;
    netFrameWorkInstalled : Boolean;
    isInstalled: Cardinal;
begin
    result := true;
    isInstalled := 0;
    netFrameworkInstalled := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup',
  'InstallSuccess', isInstalled);
    if ((netFrameworkInstalled)  and (isInstalled <> 1)) then netFrameworkInstalled := false;   
    if netFrameworkInstalled = false then
    begin
        if (MsgBox(ExpandConstant('{cm:dotnetmissing}'),
            mbConfirmation, MB_YESNO) = idYes) then
        begin
          ShellExec('open',
          'http://www.microsoft.com/en-us/download/details.aspx?id=21',
          '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
        end;
        result := false;
    end;
end;
The only difference is that URL for downloading of .NET Framework should point to .NET Framework 3.5 now, not 3.0. 

Please note that registry key 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup' should not be changed since .NET 3.5 installer proceeds this key in the correct way also.


Friday, September 21, 2012

Range-based For Loops in Visual Studio 2012

C++ 11 added a feature for easy iteration over a list of elements which is called range-based for:
int simpleArray[5] = {1, 2, 3, 4, 5};
for (int x : simpleArray)
{
    cout << x;
}
This is similar to 'foreach' statement in other languages. GCC added support of this feature in version 4.6 and now Microsoft added support in Visual Studio 2012 and in Visual C++ 11.

It is possible to modify contents of container making loop variable a reference:
vector<double> v;
v.push_back(1.0);
v.push_back(1.5);
v.push_back(2.0);

for (double &y : v)
{
    y *= 2;
}
Range-based for loop will work automatically with array or with std::vector or other STL containers. You can also make your own data structures iterable in the new way, you can find exact requirements and example of such a class here:

http://www.cprogramming.com/c++11/c++11-ranged-for-loop.html

Friday, September 14, 2012

Ribbon is now available in WPF!

With .NET Framework 4.5 and Visual Studio 2012 standard Ribbon control is finally available for WPF applications. We don't need to search for 3d controls any more!

To use ribbon you need to add reference to System.Windows.Controls.Ribbon in your WPF application.

After that you should be able to write XAML code like that:
<Window x:Class="TestRibbon.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <Ribbon>
      <RibbonTab x:Name="Home" Header="Home">
        <RibbonButton x:Name="HomeButton" Label="Home"/>
      </RibbonTab>
      <RibbonTab x:Name="FTP" Header="FTP">
        <RibbonButton x:Name="UploadButton" Label="Upload"/>
        <RibbonButton x:Name="DownloadButton" Label="Download"/>
      </RibbonTab>
    </Ribbon>
  </Grid>
</Window>
This will allow you to see the simple ribbon. Set SmallImageSource and LargeImageSource properties to make your ribbon buttons look nice.




Tuesday, September 4, 2012

Qt 5 Beta Release News



Qt 5 Beta release is available since August 30, 2012. Final release is expected by November 2012. It is, of course, an important event for C++ developers and we can get much more details here: 


Being introduced in Qt 4.7 (September 2010) QML and Qt Quick will play major role in Qt 5 release. Qt Quick gives us a declarative way of building user interfaces and it is intended to be used widely for mobile devices. Declarative scripting language is called QML. 

A good thing is that they say it will be easy to make Qt 4 applications to work on Qt 5, no special efforts will be required for that.

Another good thing is that more features of current C++ standard (C++ 11) will be supported in Qt 5. You can read about some of the features here:


A little bit earlier (August 9, 2012) Digia signed an agreement with Nokia that it is Digia who is responsible for Qt activities now:


It is especially interesting that they are planning make Qt available on Android, iOS and Windows 8 platforms very soon.

Saturday, August 25, 2012

Inno Setup, Part 8. Creating custom wizard page.

Today we will describe a process of creating custom wizard page in program installer. Though Inno Setup suggests pages which will cover your needs in most of the cases, sometimes you will need to create your own page during installation process. Custom page can be created in [Code] section in InitializeWizard function:

[Code]
procedure InitializeWizard();
begin
  authentication_form_CreatePage(wpLicense);
end;

wpLicense argument means that our custom page will be displayed after standard license page during installation process. All standard wizard pages have their predefined IDs. For instance, welcome page have ID equal to wpWelcome. Now let’s look at the code which is creating custom page. First we need to define some variables which will be used:

var
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  ServerNameEdit: TEdit;
  WindowsRadioButton: TRadioButton;
  SqlRadioButton: TRadioButton;
  UserEdit: TEdit;
  PasswordEdit: TEdit;

And this is the function itself. In it you will need to create all the necessary controls like labels, buttons, etc.:

function authentication_form_CreatePage(PreviousPageId: Integer): Integer;
var
  Page: TWizardPage;
begin
  Page := CreateCustomPage(
    PreviousPageId,
    ExpandConstant('{cm:authentication_form_Caption}'),
    ExpandConstant('{cm:authentication_form_Description}')
  );

  Label1 := TLabel.Create(Page);
  with Label1 do
  begin
    Parent := Page.Surface;
    Caption := ExpandConstant('{cm:authentication_form_Label1_Caption0}');
    Left := ScaleX(16);
    Top := ScaleY(0);
    Width := ScaleX(84);
    Height := ScaleY(17);
  end;
 
  Label2 := TLabel.Create(Page);
  with Label2 do
  begin
    Parent := Page.Surface;
    Caption := ExpandConstant('{cm: authentication_form_Label2_Caption0}');
    Left := ScaleX(16);
    Top := ScaleY(56);
    Width := ScaleX(300);
    Height := ScaleY(17);
  end;
 
  Label3 := TLabel.Create(Page);
  with Label3 do
  begin
    Parent := Page.Surface;
    Caption := ExpandConstant('{cm: authentication_form_Label3_Caption0}');
    Left := ScaleX(56);
    Top := ScaleY(136);
    Width := ScaleX(70);
    Height := ScaleY(17);
  end;
 
  Label4 := TLabel.Create(Page);
  with Label4 do
  begin
    Parent := Page.Surface;
    Caption := ExpandConstant('{cm: authentication_form_Label4_Caption0}');
    Left := ScaleX(56);
    Top := ScaleY(168);
    Width := ScaleX(63);
    Height := ScaleY(17);
  end;
 
  ServerNameEdit := TEdit.Create(Page);
  with ServerNameEdit do
  begin
    Parent := Page.Surface;
    Left := ScaleX(16);
    Top := ScaleY(24);
    Width := ScaleX(257);
    Height := ScaleY(25);
    TabOrder := 0;
    Text := ExpandConstant('{cm: authentication_form_ServerNameEdit_Text0}');
  end;
 
  WindowsRadioButton := TRadioButton.Create(Page);
  with WindowsRadioButton do
  begin
    Parent := Page.Surface;
    Caption := ExpandConstant('{cm: authentication_form_WindowsRadioButton_Caption0}');
    Left := ScaleX(16);
    Top := ScaleY(88);
    Width := ScaleX(225);
    Height := ScaleY(17);
    Checked := True;
    TabOrder := 1;
    TabStop := True;
  end;
 
  SqlRadioButton := TRadioButton.Create(Page);
  with SqlRadioButton do
  begin
    Parent := Page.Surface;
    Caption := ExpandConstant('{cm: authentication_form_SqlRadioButton_Caption0}');
    Left := ScaleX(16);
    Top := ScaleY(112);
    Width := ScaleX(193);
    Height := ScaleY(17);
    TabOrder := 2;
  end;
 
  UserEdit := TEdit.Create(Page);
  with UserEdit do
  begin
    Parent := Page.Surface;
    Left := ScaleX(136);
    Top := ScaleY(136);
    Width := ScaleX(121);
    Height := ScaleY(25);
    TabOrder := 3;
    Text := ExpandConstant('{cm: authentication_form_UserEdit_Text0}');
  end;
 
  PasswordEdit := TEdit.Create(Page);
  with PasswordEdit do
  begin
    Parent := Page.Surface;
    Left := ScaleX(136);
    Top := ScaleY(168);
    Width := ScaleX(121);
    Height := ScaleY(25);
    TabOrder := 4;
    PasswordChar := '*';
    Text := ExpandConstant('{cm: authentication_form_PasswordEdit_Text0}');
  end;

  with Page do
  begin
    OnNextButtonClick := @authentication_form_NextButtonClick;
  end;

  Result := Page.ID;
end;

Finally we will need handler for Next button click:

function authentication_form_NextButtonClick(Page: TWizardPage): Boolean;
begin
  Result := True;
  if ServerNameEdit.Text <> ''   then
    begin
       if SqlRadioButton.Checked then
       begin
          if UserEdit.Text = ''  then
          begin
             MsgBox('You should enter user name', mbError, MB_OK);
             Result := False;
          end
          else
          begin
            if PasswordEdit.Text = '' then
            begin
               MsgBox('You should enter password', mbError, MB_OK);
               Result := False;
            end
          end
       end
    end
    else
    begin
    MsgBox('You should enter path to SQL Server Database', mbError, MB_OK);
    Result := False;
    end;
end;

The text labels and messages need to be defined in special section:

[CustomMessages]
authentication_form_Caption=SQL Server Database Setup
authentication_form_Description=Choose SQL Server database you will be using (ask your administrator about its parameters)
authentication_form_Label1_Caption0=Server Name:
authentication_form_Label2_Caption0=Enter Path to SQL Server (e.g. .\SQLEXPRESS; DEVSERVER)
authentication_form_Label3_Caption0=User name:
authentication_form_Label4_Caption0=Password:
authentication_form_ServerNameEdit_Text0=
authentication_form_WindowsRadioButton_Caption0=Use Windows Authentication
authentication_form_SqlRadioButton_Caption0=Use SQL Authentication
authentication_form_UserEdit_Text0=
authentication_form_PasswordEdit_Text0=

After such a long work you want to see probably what we will receive at the end? Such a window:

As you can see to receive this nice window you have to write a large amount of code and this is the case where some automated tool like ISTool can be helpful for you.

Sunday, March 25, 2012

Inno Setup, Part 7. Integrating Inno Setup with SVN.

It is convenient when installer gets its version number automatically. There are different systems of software versioning. For our builds we are using the following system:

major version . minor version . revision . build

First three numbers are set manually since they are being changed not very often. Last number build is taken from version control system, in our case it is SVN.
Let’s discuss what we need to do for automatic versioning of Inno Setup installers.
First you need to create installer script for your program as usual, let’s call it OurProgram.iss. In its Setup section there is an additional line:
[Setup]
VersionInfoVersion = 1.0.0.$WCREV$
Also you are creating bat file containing the following line:

SubWCRev.exe . OurProgram.iss OurProgram_version.iss

When you need to make the installer, you are launching this bat file first. It will generate OurProgram_version.iss Inno Setup script. SubWCRev.exe program which is a part of SVN installation will substitute $WCREV$ with current build number. So in OurProgram_version.iss you will find the line like:
[Setup]
VersionInfoVersion = 1.0.0.105
Then you are building installer with the help of OurProgram_version.iss script. And the resulting file will have the version number you need.
The similar method for automatic versioning can be used for C++/C# exe files, we will talk about this in one of the next posts.

Saturday, March 10, 2012

Inno Setup, Part 6. Creating file associations during installation.

During installation you may need to create file association, i.e. make some file extension being connected with your program. In this case Windows will receive information that files with this extension should be always opened with your program. In Windows this is done with the help of registry records. Here is the code:
[Registry]
Root: HKCR; Subkey: ".ext"; ValueType: string; ValueName: ""; ValueData: "OurProgramFile"; Flags: uninsdeletevalue

Root: HKCR; Subkey: "OurProgramFile"; ValueType: string; ValueName: ""; ValueData: "Our Program File"; Flags: uninsdeletekey

Root: HKCR; Subkey: "OurProgramFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\OurProgram.exe,0"

Root: HKCR; Subkey: "OurProgramFile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\OurProgram.exe"" ""%1"""
In the code above we associated files with file extension .ext with OurProgram.exe which was put into {app} folder by installer. Also we set description and default icon for all the files with given file extension.
If our program is uninstalled in future, this registry records will be automatically deleted by Inno Setup.

Sunday, March 4, 2012

Inno Setup, Part 5. Checking .NET Framework versions.

In installers for programs which are using .NET Framework it is necessary to perform a check before installation if .NET Framework is installed on the machine. Such checks are not difficult and, actually they are checks of some keys in registry. These registry keys depend on .NET Framework version.

If .NET Framework is not installed, you need to install it. We prefer opening browser with appropriate URL in order user can download and install .NET Framework. Another way is to include .NET Framework installer into the main installer of the program, it may be convenient but of course this increases size of installer significantly.

Now let’s turn to the code. Here is the check for .NET Framework 3.0:
[CustomMessages]
en.dotnetmissing=Our program needs Microsoft .NET Framework 3.0. Would you like to download and install it now?
[Code]
function InitializeSetup(): Boolean;
var
    ErrorCode: Integer;
    netFrameWorkInstalled : Boolean;
    isInstalled: Cardinal;
begin
    result := true;
    isInstalled := 0;
    netFrameworkInstalled := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup',
  'InstallSuccess', isInstalled);
    if ((netFrameworkInstalled)  and (isInstalled <> 1)) then netFrameworkInstalled := false;   
    if netFrameworkInstalled = false then
    begin
        if (MsgBox(ExpandConstant('{cm:dotnetmissing}'),
            mbConfirmation, MB_YESNO) = idYes) then
        begin
          ShellExec('open',
          'http://www.microsoft.com/downloads/details.aspx?familyid=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en',
          '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
        end;
        result := false;
    end;
end;
Here is the same code for .NET Framework 4 Client Profile.
[CustomMessages]
dotnetmissing=Our program needs Microsoft .NET Framework 4.0 Client Profile. Would you like to download and install it now?
[Code]
function InitializeSetup(): Boolean;
var
    ErrorCode: Integer;
    netFrameWorkInstalled : Boolean;
    isInstalled: Cardinal;
begin
    result := true;

  isInstalled := 0;
    netFrameworkInstalled := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\client',
  'Install', isInstalled);
    if ((netFrameworkInstalled)  and (isInstalled <> 1)) then netFrameworkInstalled := false;

    if netFrameworkInstalled = false then
    begin
        if (MsgBox(ExpandConstant('{cm:dotnetmissing}'),
            mbConfirmation, MB_YESNO) = idYes) then
        begin
          ShellExec('open',
          'http://download.microsoft.com/download/7/B/6/7B629E05-399A-4A92-B5BC-484C74B5124B/dotNetFx40_Client_setup.exe',
          '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
        end;
        result := false;
    end;
end; 
So comparing functions for two versions of .NET Framework we notice that they are differing only in messages, download URLs and registry keys. If necessary, you can simply make general function for several versions of .NET Framework.

Update: for example of general function which checks different versions of .NET Framework you can look at this Q & A at stackoverflow.com.

Saturday, February 25, 2012

Inno Setup, Part 4. x64 vs. x86.

By default Inno Setup always installs your application in 32-bit mode. But if your application is compiled to 64-bit binaries (at least, partly) you will, probably, want to use 64-bit mode. First thing you need to do is to specify ArchitecturesInstallIn64BitMode in [Setup] section:
[Setup]
ArchitecturesInstallIn64BitMode = x64
This means that under 64-bit processor architecture 64-bit mode will be used. You can specify Itanium architecture (ArchitecturesInstallIn64BitMode=ia64) if necessary.
Now imagine you need to use one file for 32-bit mode and another file for 64-bit mode. You can do it in the following way:
[Files]
Source: "OurProgram\Release\shellextension.dll"; DestDir: "{app}"; Flags: regserver ignoreversion; Check: not Is64BitInstallMode;
Source: "OurProgram\x64\Release\shellextension.dll"; DestDir: "{app}"; Flags: regserver ignoreversion; Check: Is64BitInstallMode; 
In the script above we specified to use 32-bit version of shell extension dll in 32-bit mode and 64-bit version of shell extension in 64-bit mode. Other files can be the same for 32-bit and 64-bit modes or different.
Also you can create completely different installers for different architectures. For example, to create installer specially for 64-bit architecture you need to specify:
[Setup]
ArchitecturesAllowed = x64
Other possible values are x86 or ia64. You can specify several values separated by spaces.

Wednesday, February 15, 2012

Inno Setup, Part 3. Creating configuration files during installation.

Often during program installation we need to create configuration file. In this article we will create a very simple configuration file in .ini style.
It will be created with the help of simple procedure written with the help of Inno Setup script:
[Code]
procedure CreateConfig();
var Strings : TArrayOfString;
begin
  SetArrayLength(Strings, 2);
  Strings[0] := 'InstallPath=' + ExpandConstant('{app}');
  Strings[1] := 'Language=' + ExpandConstant('{language}');

  SaveStringsToFile(ExpandConstant('{commonappdata}') +
    '\OurProgram\OurProgram.config', Strings, False);
end;
This procedure creates an array of strings which consists from two strings and contains information about application folder where the program is installed and language which was selected during installation. Later this information can be used in program, for instance, we can display user interface corresponding to the selected language. Of course, number of strings can be larger than 2.
When the procedure itself is ready, all what we need is to call it. We may call it in the [Files] section:
[Files]
Source: "OurProgram\bin\Release\OurProgram.exe"; DestDir: "{app}"; Components: Main; AfterInstall: CreateConfig; Flags: ignoreversion
Please note call of CreateConfig procedure after this file will be copied.
Our simple example is finished. You can check its work. In one of the next articles when we will discuss making custom windows in Inno Setup, we will describe how to save information which user types in one of the wizard windows in the configuration file, too.

Monday, February 13, 2012

Inno Setup, Part 2. Running files during installation and uninstallation.

One of the common tasks during installation is to copy file to some temp directory, run it and delete after that. For example, it can be some script. In our example we are creating database necessary for our application work.  First part is copying the file to temp directory, this is done in [Files] section:
[Files]
Source: ..\SQL\CreateDatabase.bat; DestDir: {tmp}; Flags: deleteafterinstall;
Note deleteafterinstall flag, it indicates the file will be deleted at the end of installation when it won’t be necessary any longer.
The second part is to launch this file at the end of installation process (of course, this takes place before deleting of the files, Inno Setup handles this correctly automatically):
[Run]
Filename: {tmp}\CreateDatabase.bat; Flags: runhidden;
Note runhidden flag here, it indicates that this operation won’t be visible for users of your installer. This flag can be removed if you prefer to leave this operation noticeable.
When your application is uninstalled, you may need also to launch a file. In our example, we need to delete database.
[UninstallRun]
Filename: {app}\Scripts\DeleteDatabase.bat; Flags: runhidden;
We are using the same flag runhidden, but now we can’t use temporary directory, we need to run from application directory or from some folder like commonappdata. The file needed for deleting database was created during process of installation in [Files] section:
[Files]
Source: ..\SQL\DeleteDatabase.bat; DestDir: {app}\Scripts;

Tuesday, February 7, 2012

Inno Setup, Part 1. Introduction.

For almost each software product we need to create an installer at some stage of development. For Windows platform there is a great solution which we are using in our own products. It is Inno Setup, a free installer which supports all versions of Windows. We believe it is even better than its commercial analogues.
http://www.jrsoftware.org/isinfo.php

Also you can use a good visual editor for Inno Setup scripts - ISTool:
http://sourceforge.net/projects/istool/

We are not using it currently but it can be still helpful for you.

Inno Setup supports the majority of things you need while creating installers and the aim of this series of articles is to describe how to do some common things with Inno Setup. As far as we have made many installers using Inno Setup, we’ve figured out some typical problems and their solutions. Now we want to share them with you and provide some pieces of code which can be helpful when you will be solving some similar problems. These things will include: creating configuration files during installation, checking .NET Framework versions before installation, creating custom windows for installation wizard and many others.

Our aim is NOT rewriting of Inno Setup documentation which is enough detailed for you to understand how to do basic tasks like copying files to appropriate folders while installation.

Our samples will be taken from real projects and are 100% working.