diff --git a/.gitignore b/.gitignore index de7dc55..4842e6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vs SmartHDD/bin SmartHDD/obj +Installer/bin \ No newline at end of file diff --git a/Installer/innodependencyinstaller LICENSE.md b/Installer/innodependencyinstaller LICENSE.md new file mode 100644 index 0000000..77325dc --- /dev/null +++ b/Installer/innodependencyinstaller LICENSE.md @@ -0,0 +1,210 @@ +The Code Project Open License (CPOL) 1.02 + +Preamble + +This License governs Your use of the Work. This License is intended to allow +developers to use the Source Code and Executable Files provided as part of the +Work in any application in any form. + +The main points subject to the terms of the License are: + + * Source Code and Executable Files can be used in commercial applications; + * Source Code and Executable Files can be redistributed; and + * Source Code can be modified to create derivative works. + * No claim of suitability, guarantee, or any warranty whatsoever is provided. + The software is provided "as-is". + * The Article accompanying the Work may not be distributed or republished + without the Author's consent + +This License is entered between You, the individual or other entity reading or +otherwise making use of the Work licensed pursuant to this License and the +individual or other entity which offers the Work under the terms of this License +("Author"). + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CODE PROJECT +OPEN LICENSE ("LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER +APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE +OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HEREIN, YOU ACCEPT AND AGREE TO +BE BOUND BY THE TERMS OF THIS LICENSE. THE AUTHOR GRANTS YOU THE RIGHTS CONTAINED +HEREIN IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. IF YOU +DO NOT AGREE TO ACCEPT AND BE BOUND BY THE TERMS OF THIS LICENSE, YOU CANNOT +MAKE ANY USE OF THE WORK. + + 1. Definitions. + 1. "Articles" means, collectively, all articles written by Author which + describes how the Source Code and Executable Files for the Work may + be used by a user. + 2. "Author" means the individual or entity that offers the Work under + the terms of this License. + 3. "Derivative Work" means a work based upon the Work or upon the Work + and other pre-existing works. + 4. "Executable Files" refer to the executables, binary files, configu- + ration and any required data files included in the Work. + 5. "Publisher" means the provider of the website, magazine, CD-ROM, + DVD or other medium from or by which the Work is obtained by You. + 6. "Source Code" refers to the collection of source code and configu- + ration files used to create the Executable Files. + 7. "Standard Version" refers to such a Work if it has not been modified, + or has been modified in accordance with the consent of the Author, + such consent being in the full discretion of the Author. + 8. "Work" refers to the collection of files distributed by the Publisher, + including the Source Code, Executable Files, binaries, data files, + documentation, whitepapers and the Articles. + 9. "You" is you, an individual or entity wishing to use the Work and + exercise your rights under this License. + + 2. Fair Use/Fair Use Rights. Nothing in this License is intended to reduce, + limit, or restrict any rights arising from fair use, fair dealing, first + sale or other limitations on the exclusive rights of the copyright owner + under copyright law or other applicable laws. + + 3. License Grant. Subject to the terms and conditions of this License, the + Author hereby grants You a worldwide, royalty-free, non-exclusive, perpe- + tual (for the duration of the applicable copyright) license to exercise + the rights in the Work as stated below: + 1. You may use the standard version of the Source Code or Executable + Files in Your own applications. + 2. You may apply bug fixes, portability fixes and other modifications + obtained from the Public Domain or from the Author. A Work modified + in such a way shall still be considered the standard version and + will be subject to this License. + 3. You may otherwise modify Your copy of this Work (excluding the + Articles) in any way to create a Derivative Work, provided that + You insert a prominent notice in each changed file stating how, + when and where You changed that file. + 4. You may distribute the standard version of the Executable Files + and Source Code or Derivative Work in aggregate with other (pos- + sibly commercial) programs as part of a larger (possibly commercial) + software distribution. + 5. The Articles discussing the Work published in any form by the + author may not be distributed or republished without the Author's + consent. The author retains copyright to any such Articles. You may + use the Executable Files and Source Code pursuant to this License + but you may not repost or republish or otherwise distribute or make + available the Articles, without the prior written consent of the + Author. + Any subroutines or modules supplied by You and linked into the Source + Code or Executable Files this Work shall not be considered part of this + Work and will not be subject to the terms of this License. + + 4. Patent License. Subject to the terms and conditions of this License, + each Author hereby grants to You a perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable (except as stated in this section) + patent license to make, have made, use, import, and otherwise transfer + the Work. + + 5. Restrictions. The license granted in Section 3 above is expressly made + subject to and limited by the following restrictions: + 1. You agree not to remove any of the original copyright, patent, + trademark, and attribution notices and associated disclaimers that + may appear in the Source Code or Executable Files. + 2. You agree not to advertise or in any way imply that this Work is a + product of Your own. + 3. The name of the Author may not be used to endorse or promote pro- + ducts derived from the Work without the prior written consent of + the Author. + 4. You agree not to sell, lease, or rent any part of the Work. This + does not restrict you from including the Work or any part of the + Work inside a larger software distribution that itself is being + sold. The Work by itself, though, cannot be sold, leased or rented. + 5. You may distribute the Executable Files and Source Code only under + the terms of this License, and You must include a copy of, or the + Uniform Resource Identifier for, this License with every copy of + the Executable Files or Source Code You distribute and ensure that + anyone receiving such Executable Files and Source Code agrees that + the terms of this License apply to such Executable Files and/or + Source Code. You may not offer or impose any terms on the Work that + alter or restrict the terms of this License or the recipients' + exercise of the rights granted hereunder. You may not sublicense + the Work. You must keep intact all notices that refer to this + License and to the disclaimer of warranties. You may not distribute + the Executable Files or Source Code with any technological measures + that control access or use of the Work in a manner inconsistent with + the terms of this License. + 6. You agree not to use the Work for illegal, immoral or improper + purposes, or on pages containing illegal, immoral or improper + material. The Work is subject to applicable export laws. You agree + to comply with all such laws and regulations that may apply to the + Work after Your receipt of the Work. + + 6. Representations, Warranties and Disclaimer. THIS WORK IS PROVIDED "AS + IS", "WHERE IS" AND "AS AVAILABLE", WITHOUT ANY EXPRESS OR IMPLIED + WARRANTIES OR CONDITIONS OR GUARANTEES. YOU, THE USER, ASSUME ALL RISK + IN ITS USE, INCLUDING COPYRIGHT INFRINGEMENT, PATENT INFRINGEMENT, SUIT- + ABILITY, ETC. AUTHOR EXPRESSLY DISCLAIMS ALL EXPRESS, IMPLIED OR STATU- + TORY WARRANTIES OR CONDITIONS, INCLUDING WITHOUT LIMITATION, WARRANTIES + OR CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY OR FITNESS FOR A + PARTICULAR PURPOSE, OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT, OR THAT + THE WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, BUG-FREE OR FREE OF + VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE + WORK OR DERIVATIVE WORKS. + + 7. Indemnity. You agree to defend, indemnify and hold harmless the Author + and the Publisher from and against any claims, suits, losses, damages, + liabilities, costs, and expenses (including reasonable legal or attorneys' + fees) resulting from or relating to any use of the Work by You. + + 8. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE + LAW, IN NO EVENT WILL THE AUTHOR OR THE PUBLISHER BE LIABLE TO YOU ON + ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR + EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK OR + OTHERWISE, EVEN IF THE AUTHOR OR THE PUBLISHER HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + 9. Termination. + 1. This License and the rights granted hereunder will terminate auto- + matically upon any breach by You of any term of this License. Indi- + viduals or entities who have received Derivative Works from You + under this License, however, will not have their licenses terminated + provided such individuals or entities remain in full compliance + with those licenses. Sections 1, 2, 6, 7, 8, 9, 10 and 11 will + survive any termination of this License. + 2. If You bring a copyright, trademark, patent or any other infringe- + ment claim against any contributor over infringements You claim are + made by the Work, your License from such contributor to the Work + ends automatically. + 3. Subject to the above terms and conditions, this License is perpe- + tual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, the Author reserves the right to release + the Work under different license terms or to stop distributing the + Work at any time; provided, however that any such election will not + serve to withdraw this License (or any other license that has been, + or is required to be, granted under the terms of this License), and + this License will continue in full force and effect unless termi- + nated as stated above. + + 10. Publisher. The parties hereby confirm that the Publisher shall not, + under any circumstances, be responsible for and shall not have any lia- + bility in respect of the subject matter of this License. The Publisher + makes no warranty whatsoever in connection with the Work and shall not + be liable to You or any party on any legal theory for any damages what- + soever, including without limitation any general, special, incidental or + consequential damages arising in connection to this license. The Pub- + lisher reserves the right to cease making the Work available to You at + any time without notice + + 11. Miscellaneous + 1. This License shall be governed by the laws of the location of the + head office of the Author or if the Author is an individual, the + laws of location of the principal place of residence of the Author. + 2. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability + of the remainder of the terms of this License, and without further + action by the parties to this License, such provision shall be + reformed to the minimum extent necessary to make such provision + valid and enforceable. + 3. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in + writing and signed by the party to be charged with such waiver or + consent. + 4. This License constitutes the entire agreement between the parties + with respect to the Work licensed herein. There are no understan- + dings, agreements or representations with respect to the Work not + specified herein. The Author shall not be bound by any additional + provisions that may appear in any communication from You. This + License may not be modified without the mutual written agreement + of the Author and You. diff --git a/Installer/innodependencyinstaller README.md b/Installer/innodependencyinstaller README.md new file mode 100644 index 0000000..bca518c --- /dev/null +++ b/Installer/innodependencyinstaller README.md @@ -0,0 +1,3 @@ +This installer uses 3rd party components from https://github.com/stfx/innodependencyinstaller to automatically download and install .NET frameworks. + +See **'innodependencyinstaller LICENSE.md'** for the license of innodependencyinstaller. \ No newline at end of file diff --git a/Installer/scripts/code.pas b/Installer/scripts/code.pas new file mode 100644 index 0000000..bf437e8 --- /dev/null +++ b/Installer/scripts/code.pas @@ -0,0 +1,313 @@ +{ + --- TYPES AND VARIABLES --- +} +type + TProduct = record + File: String; + Title: String; + Parameters: String; + ForceSuccess : boolean; + InstallClean : boolean; + MustRebootAfter : boolean; + end; + + InstallResult = (InstallSuccessful, InstallRebootRequired, InstallError); + +var + installMemo, downloadMemo, downloadMessage: string; + products: array of TProduct; + delayedReboot, isForcedX86: boolean; + DependencyPage: TOutputProgressWizardPage; + +procedure AddProduct(filename, parameters, title, size, url: string; forceSuccess, installClean, mustRebootAfter : boolean); +{ + Adds a product to the list of products to download. + Parameters: + filename: the file name under which to save the file + parameters: the parameters with which to run the file + title: the product title + size: the file size + url: the URL to download from + forceSuccess: whether to continue in case of setup failure + installClean: whether the product needs a reboot before installing + mustRebootAfter: whether the product needs a reboot after installing +} +var + path: string; + i: Integer; +begin + installMemo := installMemo + '%1' + title + #13; + + path := ExpandConstant('{src}{\}') + CustomMessage('DependenciesDir') + '\' + filename; + if not FileExists(path) then begin + path := ExpandConstant('{tmp}{\}') + filename; + + if not FileExists(path) then begin + isxdl_AddFile(url, path); + + downloadMemo := downloadMemo + '%1' + title + #13; + downloadMessage := downloadMessage + ' ' + title + ' (' + size + ')' + #13; + end; + end; + + i := GetArrayLength(products); + SetArrayLength(products, i + 1); + products[i].File := path; + products[i].Title := title; + products[i].Parameters := parameters; + products[i].ForceSuccess := forceSuccess; + products[i].InstallClean := installClean; + products[i].MustRebootAfter := mustRebootAfter; +end; + +function SmartExec(product : TProduct; var resultcode : Integer): boolean; +{ + Executes a product and returns the exit code. + Parameters: + product: the product to install + resultcode: the exit code +} +begin + if (LowerCase(Copy(product.File, Length(product.File) - 2, 3)) = 'exe') then begin + Result := Exec(product.File, product.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, resultcode); + end else begin + Result := ShellExec('', product.File, product.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, resultcode); + end; +end; + +function PendingReboot: boolean; +{ + Checks whether the machine has a pending reboot. +} +var names: String; +begin + if (RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'PendingFileRenameOperations', names)) then begin + Result := true; + end else if ((RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'SetupExecute', names)) and (names <> '')) then begin + Result := true; + end else begin + Result := false; + end; +end; + +function InstallProducts: InstallResult; +{ + Installs the downloaded products +} +var + resultCode, i, productCount, finishCount: Integer; +begin + Result := InstallSuccessful; + productCount := GetArrayLength(products); + + if productCount > 0 then begin + DependencyPage := CreateOutputProgressPage(CustomMessage('depinstall_title'), CustomMessage('depinstall_description')); + DependencyPage.Show; + + for i := 0 to productCount - 1 do begin + if (products[i].InstallClean and (delayedReboot or PendingReboot())) then begin + Result := InstallRebootRequired; + break; + end; + + DependencyPage.SetText(FmtMessage(CustomMessage('depinstall_status'), [products[i].Title]), ''); + DependencyPage.SetProgress(i, productCount); + + if SmartExec(products[i], resultCode) then begin + //setup executed; resultCode contains the exit code + if (products[i].MustRebootAfter) then begin + //delay reboot after install if we installed the last dependency anyways + if (i = productCount - 1) then begin + delayedReboot := true; + end else begin + Result := InstallRebootRequired; + end; + break; + end else if (resultCode = 0) or (products[i].ForceSuccess) then begin + finishCount := finishCount + 1; + end else if (resultCode = 3010) then begin + //Windows Installer resultCode 3010: ERROR_SUCCESS_REBOOT_REQUIRED + delayedReboot := true; + finishCount := finishCount + 1; + end else begin + Result := InstallError; + break; + end; + end else begin + Result := InstallError; + break; + end; + end; + + //only leave not installed products for error message + for i := 0 to productCount - finishCount - 1 do begin + products[i] := products[i+finishCount]; + end; + SetArrayLength(products, productCount - finishCount); + + DependencyPage.Hide; + end; +end; + +{ + -------------------- + INNO EVENT FUNCTIONS + -------------------- +} + +function PrepareToInstall(var NeedsRestart: boolean): String; +{ + Before the "preparing to install" page. + See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents +} +var + i: Integer; + s: string; +begin + delayedReboot := false; + + case InstallProducts() of + InstallError: begin + s := CustomMessage('depinstall_error'); + + for i := 0 to GetArrayLength(products) - 1 do begin + s := s + #13 + ' ' + products[i].Title; + end; + + Result := s; + end; + InstallRebootRequired: begin + Result := products[0].Title; + NeedsRestart := true; + + //write into the registry that the installer needs to be executed again after restart + RegWriteStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'InstallBootstrap', ExpandConstant('{srcexe}')); + end; + end; +end; + +function NeedRestart : boolean; +{ + Checks whether a restart is needed at the end of install + See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents +} +begin + Result := delayedReboot; +end; + +function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String; +{ + Just before the "ready" page. + See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents +} +var + s: string; +begin + if downloadMemo <> '' then + s := s + CustomMessage('depdownload_memo_title') + ':' + NewLine + FmtMessage(downloadMemo, [Space]) + NewLine; + if installMemo <> '' then + s := s + CustomMessage('depinstall_memo_title') + ':' + NewLine + FmtMessage(installMemo, [Space]) + NewLine; + + s := s + MemoDirInfo + NewLine + NewLine + MemoGroupInfo + + if MemoTasksInfo <> '' then + s := s + NewLine + NewLine + MemoTasksInfo; + + Result := s +end; + +function NextButtonClick(CurPageID: Integer): boolean; +{ + At each "next" button click + See: http://www.jrsoftware.org/ishelp/index.php?topic=scriptevents +} +begin + Result := true; + + if CurPageID = wpReady then begin + if downloadMemo <> '' then begin + //change isxdl language only if it is not english because isxdl default language is already english + if (ActiveLanguage() <> 'en') then begin + ExtractTemporaryFile(CustomMessage('isxdl_langfile')); + isxdl_SetOption('language', ExpandConstant('{tmp}{\}') + CustomMessage('isxdl_langfile')); + end; + //isxdl_SetOption('title', FmtMessage(SetupMessage(msgSetupWindowTitle), [CustomMessage('appname')])); + + if SuppressibleMsgBox(FmtMessage(CustomMessage('depdownload_msg'), [downloadMessage]), mbConfirmation, MB_YESNO, IDYES) = IDNO then + Result := false + else if isxdl_DownloadFiles(StrToInt(ExpandConstant('{wizardhwnd}'))) = 0 then + Result := false; + end; + end; +end; + +{ + ----------------------------- + ARCHITECTURE HELPER FUNCTIONS + ----------------------------- +} + +function IsX86: boolean; +{ + Gets whether the computer is x86 (32 bits). +} +begin + Result := isForcedX86 or (ProcessorArchitecture = paX86) or (ProcessorArchitecture = paUnknown); +end; + +function IsX64: boolean; +{ + Gets whether the computer is x64 (64 bits). +} +begin + Result := (not isForcedX86) and Is64BitInstallMode and (ProcessorArchitecture = paX64); +end; + +function IsIA64: boolean; +{ + Gets whether the computer is IA64 (Itanium 64 bits). +} +begin + Result := (not isForcedX86) and Is64BitInstallMode and (ProcessorArchitecture = paIA64); +end; + +function GetString(x86, x64, ia64: String): String; +{ + Gets a string depending on the computer architecture. + Parameters: + x86: the string if the computer is x86 + x64: the string if the computer is x64 + ia64: the string if the computer is IA64 +} +begin + if IsX64() and (x64 <> '') then begin + Result := x64; + end else if IsIA64() and (ia64 <> '') then begin + Result := ia64; + end else begin + Result := x86; + end; +end; + +function GetArchitectureString(): String; +{ + Gets the "standard" architecture suffix string. + Returns either _x64, _ia64 or nothing. +} +begin + if IsX64() then begin + Result := '_x64'; + end else if IsIA64() then begin + Result := '_ia64'; + end else begin + Result := ''; + end; +end; + +procedure SetForceX86(value: boolean); +{ + Forces the setup to use X86 products +} +begin + isForcedX86 := value; +end; diff --git a/Installer/scripts/isxdl/english.ini b/Installer/scripts/isxdl/english.ini new file mode 100644 index 0000000..55b2878 --- /dev/null +++ b/Installer/scripts/isxdl/english.ini @@ -0,0 +1,49 @@ +[strings] +; General +100=File download +101=Do you want to cancel the download? +102=%1 (%2 of %3) +103=%1 KB +104=%1 KB of %2 KB (%3%) + +; Status information +110=Getting file information... +111=Redirecting to %1 +112=Sending request... +113=Resolving %1 +114=Connected to %1 +115=Receiving... +116=Connecting to %1 + +; Error messages +120=Error connecting to the internet.\n\n%1 +121=Error opening %1.\n\nThe server returned status code %2. +122=Error reading URL.\n\n%1 +123=Error writing file %1.\n\n%2 +124=Error opening file %1.\n\n%2 +125='%1' is an invalid URL. +126=Error opening %1.\n\n%2 +127=Error sending request.\n\n%1 +128=Unsupported protocol. Only HTTP and FTP protocols are supported. +129=Failed to connect to %1.\n\n%2 +130=Failed to query status code.\n\n%1 +131=Error requesting file.\n\n%1 + +; Other +144=About... +146=Download +147=Setup is now downloading additional files to your computer. + +; labels +160=File: +161=Speed: +162=Status: +163=Elapsed Time: +164=Remaining Time: +165=Current File: +166=Overall Progress: +167=Cancel +168=OK +169=User Name and Password +170=User Name: +171=Password: diff --git a/Installer/scripts/isxdl/isxdl.dll b/Installer/scripts/isxdl/isxdl.dll new file mode 100644 index 0000000..d227bca Binary files /dev/null and b/Installer/scripts/isxdl/isxdl.dll differ diff --git a/Installer/scripts/isxdl/isxdl.iss b/Installer/scripts/isxdl/isxdl.iss new file mode 100644 index 0000000..18e653a --- /dev/null +++ b/Installer/scripts/isxdl/isxdl.iss @@ -0,0 +1,14 @@ +[Files] +Source: "scripts\isxdl\isxdl.dll"; Flags: dontcopy + +[Code] +procedure isxdl_AddFile(URL, Filename: PAnsiChar); +external 'isxdl_AddFile@files:isxdl.dll stdcall'; + +function isxdl_DownloadFiles(hWnd: Integer): Integer; +external 'isxdl_DownloadFiles@files:isxdl.dll stdcall'; + +function isxdl_SetOption(Option, Value: PAnsiChar): Integer; +external 'isxdl_SetOption@files:isxdl.dll stdcall'; + +[Setup] diff --git a/Installer/scripts/products.iss b/Installer/scripts/products.iss new file mode 100644 index 0000000..bfca177 --- /dev/null +++ b/Installer/scripts/products.iss @@ -0,0 +1,27 @@ +#include "isxdl\isxdl.iss" + +[CustomMessages] +DependenciesDir=MyProgramDependencies + +en.depdownload_msg=The following applications are required before setup can continue:%n%n%1%nDownload and install now? + +en.depdownload_memo_title=Download dependencies + +en.depinstall_memo_title=Install dependencies + +en.depinstall_title=Installing dependencies + +en.depinstall_description=Please wait while Setup installs dependencies on your computer. + +en.depinstall_status=Installing %1... + +en.depinstall_missing=%1 must be installed before setup can continue. Please install %1 and run Setup again. + +en.depinstall_error=An error occured while installing the dependencies. Please restart the computer and run the setup again or install the following dependencies manually:%n + +en.isxdl_langfile= + +[Code] +#include "code.pas" + +[Setup] diff --git a/Installer/scripts/products/dotnetfx46.iss b/Installer/scripts/products/dotnetfx46.iss new file mode 100644 index 0000000..856a9a5 --- /dev/null +++ b/Installer/scripts/products/dotnetfx46.iss @@ -0,0 +1,28 @@ +; requires Windows 10, Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2 +; WARNING: express setup (downloads and installs the components depending on your OS) if you want to deploy it on cd or network download the full bootsrapper on website below +; https://www.microsoft.com/en-US/download/details.aspx?id=49982 + +[CustomMessages] +dotnetfx46_title=.NET Framework 4.6.1 + +dotnetfx46_size=1 MB - 65 MB + +;http://www.microsoft.com/globaldev/reference/lcid-all.mspx +en.dotnetfx46_lcid= + +[Code] +const + dotnetfx461_url = 'http://download.microsoft.com/download/3/5/9/35980F81-60F4-4DE3-88FC-8F962B97253B/NDP461-KB3102438-Web.exe'; + +procedure dotnetfx46(minVersion: integer); +begin + if (not netfxinstalled(NetFx4x, '') or (netfxspversion(NetFx4x, '') < minVersion)) then + AddProduct('dotnetfx46.exe', + CustomMessage('dotnetfx46_lcid') + ' /passive /norestart', + CustomMessage('dotnetfx46_title'), + CustomMessage('dotnetfx46_size'), + dotnetfx461_url, + false, false, false); +end; + +[Setup] diff --git a/Installer/scripts/products/dotnetfxversion.iss b/Installer/scripts/products/dotnetfxversion.iss new file mode 100644 index 0000000..c828867 --- /dev/null +++ b/Installer/scripts/products/dotnetfxversion.iss @@ -0,0 +1,94 @@ +[Code] +type + NetFXType = (NetFx10, NetFx11, NetFx20, NetFx30, NetFx35, NetFx40Client, NetFx40Full, NetFx4x); + +const + netfx11plus_reg = 'Software\Microsoft\NET Framework Setup\NDP\'; + +function netfxinstalled(version: NetFXType; lcid: string): boolean; +var + regVersion: cardinal; + regVersionString: string; +begin + if (lcid <> '') then + lcid := '\' + lcid; + + if (version = NetFx10) then begin + RegQueryStringValue(HKLM, 'Software\Microsoft\.NETFramework\Policy\v1.0\3705', 'Install', regVersionString); + Result := regVersionString <> ''; + end else begin + case version of + NetFx11: + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v1.1.4322' + lcid, 'Install', regVersion); + NetFx20: + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v2.0.50727' + lcid, 'Install', regVersion); + NetFx30: + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.0\Setup' + lcid, 'InstallSuccess', regVersion); + NetFx35: + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.5' + lcid, 'Install', regVersion); + NetFx40Client: + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Client' + lcid, 'Install', regVersion); + NetFx40Full: + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Install', regVersion); + NetFx4x: + begin + RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Release', regVersion); + Result := (regVersion >= 378389); // 4.5.0+ + Exit; + end; + end; + Result := (regVersion <> 0); + end; +end; + +function netfxspversion(version: NetFXType; lcid: string): integer; +var + regVersion: cardinal; +begin + if (lcid <> '') then + lcid := '\' + lcid; + + case version of + NetFx10: + //not supported + regVersion := -1; + NetFx11: + if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v1.1.4322' + lcid, 'SP', regVersion)) then + regVersion := -1; + NetFx20: + if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v2.0.50727' + lcid, 'SP', regVersion)) then + regVersion := -1; + NetFx30: + if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.0' + lcid, 'SP', regVersion)) then + regVersion := -1; + NetFx35: + if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.5' + lcid, 'SP', regVersion)) then + regVersion := -1; + NetFx40Client: + if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Client' + lcid, 'Servicing', regVersion)) then + regVersion := -1; + NetFx40Full: + if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Servicing', regVersion)) then + regVersion := -1; + NetFx4x: + if (RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Release', regVersion)) then begin + if (regVersion >= 394747) then + regVersion := 62 // 4.6.2+ + else if (regVersion >= 394254) then + regVersion := 61 // 4.6.1+ + else if (regVersion >= 393295) then + regVersion := 60 // 4.6+ + else if (regVersion >= 379893) then + regVersion := 52 // 4.5.2+ + else if (regVersion >= 378675) then + regVersion := 51 // 4.5.1+ + else if (regVersion >= 378389) then + regVersion := 50 // 4.5.0+ + else + regVersion := -1; + end; + end; + Result := regVersion; +end; + +[Setup] diff --git a/Installer/scripts/products/fileversion.iss b/Installer/scripts/products/fileversion.iss new file mode 100644 index 0000000..b5570c5 --- /dev/null +++ b/Installer/scripts/products/fileversion.iss @@ -0,0 +1,25 @@ +[Code] +function GetFullVersion(VersionMS, VersionLS: cardinal): string; +var + version: string; +begin + version := IntToStr(word(VersionMS shr 16)); + version := version + '.' + IntToStr(word(VersionMS and not $ffff0000)); + + version := version + '.' + IntToStr(word(VersionLS shr 16)); + version := version + '.' + IntToStr(word(VersionLS and not $ffff0000)); + + Result := version; +end; + +function fileversion(file: string): string; +var + versionMS, versionLS: cardinal; +begin + if GetVersionNumbers(file, versionMS, versionLS) then + Result := GetFullVersion(versionMS, versionLS) + else + Result := '0'; +end; + +[Setup] diff --git a/Installer/scripts/products/stringversion.iss b/Installer/scripts/products/stringversion.iss new file mode 100644 index 0000000..e7ee3d7 --- /dev/null +++ b/Installer/scripts/products/stringversion.iss @@ -0,0 +1,62 @@ +[Code] +function stringtoversion(var temp: String): Integer; +var + part: String; + pos1: Integer; + +begin + if (Length(temp) = 0) then begin + Result := -1; + Exit; + end; + + pos1 := Pos('.', temp); + if (pos1 = 0) then begin + Result := StrToInt(temp); + temp := ''; + end else begin + part := Copy(temp, 1, pos1 - 1); + temp := Copy(temp, pos1 + 1, Length(temp)); + Result := StrToInt(part); + end; +end; + +function compareinnerversion(var x, y: String): Integer; +var + num1, num2: Integer; + +begin + num1 := stringtoversion(x); + num2 := stringtoversion(y); + if (num1 = -1) and (num2 = -1) then begin + Result := 0; + Exit; + end; + + if (num1 < 0) then begin + num1 := 0; + end; + if (num2 < 0) then begin + num2 := 0; + end; + + if (num1 < num2) then begin + Result := -1; + end else if (num1 > num2) then begin + Result := 1; + end else begin + Result := compareinnerversion(x, y); + end; +end; + +function compareversion(versionA, versionB: String): Integer; +var + temp1, temp2: String; + +begin + temp1 := versionA; + temp2 := versionB; + Result := compareinnerversion(temp1, temp2); +end; + +[Setup] diff --git a/Installer/scripts/products/winversion.iss b/Installer/scripts/products/winversion.iss new file mode 100644 index 0000000..c6d7e72 --- /dev/null +++ b/Installer/scripts/products/winversion.iss @@ -0,0 +1,49 @@ +[Code] +var + WindowsVersion: TWindowsVersion; + +procedure initwinversion(); +begin + GetWindowsVersionEx(WindowsVersion); +end; + +function exactwinversion(MajorVersion, MinorVersion: integer): boolean; +begin + Result := (WindowsVersion.Major = MajorVersion) and (WindowsVersion.Minor = MinorVersion); +end; + +function minwinversion(MajorVersion, MinorVersion: integer): boolean; +begin + Result := (WindowsVersion.Major > MajorVersion) or ((WindowsVersion.Major = MajorVersion) and (WindowsVersion.Minor >= MinorVersion)); +end; + +function maxwinversion(MajorVersion, MinorVersion: integer): boolean; +begin + Result := (WindowsVersion.Major < MajorVersion) or ((WindowsVersion.Major = MajorVersion) and (WindowsVersion.Minor <= MinorVersion)); +end; + +function exactwinspversion(MajorVersion, MinorVersion, SpVersion: integer): boolean; +begin + if exactwinversion(MajorVersion, MinorVersion) then + Result := WindowsVersion.ServicePackMajor = SpVersion + else + Result := true; +end; + +function minwinspversion(MajorVersion, MinorVersion, SpVersion: integer): boolean; +begin + if exactwinversion(MajorVersion, MinorVersion) then + Result := WindowsVersion.ServicePackMajor >= SpVersion + else + Result := true; +end; + +function maxwinspversion(MajorVersion, MinorVersion, SpVersion: integer): boolean; +begin + if exactwinversion(MajorVersion, MinorVersion) then + Result := WindowsVersion.ServicePackMajor <= SpVersion + else + Result := true; +end; + +[Setup] diff --git a/Installer/setup.iss b/Installer/setup.iss new file mode 100644 index 0000000..0fbd400 --- /dev/null +++ b/Installer/setup.iss @@ -0,0 +1,82 @@ +#define use_dotnetfx46 + +#define MyAppName "SmartHDD" +#define MyAppVersion "1.0.0.0" +#define MyAppPublisher "DoogeJ" +#define MyAppURL "https://github.com/DoogeJ/SmartHDD" +#define MyAppExeName "SmartHDD.exe" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +AppId={{8F0F9A45-E913-479D-97DE-0E8017B7B687} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={pf}\{#MyAppName} +DefaultGroupName={#MyAppName} +DisableProgramGroupPage=yes +OutputDir=bin +LicenseFile=..\LICENSE +OutputBaseFilename=Install_{#MyAppName}_{#MyAppVersion} +SetupIconFile=..\Visualpharm-Hardware-Hard-disk.ico +Compression=lzma +SolidCompression=yes + +; we will need administrator privileges to copy to program files and / or install prerequirements +PrivilegesRequired=admin + +;Downloading and installing dependencies will only work if the memo/ready page is enabled (default behaviour) +DisableReadyPage=no +DisableReadyMemo=no + +[Languages] +Name: "en"; MessagesFile: "compiler:Default.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" +Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; OnlyBelowVersion: 0,6.1 + +[Files] +Source: "..\SmartHDD\bin\Release\SmartHDD.exe"; DestDir: "{app}"; Flags: ignoreversion + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" +Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent runascurrentuser + +[CustomMessages] +win_sp_title=Windows %1 Service Pack %2 + + +; shared code for installing the products +#include "scripts\products.iss" +; helper functions +#include "scripts\products\stringversion.iss" +#include "scripts\products\winversion.iss" +#include "scripts\products\fileversion.iss" +#include "scripts\products\dotnetfxversion.iss" + +#ifdef use_dotnetfx46 +#include "scripts\products\dotnetfx46.iss" +#endif + + +[Code] +function InitializeSetup(): boolean; +begin + // initialize windows version + initwinversion(); + +#ifdef use_dotnetfx46 + dotnetfx46(50); // min allowed version is 4.5.0 +#endif + + Result := true; +end; \ No newline at end of file diff --git a/README.md b/README.md index 6ebd595..3f0298b 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,18 @@ It will most likely build fine on different configurations, but might require so ## Updating the version number The version number is stored in two locations: * In the projects assembly info file: **'SmartHDD\Properties\AssemblyInfo.cs'** +* In the installer setup.iss file (only used for the installer): **'Installer\setup.iss'** + +## Building the installer +> Note: *This installer uses 3rd party components from [innodependencyinstaller](https://github.com/stfx/innodependencyinstaller) to automatically download and install the correct .NET framework if required. See* ***'Installer\innodependencyinstaller LICENSE.md'*** *for the license of innodependencyinstaller.* + +SmartHDD uses the [Inno Setup Compiler](http://www.jrsoftware.org/isinfo.php) to generate an executable installer. +The installer project files are located in the **'Installer'**-folder. + +The scripts are based on [Inno Setup 5.5.9](http://www.jrsoftware.org/isinfo.php) but will probably work with any recent version. + +To build the installer: +* Make sure the project is compiled and there is a working executable named **'SmartHDD.exe'** in the **'SmartHDD\bin\Release'**-folder +* Open **'Installer\setup.iss'** in the [Inno Setup Compiler](http://www.jrsoftware.org/isinfo.php) +* Hit *Build* -> *Compile* (Ctrl+F9) +* Done, the installer should be in the **'Installer\bin'**-folder \ No newline at end of file