From d2bd4ec4be4409e7701e826decc948a07349cd27 Mon Sep 17 00:00:00 2001 From: Yuanle Song Date: Fri, 15 Nov 2019 00:40:31 +0800 Subject: [PATCH] WIP build msi using wix. - introduced wix, make - rsync-mingw64.msi works - I decide to include rsync inside mbackup.msi, and install it in the same app dir. So this working rsync-mingw64.msi config will be removed in next commit. --- .gitignore | 4 + Makefile | 29 +++ mbackup-for-windows.fsproj | 1 + mbackup.wxs | 45 +++++ operational | 378 ++++++++++++++++++++++++++++--------- rsync-mingw64.wxs | 15 ++ 6 files changed, 383 insertions(+), 89 deletions(-) create mode 100644 Makefile create mode 100644 mbackup.wxs create mode 100644 rsync-mingw64.wxs diff --git a/.gitignore b/.gitignore index ff4880b..dc7b3ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ obj/ bin/ .ionide/ +*.wixobj +*.wixpdb +*.msi +rsync-mingw64-files.wxs diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a045810 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +WIX_DIR := "C:\Program Files (x86)\WiX Toolset v3.11\bin" +HEAT := "C:\Program Files (x86)\WiX Toolset v3.11\bin\heat.exe" +CANDLE := "C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe" -arch x64 +LIGHT := "C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" +default: test +all: test release dist +dist: mbackup.msi rsync-mingw64.msi +release: + dotnet publish -c Release -r win10-x64 --nologo +test: + dotnet test mbackup-tests +check: test +build: + dotnet build +clean: + dotnet clean + del *.wixobj *.msi +%.wixobj: %.wxs + $(CANDLE) $< +mbackup.msi: mbackup.wixobj release + $(LIGHT) $< +# standalone rsync-mingw64 +rsync-mingw64-files.wxs: + $(HEAT) dir "D:\downloads\apps\rsync-w64" -cg RsyncHeatGenerated -dr ProgramFiles64Folder -var var.RsyncSourceDir -gg -nologo -out rsync-mingw64-files.wxs -sw5150 +rsync-mingw64.msi: rsync-mingw64.wxs rsync-mingw64-files.wxs + $(CANDLE) -dRsyncSourceDir=D:\downloads\apps\rsync-w64\ .\rsync-mingw64.wxs .\rsync-mingw64-files.wxs + $(LIGHT) rsync-mingw64.wixobj rsync-mingw64-files.wixobj -o rsync-mingw64.msi +# END standalone rsync-mingw64 +.PHONY: default all dist release test check build clean diff --git a/mbackup-for-windows.fsproj b/mbackup-for-windows.fsproj index 717b654..213547f 100644 --- a/mbackup-for-windows.fsproj +++ b/mbackup-for-windows.fsproj @@ -3,6 +3,7 @@ Exe netcoreapp3.0 + win10-x64 Mbackup diff --git a/mbackup.wxs b/mbackup.wxs new file mode 100644 index 0000000..6436e5f --- /dev/null +++ b/mbackup.wxs @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/operational b/operational index 0aa7687..0b8f10b 100644 --- a/operational +++ b/operational @@ -64,6 +64,10 @@ dotnet run -- -i https://docs.microsoft.com/en-us/dotnet/api/system.datetime.tostring?view=netframework-4.8 Standard Date and Time Format Strings | Microsoft Docs https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings?view=netframework-4.8 + The Option type | F# for fun and profit + https://fsharpforfunandprofit.com/posts/the-option-type/ + Pattern Matching - F# | Microsoft Docs + https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching - FSharpLint http://fsprojects.github.io/FSharpLint/ http://fsprojects.github.io/FSharpLint/index.html @@ -84,7 +88,16 @@ C:\Program Files\mbackup\rsync-w64\usr\bin\ssh.exe C:\ProgramData\mbackup\mbackup-default.exclude C:\ProgramData\mbackup\mbackup-default.list C:\ProgramData\mbackup\user-default.list -C:\ProgramData\mbackup\mbackup.ini +C:\ProgramData\mbackup\mbackup.txt + +- optional user configs + like /etc/mbackup/ in linux + C:\ProgramData\mbackup\local.list + C:\ProgramData\mbackup\local.exclude + + like ~/.mbackup/ in linux + /mbackup/local.list + /mbackup/local.exclude ** 2019-11-14 notes :development: - Argu optional param support. @@ -94,6 +107,16 @@ C:\ProgramData\mbackup\mbackup.ini results.TryGetResult Target or results.GetResult(Target, defaultValue = xxx) +- WiX wxs file + + Platform="x64" has the same meaning as candle -arch x64. + +- Wix for creating installer for 64bit app, you need to add in attribute + Win64="yes" + + use candle -arch x64 can add Win64="yes" automatically if there is no Win64 attribute specified in Component. + wix3.6 - WiX Heat tool, create Component with Win64 attribute - Stack Overflow + https://stackoverflow.com/questions/11981498/wix-heat-tool-create-component-with-win64-attribute - * later :entry: @@ -103,105 +126,162 @@ it can only support open a namespace. using the vscode Ionide-fsharp extension. * current :entry: ** -** 2019-11-13 next todos -- DONE fix TODOs in F# code -- DONE add rsync command and arguments for running in windows. - i.e. -e etc. +** TODO 2019-11-15 additionally support /mbackup/local.list file. +This file is easier to open and backup. + +no. programdata should be good enough. +but this is per user extra config file. +each user could have their own local file to backup. +one user don't want to manage all other user's local backup list. + +yes. I should support this. + +Both local.list and local.exclude. + +** 2019-11-14 learn how to create an msi installer. +- WiX Toolset + https://wixtoolset.org/ + c# - How to create MSI installer for ASP.NET Core application using Wix Toolset - Stack Overflow + https://stackoverflow.com/questions/46878752/how-to-create-msi-installer-for-asp-net-core-application-using-wix-toolset + + Windows Installer XML (WiX) + https://wixtoolset.org/documentation/manual/v3/main/ + +- Introducing dotGet: an installer for .NET Core CLI apps + https://medium.com/@tonerdo/introducing-dotget-an-installer-for-net-core-cli-apps-9ba79ac7cd89 + + requires nuget. then it can install your dotnet core console project. + this is not what I need here. +- Packaging a self-contained .NET Core app for Windows Installer + https://nblumhardt.com/2017/04/netcore-msi/ + + This is the first time I’ve tried packaging a .NET Core app for the Windows + Installer, so I thought I’d write these brief notes to help anyone else + interested in taking the same path. + +- should I include rsync-mingw64 in the same msi file? + distributing it alone is not very useful, since people can just use msys2 or cygwin. + + If I include it in the same msi, I don't need to use wix bundle, and I can install rsync to the same dir as mbackup. + it seems cleaner this way. Just like a VPN client bundle openvpn or a python program bundle python. + yes. include it in the same msi and install in a sub dir. +- try Wix. + - install wix. + requires .net 3.5 windows feature. + - Building Installation Package Bundles + https://wixtoolset.org/documentation/manual/v3/bundle/ + - How To Guides + https://wixtoolset.org/documentation/manual/v3/howtos/ + - How To: Add a File to Your Installer + https://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/add_a_file.html + - create installer.wxs + + build mbackup binaries + dotnet publish -c Release - --stats -togr --chown=sylecn:sylecn --exclude-from=/cygdrive/d/sylecn_docs/texts/configs/rsync-exclude - --files-from=/cygdrive/d/sylecn_docs/texts/configs/rsync-file-list - --log-file=/cygdrive/d/sylecn_docs/rsync-b75i3.log - -e ".\ssh.exe -F c:/users/sylecn/.ssh/config -i c:/Users/sylecn/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" - / sheni:/data/backup/server-backup/b75i3/ +- problems + - each file require it's own tag. + rsync mingw have many files. I seems I need to generate an installer for + rsync for windows. + - search: wix only install file if it does not exist + windows installer - Copy if not exist in WiX - Stack Overflow + https://stackoverflow.com/questions/1912037/copy-if-not-exist-in-wix + installer - What is the wix 'KeyPath' attribute? - Stack Overflow + https://stackoverflow.com/questions/2003043/what-is-the-wix-keypath-attribute/2003366#2003366 + Component Table - Win32 apps | Microsoft Docs + https://docs.microsoft.com/en-us/windows/win32/msi/component-table?redirectedfrom=MSDN + How To: Check for .NET Framework Versions + https://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/check_for_dotnet.html + - TODO how to unpack zip file to target dir? + I don't want to create a Component for every file there. + + windows installer - Wix custom action to unzip a file - Stack Overflow + https://stackoverflow.com/questions/47691477/wix-custom-action-to-unzip-a-file + + the suggestion is to include the files in msi. + or unzip the files at app runtime. + + I will try create a msi file for mingw64 rsync. + then use wix bundle to install it as dependency. + + - search: wix install all files in a folder + + - Include all Files in Bin folder in Wix installer - Stack Overflow + https://stackoverflow.com/questions/36756311/include-all-files-in-bin-folder-in-wix-installer + + create rsync-mingw64-files.wxs + &"C:\Program Files (x86)\WiX Toolset v3.11\bin\heat.exe" dir "D:\downloads\apps\rsync-w64" -cg RsyncHeatGenerated -dr ProgramFiles64Folder -var var.RsyncSourceDir -gg -nologo -out rsync-mingw64-files.wxs -sw5150 + + compile and build rsync-mingw64.msi + &"C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe" -dRsyncSourceDir=D:\downloads\apps\rsync-w64\ .\rsync-mingw64.wxs .\rsync-mingw64-files.wxs + &"C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" .\rsync-mingw64.wixobj .\rsync-mingw64-files.wixobj -o rsync-mingw64.msi + + build is getting complex. I need make and Makefile. + - problems + - how to pass in preprocessor variable? + WiX undefined preprocessor variable - Stack Overflow + https://stackoverflow.com/questions/2063630/wix-undefined-preprocessor-variable + To pass values for preprocessor variables like $(var.MyProject.TargetDir), use options like -dMyProject.TargetDir=c:\foo. + - why rsync-mingw64 is installed to C:\Program Files (x86)\rsync-w64? I expect C:\Program Files\rsync-w64\ + wix-users - 64 Bit program files folder + http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/64-Bit-program-files-folder-td5948080.html + - INVALID make pattern rule doesn't work in windows + it works. it is because my source file is missing. + - why mbackup.exe is 32 bit component? + try this: + dotnet publish -c Release -r win10-x64 + still same error. + D:\sylecn_docs\projects\mbackup-for-windows\mbackup.wxs(16) : error LGHT0204 : ICE80: This 32BitComponent mbackup.exe uses 64BitDirectory APPLICATIONROOTDIRECTORY + search: dotnet core how to build x64 exe file + dotnet is building x64 exe file. it's WIX issue. + need to add Win64="yes" in attribute. + + - DONE how to run wix to create msi file? + two command line tool + light + candle + it's not added in PATH. + C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe + C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe + + There is offline doc. + C:\Program Files (x86)\WiX Toolset v3.11\doc\WiX.chm + C:\Program Files (x86)\WiX Toolset v3.11\doc\msi.chm + + do read the WiX Tutorial. + https://www.firegiant.com/wix/tutorial/ + https://www.firegiant.com/wix/tutorial/getting-started/ + + &"C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe" .\mbackup.wxs + &"C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" .\mbackup.wixobj + it works. + mbackup.msi file is created. + - -- DONE test param parsing is working. - command line param > env var > mbackup default value. - support --node-name param. -- test run in console and scheduled task. - run in console works. - try run in scheduled task. +** 2019-11-12 make code work in a specific dir. then create an installer. +- bundle dotnet core 3 with installer. +- install binary files to %programfiles% +- install mbackup config files to %programdata% +- install scheduled tasks as admin SCHTASKS /Create /? # run mbackup 15m after user logon. - SCHTASKS /Create /U /SC ONLOGON /TN mbackup-logon /TR "\"\" \"args\"" /DELAY 15:00 + SCHTASKS /Create /NP /SC ONLOGON /TN mbackup-logon /TR "\"\" \"args\"" /DELAY 15:00 # run mbackup at 10am and 4pm. - SCHTASKS /Create /U /SC DAILY /TN mbackup-morning /TR "\"\" \"args\"" /ST 10:00 /ET 13:00 /K - SCHTASKS /Create /U /SC DAILY /TN mbackup-afternoon /TR "\"\" \"args\"" /ST 16:00 /ET 19:00 /K + SCHTASKS /Create /NP /SC DAILY /TN mbackup-morning /TR "\"\" \"args\"" /ST 10:00 /ET 13:00 /K + SCHTASKS /Create /NP /SC DAILY /TN mbackup-afternoon /TR "\"\" \"args\"" /ST 16:00 /ET 19:00 /K # debug purpose, one time only - SCHTASKS /Create /U /SC ONCE /TN mbackup-afternoon /TR "\"\" \"args\"" /ST 12:03 - - - problems - - how many scheduled task to run on a multi-user PC? - each user have its own user-default.list expansion. - should I iter over all users on PC? - I think only current user can get it's profile dir and special dirs. - - maybe config mbackup to run after user logon. with 15minute delay. - always run as current user. - - how to not require any param when running mbackup.exe? - put TARGET and other option in a config file? - define system level TARGET env variable. - - use config file is easier for user to edit and making the change effective. - userConfigDir / mbackup.conf - - search: F# read config file - FSharp.Configuration - http://fsprojects.github.io/FSharp.Configuration/ - - FSharp.Configuration missing reference to System.Runtime.Caching - search: how to reference System.Runtime.Caching for dotnet core project - https://www.nuget.org/packages/System.Runtime.Caching/ - dotnet add package System.Runtime.Caching --version 4.6.0 - should I add 4.0.0? Can I use a higher version? - - still not compatible. - search: use FSharp.Configuration with dotnet core 3 - - give up on FSharp.Configuration. - - try this: - FsConfig - https://www.demystifyfp.com/FsConfig/ - AppSettings is only supported in V0.0.6 or below. - try F# AppSettings directly. - If nothing is easy to use, write my own parser. - Support similar config format as python wells lib. - - ConfigurationManager.AppSettings Property (System.Configuration) | Microsoft Docs - https://docs.microsoft.com/en-us/dotnet/api/system.configuration.configurationmanager.appsettings?view=netframework-4.8 - where should I save the App.config xml file? - search: what is app.config - App.Config: Basics and Best Practices - SubMain Blog - https://blog.submain.com/app-config-basics-best-practices/ - What is App.config in C#.NET? How to use it? - Stack Overflow - https://stackoverflow.com/questions/13043530/what-is-app-config-in-c-net-how-to-use-it - Okay. This is not what I want. - This is for application configuration (rarely change), not for user configuration (can change any time). - dotnet will create .exe.config from your App.config file. - - how to use multiple files in F# dotnet core project? - search: f# module and namespace - search: f# module - Modules - F# | Microsoft Docs - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/modules + SCHTASKS /Create /NP /SC ONCE /TN mbackup-test /TR "\"\" \"args\"" /ST 19:18 -- create an installer. The installer should add scheduled task on install and - delete scheduled task on removal. + In admin powershell, + SCHTASKS /Create /NP /SC ONCE /TN mbackup-test /TR $mbackupexe /ST 19:32 + /NP option requires admin privilledge. + it works. -- problems - - how to write unit test in F#? - Unit testing F# in .NET Core with dotnet test and NUnit - .NET Core | Microsoft Docs - https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-fsharp-with-nunit - mkdir mbackup-tests - cd mbackup-tests - dotnet new nunit -lang F# - //wait. - dotnet test + to delete it, + schtasks /delete /tn mbackup-test - dotnet add reference ../mbackup-for-windows.fsproj - dotnet build # this will build both ref project and test project. - dotnet test - - how to support short option names? - --dry-run -n - - -** 2019-11-12 make code work in a specific dir. then create an installer. -- install to %programfiles% - config is installed/saved to %appdata% roaming dir. - problems - config should be system wide. %appdata% is per-user dir. @@ -307,6 +387,126 @@ using the vscode Ionide-fsharp extension. it contains hostname. - * done :entry: +** 2019-11-13 next todos; scheduled task command line. +- DONE fix TODOs in F# code +- DONE add rsync command and arguments for running in windows. + i.e. -e etc. + + --stats -togr --chown=sylecn:sylecn --exclude-from=/cygdrive/d/sylecn_docs/texts/configs/rsync-exclude + --files-from=/cygdrive/d/sylecn_docs/texts/configs/rsync-file-list + --log-file=/cygdrive/d/sylecn_docs/rsync-b75i3.log + -e ".\ssh.exe -F c:/users/sylecn/.ssh/config -i c:/Users/sylecn/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" + / sheni:/data/backup/server-backup/b75i3/ + +- DONE test param parsing is working. + command line param > env var > mbackup default value. + support --node-name param. +- DONE test run in console and scheduled task. + run in console works. + try run in scheduled task. + + SCHTASKS /Create /? + # run mbackup 15m after user logon. + SCHTASKS /Create /U /SC ONLOGON /TN mbackup-logon /TR "\"\" \"args\"" /DELAY 15:00 + # run mbackup at 10am and 4pm. + SCHTASKS /Create /U /SC DAILY /TN mbackup-morning /TR "\"\" \"args\"" /ST 10:00 /ET 13:00 /K + SCHTASKS /Create /U /SC DAILY /TN mbackup-afternoon /TR "\"\" \"args\"" /ST 16:00 /ET 19:00 /K + + # debug purpose, one time only + SCHTASKS /Create /SC ONCE /TN mbackup-test /TR "\"\" \"args\"" /ST 19:18 + + in powershell, + $mbackupexe = "D:\sylecn_docs\projects\mbackup-for-windows\bin\Debug\netcoreapp3.0\mbackup-for-windows.exe" + SCHTASKS /Create /SC ONCE /TN mbackup-test /TR $mbackupexe /ST 19:21 + default run as user is current user. + + in admin powershell, + SCHTASKS /Create /SC ONCE /TN mbackup-test /TR $mbackupexe /ST 19:32 /NP + /NP option requires admin privilledge. + it works. + + to delete it, + schtasks /delete /tn mbackup-test + + - problems + - how many scheduled task to run on a multi-user PC? + each user have its own user-default.list expansion. + should I iter over all users on PC? + I think only current user can get it's profile dir and special dirs. + - maybe config mbackup to run after user logon. with 15minute delay. + always run as current user. + - how to not require any param when running mbackup.exe? + put TARGET and other option in a config file? + define system level TARGET env variable. + + use config file is easier for user to edit and making the change effective. + userConfigDir / mbackup.conf + + search: F# read config file + FSharp.Configuration + http://fsprojects.github.io/FSharp.Configuration/ + - FSharp.Configuration missing reference to System.Runtime.Caching + search: how to reference System.Runtime.Caching for dotnet core project + https://www.nuget.org/packages/System.Runtime.Caching/ + dotnet add package System.Runtime.Caching --version 4.6.0 + should I add 4.0.0? Can I use a higher version? + + still not compatible. + search: use FSharp.Configuration with dotnet core 3 + - give up on FSharp.Configuration. + - try this: + FsConfig + https://www.demystifyfp.com/FsConfig/ + AppSettings is only supported in V0.0.6 or below. + try F# AppSettings directly. + If nothing is easy to use, write my own parser. + Support similar config format as python wells lib. + - ConfigurationManager.AppSettings Property (System.Configuration) | Microsoft Docs + https://docs.microsoft.com/en-us/dotnet/api/system.configuration.configurationmanager.appsettings?view=netframework-4.8 + where should I save the App.config xml file? + search: what is app.config + App.Config: Basics and Best Practices - SubMain Blog + https://blog.submain.com/app-config-basics-best-practices/ + What is App.config in C#.NET? How to use it? - Stack Overflow + https://stackoverflow.com/questions/13043530/what-is-app-config-in-c-net-how-to-use-it + Okay. This is not what I want. + This is for application configuration (rarely change), not for user configuration (can change any time). + dotnet will create .exe.config from your App.config file. + - how to use multiple files in F# dotnet core project? + search: f# module and namespace + search: f# module + Modules - F# | Microsoft Docs + https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/modules + - SCHTASKS /Create /SC ONCE /TN mbackup-test /TR $mbackupexe /ST 19:21 + this runs, it will show a console window. how to not show console window? + + search: schedule tasks do not show console window + + In the “General” tab, under the “Security options” section, select the Run + whether user is logged on or not option. (This is the option that will make + the command window not to appear when the task runs automatically.) + + try /NP option. + +- create an installer. The installer should add scheduled task on install and + delete scheduled task on removal. + +- problems + - how to write unit test in F#? + Unit testing F# in .NET Core with dotnet test and NUnit - .NET Core | Microsoft Docs + https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-fsharp-with-nunit + mkdir mbackup-tests + cd mbackup-tests + dotnet new nunit -lang F# + //wait. + dotnet test + + dotnet add reference ../mbackup-for-windows.fsproj + dotnet build # this will build both ref project and test project. + dotnet test + - how to support short option names? + --dry-run -n + - ** 2019-11-14 support mbackup.txt config. config file will have wells config file format. empty lines and comment lines are ignored. diff --git a/rsync-mingw64.wxs b/rsync-mingw64.wxs new file mode 100644 index 0000000..f132d2e --- /dev/null +++ b/rsync-mingw64.wxs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + -- GitLab