Commit a00a1c3c authored by Yuanle Song's avatar Yuanle Song
Browse files

mbackup.msi works on dev node.

- renmaed mbackup-for-windows.fsproj to mbackup.fsproj
  this file name is the project name. now exe is named mbackup.exe
- use framework dependent release.
- include rsync-mingw in one msi
- use installed rsync and ssh path in Program.fs
parent d2bd4ec4
......@@ -4,4 +4,4 @@ bin/
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
WIX_DIR := C:\Program Files (x86)\WiX Toolset v3.11\bin
HEAT := "$(WIX_DIR)\heat.exe"
CANDLE := "$(WIX_DIR)\candle.exe" -arch x64 -nologo
LIGHT := "$(WIX_DIR)\light.exe" -nologo
RSYNC_MINGW_DIR := D:\downloads\apps\rsync-w64
MBACKUP_PUBLISH_DIR := bin\Release\netcoreapp3.0\publish
default: build
@cmd /C echo 'Usage: make [build|test|release|clean|dist|all]'
all: test release dist
dist: mbackup.msi rsync-mingw64.msi
dist: mbackup.msi
dotnet publish -c Release -r win10-x64 --nologo
dotnet publish --nologo -c Release --self-contained false
dotnet test mbackup-tests
dotnet test --nologo mbackup-tests
check: test
dotnet build
dotnet build --nologo
dotnet clean
del *.wixobj *.msi
dotnet clean --nologo
cmd /C 'del *.wixobj *.wixpdb *.msi rsync-mingw64-files.wxs'
%.wixobj: %.wxs
$(CANDLE) $<
mbackup.msi: mbackup.wixobj release
$(LIGHT) $<
# standalone rsync-mingw64
$(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
$(HEAT) dir $(RSYNC_MINGW_DIR) -cg RsyncHeatGenerated -dr MBACKUP_PROGRAM_FILES -var var.RsyncSourceDir -gg -nologo -out $@ -sw5150
rsync-mingw64-files.wixobj: rsync-mingw64-files.wxs
$(CANDLE) -dRsyncSourceDir=$(RSYNC_MINGW_DIR) $<
mbackup-files.wxs: release
$(HEAT) dir $(MBACKUP_PUBLISH_DIR) -cg MbackupHeatGenerated -dr MBACKUP_PROGRAM_FILES -var var.MbackupPublishDir -gg -nologo -out $@ -sw5150
mbackup-files.wixobj: mbackup-files.wxs
$(CANDLE) -dMbackupPublishDir=$(MBACKUP_PUBLISH_DIR) $<
mbackup.msi: mbackup.wixobj rsync-mingw64-files.wixobj mbackup-files.wixobj
$(LIGHT) $^ -o $@
.PHONY: default help all dist release test check build clean rsync-mingw64-files.wxs mbackup-files.wxs
......@@ -44,6 +44,11 @@ with
| Node_Name _ -> "local node's name, used in remote logging"
| Ssh_Key _ -> "ssh private key, used when backup to remote ssh node"
let programFilesDirWin = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) |> ensureWinDir
let programFilesDir = toMingwPath programFilesDirWin
let mbackupProgramDirWin = programFilesDirWin + "mbackup\\"
let mbackupProgramDir = toMingwPath mbackupProgramDirWin
let appDataRoamingDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) |> toMingwPath |> ensureDir
let programDataDirWin = getEnv "PROGRAMDATA" |> ensureWinDir
let programDataDir = toMingwPath programDataDirWin
......@@ -115,7 +120,7 @@ let generateMbackupList (logger: Logger) =
let lines = readMbackupListFile mbackupLocalList |> toMingwPath
(true, lines)
| :? System.IO.FileNotFoundException ->
| :? FileNotFoundException ->
(true, Seq.empty)
| ex ->
logger.Error "Read mbackupLocalList failed: %s" ex.Message
......@@ -151,6 +156,7 @@ let main argv =
logger.Info "user config dir: %s" userConfigDirWin
logger.Info "runtime dir: %s" runtimeDirWin
logger.Debug "program dir: %s" mbackupProgramDirWin
let rsyncCmd: string list = []
let rsyncCmd = appendWhen dryRun rsyncCmd "--dry-run"
......@@ -170,13 +176,10 @@ let main argv =
let localLogFile = runtimeDir + "mbackup.log"
let rsyncCmd = List.append rsyncCmd [sprintf "--log-file=%s" localLogFile]
// TODO remove usage of test dir.
let mbackupInstallDirWinTest = "D:\\downloads\\apps\\mbackupTest\\"
let mbackupInstallDirTest = mbackupInstallDirWinTest |> toMingwPath |> ensureDir
let sshExeFile = mbackupInstallDirTest + "rsync-w64/usr/bin/ssh.exe"
let sshExeFile = mbackupProgramDir + "rsync-w64/usr/bin/ssh.exe"
let sshConfigFile = userHome + ".ssh/config"
let sshPrivateKeyFile = results.GetResult(Ssh_Key, defaultValue = userHome + ".ssh/id_rsa") |> toMingwPath
let rsyncCmd = List.append rsyncCmd [sprintf "-e \"%s -F %s -i %s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\"" sshExeFile sshConfigFile sshPrivateKeyFile]
let rsyncCmd = List.append rsyncCmd [sprintf "-e \"'%s' -F %s -i %s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\"" sshExeFile sshConfigFile sshPrivateKeyFile]
// precedence: command line argument > environment variable > config file
let normalizeTarget target =
......@@ -211,13 +214,12 @@ let main argv =
let rsyncCmd = List.append rsyncCmd ["/"]
let rsyncCmd = List.append rsyncCmd [backupTarget]
let rsyncArgs = rsyncCmd |> String.concat " "
let rsyncExe = mbackupInstallDirWinTest + "rsync-w64\\usr\\bin\\rsync.exe"
let echoExe = "C:\\Program Files\\Git\\usr\\bin\\echo.exe"
let rsyncExe = mbackupProgramDirWin + "rsync-w64\\usr\\bin\\rsync.exe"
IO.Directory.CreateDirectory(runtimeDir) |> ignore
IO.Directory.CreateDirectory(userConfigDir) |> ignore
let proc = Process.Start(rsyncExe, rsyncArgs)
Directory.CreateDirectory(runtimeDir) |> ignore
Directory.CreateDirectory(userConfigDir) |> ignore
logger.Info "Note: if you run the following rsync command yourself, make sure the generated file list (%s) is up-to-date.\n%s" mbackupFile (rsyncExe + " " + rsyncArgs)
let proc = Process.Start(rsyncExe, rsyncArgs)
if proc.WaitForExit Int32.MaxValue then
logger.Info "mbackup exit"
......@@ -225,7 +227,7 @@ let main argv =
logger.Error "mbackup timed out while waiting for rsync to complete"
| :? System.IO.IOException as ex ->
| :? IOException as ex ->
logger.Error "IO Error: %s %s" ex.Source ex.Message
| ex ->
......@@ -20,7 +20,7 @@
<ProjectReference Include="..\mbackup-for-windows.fsproj" />
<ProjectReference Include="..\mbackup.fsproj" />
......@@ -5,6 +5,7 @@
......@@ -5,20 +5,14 @@
<Media Id="1" Cabinet="" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="mbackup"/>
<Directory Id="MBACKUP_PROGRAM_FILES" Name="mbackup" />
<Directory Id="CommonAppDataFolder">
<Directory Id="APPLICATIONDATADIR" Name="mbackup"/>
<Directory Id="MBACKUP_DATA" Name="mbackup"/>
<Component Id="mbackup.exe" Guid="*">
<File Id="mbackup.exe" Source="bin\Release\netcoreapp3.0\win10-x64\mbackup-for-windows.exe" KeyPath="yes" Checksum="yes"/>
<DirectoryRef Id="MBACKUP_DATA">
<Component Id="mbackup_default.exclude" Guid="*">
<File Id="mbackup_default.exclude" Source="mbackup-config\mbackup-default.exclude" KeyPath="yes"/>
......@@ -35,7 +29,8 @@
<Feature Id="MainApplication" Title="Main Application" Level="1">
<ComponentRef Id="mbackup.exe" />
<ComponentGroupRef Id="MbackupHeatGenerated" />
<ComponentGroupRef Id="RsyncHeatGenerated" />
<ComponentRef Id="mbackup_default.exclude" />
<ComponentRef Id="mbackup_default.list" />
<ComponentRef Id="user_default.list" />
......@@ -85,6 +85,8 @@ dotnet run -- -i
** 2019-11-13 install dir layout.
C:\Program Files\mbackup\rsync-w64\usr\bin\rsync.exe
C:\Program Files\mbackup\rsync-w64\usr\bin\ssh.exe
C:\Program Files\mbackup\publish\mbackup.exe
C:\Program Files\mbackup\publish\mbackup.dll
......@@ -117,6 +119,8 @@ C:\ProgramData\mbackup\mbackup.txt
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
- Wix to install file in another name, add Name attribute in <File>.
<File Id="mbackup.exe" Name="mbackup.exe" Source="bin\Release\netcoreapp3.0\win10-x64\mbackup-for-windows.exe" KeyPath="yes" Checksum="yes"/>
* later :entry:
......@@ -174,10 +178,22 @@ Both local.list and local.exclude.
- How To: Add a File to Your Installer
- create installer.wxs
- create mbackup.wxs
build mbackup binaries
dotnet publish -c Release
- TODO how to show a message when installer is finished succesfully?
currently it installs very fast and just exit without any user notification.
maybe show a installer window and let user click Next and Finish.
- TODO how to add some dir to PATH?
I only have one exe. Maybe just create a start menu or desktop shortcut?
create desktop shortcut to mbackup.exe
- TODO how to support upgrade when I click a new msi?
currently every msi is a standalone msi and will always install fresh.
is the UpgradeCode used for this?
- mbackup.msi works on B75I3 host.
- try mbackup.msi on win 10 VM.
how to require dotnet core 3.0 in .wxs file?
- problems
- each file require it's own <Component> tag.
......@@ -192,7 +208,7 @@ Both local.list and local.exclude.
How To: Check for .NET Framework Versions
- TODO how to unpack zip file to target dir?
- WONTFIX 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
......@@ -256,7 +272,40 @@ Both local.list and local.exclude.
&"C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" .\mbackup.wixobj
it works.
mbackup.msi file is created.
- the mbackup.exe can't run without all those dlls.
dotnet publish -c Release -r win10-x64 --nologo
maybe I should build a exe that requires dotnet core 3 to run.
I don't want to create a big msi.
try this:
dotnet publish -c Release --nologo
and update wix xml files.
need to add all files in bin\Release\netcoreapp3.0\publish\ dir.
use heat to create another wxs file.
- heat can't add some dll.
"C:\Program Files (x86)\WiX Toolset v3.11\bin\heat.exe" dir bin\Release\netcoreapp3.0\publish -cg MbackupHeatGenerated -dr MBACKUP_PROGRAM_FILES -var var.MbackupPublishDir -gg -nologo -out mbackup-files.wxs -sw5150
heat.exe : warning HEAT5151 : Could not harvest data from a file that was expected to be an assembly: D:\sylecn_docs\projects\mbackup-for-windows\bin\Release\netcoreapp3.0\publish\Argu.dll. If this file is not an assembly you can ignore this warning. Otherwise, this error detail may be helpful to diagnose the failure: 未能加载文件或程序集“FSharp.Core, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到
heat.exe : warning HEAT5151 : Could not harvest data from a file that was expected to be an assembly: D:\sylecn_docs\projects\mbackup-for-windows\bin\Release\netcoreapp3.0\publish\mbackup.dll. If this file is not an assembly
you can ignore this warning. Otherwise, this error detail may be helpful to diagnose the failure: 未能加载文件或程序集“System.Runtime, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统
.net - Wix Toolkit: Heat balking about DLL's - Stack Overflow
com - Cannot register DLL using WiX - Stack Overflow
- TODO dup file?
<Component Id="cmp981FC09307D7CB82695815FAAFCC646D" Directory="dir02A4AE56AE905AEEE7E2D4F4410A9748" Guid="{DB94490C-32CA-4B14-A96D-A95D4B557D01}">
<File Id="fil432C46247A06CCDB891611045DD37081" KeyPath="yes" Source="$(var.MbackupPublishDir)\runtimes\win\lib\netstandard2.0\System.Security.Cryptography.ProtectedData.dll" />
<Component Id="cmp5190411B4FE56A0E0CE782BE6C1B537E" Directory="dir1B0C588BD61288F160D459591DA01603" Guid="{F0613E24-B22B-4A58-A054-380BDF2B857C}">
<File Id="filE0C94795A0B5F482BD659FBB774641C7" KeyPath="yes" Source="$(var.MbackupPublishDir)\System.Security.Cryptography.ProtectedData.dll" />
why there are duplicated dll in publish dir? check publish doc.
this is the only duplicated file. I will ignore it for now.
- DONE ssh.exe path escape issue.
&"C:\Program Files\mbackup\rsync-w64\usr\bin\rsync.exe" -h --stats -togr --delete --delete-excluded --ignore-missing-args --files-from=/cygdrive/c/Users/sylecn/AppData/Local/mbackup/mbackup.list --exclude-from=/cygdrive/c/ProgramData/mbackup/mbackup-default.exclude --log-file=/cygdrive/c/Users/sylecn/AppData/Local/mbackup/mbackup.log -e "/cygdrive/c/Program Files/mbackup/rsync-w64/usr/bin/ssh.exe -F /cygdrive/c/Users/sylecn/.ssh/config -i /cygdrive/c/Users/sylecn/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --remote-option=--log-file=/var/log/mbackup/B75I3.log --chown=sylecn:sylecn /
rsync: Failed to exec /cygdrive/c/Program: No such file or directory (2)
&"C:\Program Files\mbackup\rsync-w64\usr\bin\rsync.exe" -h --stats -togr --delete --delete-excluded --ignore-missing-args --files-from=/cygdrive/c/Users/sylecn/AppData/Local/mbackup/mbackup.list --exclude-from=/cygdrive/c/ProgramData/mbackup/mbackup-default.exclude --log-file=/cygdrive/c/Users/sylecn/AppData/Local/mbackup/mbackup.log -e "'/cygdrive/c/Program Files/mbackup/rsync-w64/usr/bin/ssh.exe' -F /cygdrive/c/Users/sylecn/.ssh/config -i /cygdrive/c/Users/sylecn/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --remote-option=--log-file=/var/log/mbackup/B75I3.log --chown=sylecn:sylecn /
** 2019-11-12 make code work in a specific dir. then create an installer.
- bundle dotnet core 3 with installer.
<?xml version="1.0"?>
<Wix xmlns="">
<Product Id="*" UpgradeCode="BED92ED4-C85E-4EFE-82AF-88AC26CFF875" Version="" Language="1033" Name="rsync-mingw64" Manufacturer="Yuanle Song">
<Package InstallerVersion="300" Compressed="yes"/>
<Media Id="1" Cabinet="" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Feature Id="MainApplication" Title="Main Application" Level="1">
<ComponentGroupRef Id="RsyncHeatGenerated" />
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment