Thursday, October 18, 2012
Windows 8 SmartScreen
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
.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
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!
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
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.
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]Also you are creating bat file containing the following line:
VersionInfoVersion = 1.0.0.$WCREV$
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]Then you are building installer with the help of OurProgram_version.iss script. And the resulting file will have the version number you need.
VersionInfoVersion = 1.0.0.105
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.
[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.
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.
[Setup] ArchitecturesInstallIn64BitMode = x64This 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 = x64Other 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.
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: ignoreversionPlease 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.
[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.
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.