Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2024-04-03 14:27:35 +08:00 committed by GitHub
parent 33eaf2e05c
commit ed257e39d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 349 additions and 181 deletions

7
res/msi/.gitignore vendored
View File

@ -2,3 +2,10 @@
**/bin
**/obj
x64
packages
CustomActions/x64
CustomActions/*.user
CustomActions/*.filters

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<!--
Use supportedRuntime tags to explicitly specify the version(s) of the .NET Framework runtime that
the custom action should run on. If no versions are specified, the chosen version of the runtime
will be the "best" match to what WixToolset.Dtf.CustomAction.dll was built against.
WARNING: leaving the version unspecified is dangerous as it introduces a risk of compatibility
problems with future versions of the .NET Framework runtime. It is highly recommended that you specify
only the version(s) of the .NET Framework runtime that you have tested against.
For more information https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/startup/startup-element
-->
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

View File

@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
using WixToolset.Dtf.WindowsInstaller;
namespace CustomActions
{
public class CustomActions
{
[CustomAction]
public static ActionResult CustomActionHello(Session session)
{
try
{
session.Log("================= Example CustomAction Hello");
return ActionResult.Success;
}
catch (Exception e)
{
session.Log("An error occurred: " + e.Message);
return ActionResult.Failure;
}
}
[CustomAction]
public static ActionResult RunCommandAsSystem(Session session)
{
try
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c " + session["CMD"],
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
Verb = "runas"
};
using (Process process = Process.Start(psi))
{
process.WaitForExit();
}
return ActionResult.Success;
}
catch (Exception e)
{
session.Log("An error occurred: " + e.Message);
return ActionResult.Failure;
}
}
}
}

View File

@ -0,0 +1,63 @@
// CustomAction.cpp : Defines the entry point for the custom action.
#include "pch.h"
#include <shellapi.h>
UINT __stdcall CustomActionHello(
__in MSIHANDLE hInstall
)
{
HRESULT hr = S_OK;
DWORD er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "CustomActionHello");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
// TODO: Add your custom action code here.
WcaLog(LOGMSG_STANDARD, "================= Example CustomAction Hello");
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
UINT __stdcall RemoveInstallFolder(
__in MSIHANDLE hInstall
)
{
HRESULT hr = S_OK;
DWORD er = ERROR_SUCCESS;
int nResult = 0;
wchar_t szCustomActionData[256] = { 0 };
DWORD cchCustomActionData = sizeof(szCustomActionData) / sizeof(szCustomActionData[0]);
hr = WcaInitialize(hInstall, "RemoveInstallFolder");
ExitOnFailure(hr, "Failed to initialize");
MsiGetPropertyW(hInstall, L"InstallFolder", szCustomActionData, &cchCustomActionData);
WcaLog(LOGMSG_STANDARD, "================= Remove Install Folder: %ls", szCustomActionData);
SHFILEOPSTRUCTW fileOp;
ZeroMemory(&fileOp, sizeof(SHFILEOPSTRUCT));
fileOp.wFunc = FO_DELETE;
fileOp.pFrom = szCustomActionData;
fileOp.fFlags = FOF_NOCONFIRMATION | FOF_SILENT;
nResult = SHFileOperationW(&fileOp);
if (nResult == 0)
{
WcaLog(LOGMSG_STANDARD, "The directory \"%ls\" has been deleted.", szCustomActionData);
}
else
{
WcaLog(LOGMSG_STANDARD, "The directory \"%ls\" has not been deleted, error code: 0X%02X.", szCustomActionData, nResult);
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}

View File

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<Configurations>Release</Configurations>
</PropertyGroup>
<ItemGroup>
<Content Include="CustomAction.config" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="WixToolset.Dtf.CustomAction" Version="4.0.5" />
<PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="4.0.5" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,5 @@
LIBRARY "CustomActions"
EXPORTS
CustomActionHello
RemoveInstallFolder

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\WixToolset.WcaUtil.4.0.5\build\WixToolset.WcaUtil.props" Condition="Exists('..\packages\WixToolset.WcaUtil.4.0.5\build\WixToolset.WcaUtil.props')" />
<Import Project="..\packages\WixToolset.DUtil.4.0.5\build\WixToolset.DUtil.props" Condition="Exists('..\packages\WixToolset.DUtil.4.0.5\build\WixToolset.DUtil.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{87e7c13b-ae0e-4048-95cf-4523d510a3cd}</ProjectGuid>
<RootNamespace>CustomActions</RootNamespace>
<PlatformToolset>v143</PlatformToolset>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;EXAMPLECADLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<AdditionalDependencies>msi.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CustomActions.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="CustomActions.def" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\WixToolset.DUtil.4.0.5\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WixToolset.DUtil.4.0.5\build\WixToolset.DUtil.props'))" />
<Error Condition="!Exists('..\packages\WixToolset.WcaUtil.4.0.5\build\WixToolset.WcaUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WixToolset.WcaUtil.4.0.5\build\WixToolset.WcaUtil.props'))" />
</Target>
</Project>

View File

@ -0,0 +1,26 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
BOOL APIENTRY DllMain(
__in HMODULE hModule,
__in DWORD ulReasonForCall,
__in LPVOID
)
{
switch (ulReasonForCall)
{
case DLL_PROCESS_ATTACH:
WcaGlobalInitialize(hModule);
break;
case DLL_PROCESS_DETACH:
WcaGlobalFinalize();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}

View File

@ -0,0 +1,10 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
#include <strsafe.h>
#include <msiquery.h>
// WiX Header Files:
#include <wcautil.h>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="WixToolset.DUtil" version="4.0.5" targetFramework="native" />
<package id="WixToolset.WcaUtil" version="4.0.5" targetFramework="native" />
</packages>

View File

@ -0,0 +1,5 @@
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

View File

@ -0,0 +1,13 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#endif //PCH_H

View File

@ -30,8 +30,8 @@
<Custom Action="CustomActionHello" Before="InstallFinalize" />
<Custom Action="SetCmdRemoveDir" After="RemoveFiles"/>
<Custom Action="RunCommandAsSystem" After="SetCmdRemoveDir"/>
<Custom Action="SetInstallFolder" After="RemoveFiles"/>
<Custom Action="RemoveInstallFolder" After="SetInstallFolder"/>
</InstallExecuteSequence>
<!-- Shortcuts -->

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<?include ../Includes.wxi?>
<Fragment>
<Property Id="AddRemovePropertiesFile" Value="1" />
<!--
Support entries shown when clicking "Click here for support information"
in Control Panel's Add/Remove Programs http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/configuration_properties.asp
-->
Support entries shown when clicking "Click here for support information"
in Control Panel's Add/Remove Programs http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/configuration_properties.asp
-->
<Property Id="ARPCOMMENTS" Value="!(loc.AR_Comment)" />
<Property Id="ARPCONTACT" Value="https://github.com/rustdesk/rustdesk" />
<Property Id="ARPHELPLINK" Value="https://github.com/rustdesk/rustdesk" />

View File

@ -1,22 +1,22 @@
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Fragment>
<?include ../Includes.wxi?>
<Binary Id="Custom_Actions_Dll" SourceFile="$(var.CustomActions.TargetDir)$(var.CustomActions.TargetName).CA.dll" />
<?include ../Includes.wxi?>
<CustomAction Id="CustomActionHello" DllEntry="CustomActionHello" Impersonate="yes" Execute="immediate" Return="ignore" BinaryRef="Custom_Actions_Dll"/>
<CustomAction Id="RunCommandAsSystem" DllEntry="RunCommandAsSystem" Impersonate="no" Execute="immediate" Return="ignore" BinaryRef="Custom_Actions_Dll"/>
<Binary Id="Custom_Actions_Dll" SourceFile="$(var.CustomActions.TargetDir)$(var.CustomActions.TargetName).dll" />
<Property Id="CMD" Value='echo "Hello"' />
<CustomAction Id="SetCmdRemoveDir" Property="CMD" Value='rmdir /s /q "[INSTALLFOLDER]"' />
<CustomAction Id="CustomActionHello" DllEntry="CustomActionHello" Impersonate="yes" Execute="immediate" Return="ignore" BinaryRef="Custom_Actions_Dll"/>
<CustomAction Id="RemoveInstallFolder" DllEntry="RemoveInstallFolder" Impersonate="no" Execute="immediate" Return="ignore" BinaryRef="Custom_Actions_Dll"/>
<Property Id="InstallFolder" Value="C:\Programe Files\$(var.Product)" />
<CustomAction Id="SetInstallFolder" Property="InstallFolder" Value="[INSTALLFOLDER]" />
<!-- Use WixQuietExec to run the commands to avoid the command window popping up. The command line to run needs to be stored
in a property with the same id as the WixQuietExec custom action and the path to the exe needs to be quoted.
A SetProperty action is used to allow the [SystemFolder] reference to be resolved and needs to be scheduled to run before the action.-->
in a property with the same id as the WixQuietExec custom action and the path to the exe needs to be quoted.
A SetProperty action is used to allow the [SystemFolder] reference to be resolved and needs to be scheduled to run before the action.-->
<SetProperty Id="FirewallPortOutAdd" Value="&quot;[SystemFolder]netsh.exe&quot; advfirewall firewall add rule name=&quot;$(var.Product) Service&quot; dir=out action=allow programe=$(var.ProductLower) enable=yes" Before="FirewallPortOutAdd" Sequence="execute" />
<CustomAction Id="FirewallPortOutAdd" DllEntry="WixQuietExec" Execute="deferred" Return="asyncWait" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" />
<SetProperty Id="FirewallPortInAdd" Value="&quot;[SystemFolder]netsh.exe&quot; advfirewall firewall add rule name=&quot;$(var.Product) Service&quot; dir=in action=allow programe=$(var.ProductLower) enable=yes" Before="FirewallPortInAdd" Sequence="execute" />
<SetProperty Id="FirewallPortInAdd" Value="&quot;[SystemFolder]netsh.exe&quot; advfirewall firewall add rule name=&quot;$(var.Product) Service&quot; dir=in action=allow programe=$(var.ProductLower) enable=yes" Before="FirewallPortInAdd" Sequence="execute" />
<CustomAction Id="FirewallPortInAdd" DllEntry="WixQuietExec" Execute="deferred" Return="asyncWait" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" />
<SetProperty Id="FirewallPortRemove" Value="&quot;[SystemFolder]netsh.exe&quot; advfirewall firewall delete rule name=&quot;$(var.Product) Service&quot;" Before="FirewallPortRemove" Sequence="execute" />

View File

@ -4,18 +4,18 @@
<?include ..\Includes.wxi?>
<!--
Properties and related actions for specifying whether to install start menu/desktop shortcuts.
-->
Properties and related actions for specifying whether to install start menu/desktop shortcuts.
-->
<!-- These are the actual properties that get used in conditions to determine whether to
install start menu shortcuts, they are initialized with a default value to install shortcuts.
They should not be set directly from the command line or registry, instead the CREATE* properties
below should be set, then they will update these properties with their values only if set. -->
install start menu shortcuts, they are initialized with a default value to install shortcuts.
They should not be set directly from the command line or registry, instead the CREATE* properties
below should be set, then they will update these properties with their values only if set. -->
<Property Id="STARTMENUSHORTCUTS" Value="1" Secure="yes"></Property>
<Property Id="DESKTOPSHORTCUTS" Value="1" Secure="yes"></Property>
<!-- These properties get set from either the command line, bundle or registry value,
if set they update the properties above with their value. -->
if set they update the properties above with their value. -->
<Property Id="CREATESTARTMENUSHORTCUTS" Secure="yes">
<RegistrySearch Id="CreateStartMenuShortcutsSearch" Root="HKCR" Key="$(var.RegKeyRoot)" Name="STARTMENUSHORTCUTS" Type="raw" />
</Property>
@ -34,8 +34,8 @@
</DirectoryRef>
<!-- If a property value has been passed via the command line (which includes when set from the bundle), the registry search will
overwrite the command line value, these actions temporarily store the command line value before the registry search
is performed so they can be restored after the registry search is complete -->
overwrite the command line value, these actions temporarily store the command line value before the registry search
is performed so they can be restored after the registry search is complete -->
<SetProperty Id="SavedStartMenuShortcutsCmdLineValue" Value="[CREATESTARTMENUSHORTCUTS]" Before="AppSearch" Sequence="first" Condition="CREATESTARTMENUSHORTCUTS" />
<SetProperty Id="SavedDesktopShortcutsCmdLineValue" Value="[CREATEDESKTOPSHORTCUTS]" Before="AppSearch" Sequence="first" Condition="CREATEDESKTOPSHORTCUTS" />

View File

@ -3,9 +3,8 @@
<Property Id="UpgradesFile" Value="1" />
<Upgrade Id="9D8E3E95-42B8-427E-B801-79F3FE7B6DD7">
<UpgradeVersion Property="OLD_VERSION_FOUND" Minimum="2.0.0.0" Maximum="2.99.99" IncludeMinimum="yes" IncludeMaximum="yes" OnlyDetect="no" IgnoreRemoveFailure="yes" MigrateFeatures="yes" />
</Upgrade>
<!--$UpgradeStart$-->
<!--$UpgradeEnd$-->
</Fragment>
</Wix>

View File

@ -4,7 +4,4 @@
<!--$PreVarsStart$-->
<!--$PreVarsEnd$-->
<!-- This should NEVER be changed ! -->
<?define UpgradeCode = "9D8E3E95-42B8-427E-B801-79F3FE7B6DD7" ?>
</Include>

View File

@ -17,6 +17,6 @@
<PackageReference Include="WixToolset.Util.wixext" Version="4.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CustomActions\CustomActions.csproj" />
<ProjectReference Include="..\CustomActions\CustomActions.vcxproj" />
</ItemGroup>
</Project>

View File

@ -4,6 +4,13 @@ Use Visual Studio 2022 to compile this project.
This project is mainly derived from <https://github.com/MediaPortal/MediaPortal-2.git> .
## Steps
1. `python preprocess.py`
2. Build the .sln solution.
Run `msiexec /i package.msi /l*v install.log` to record the log.
## TODOs
1. tray, uninstall shortcut

View File

@ -4,34 +4,39 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.7.34003.232
MinimumVisualStudioVersion = 10.0.40219.1
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Package", "Package\Package.wixproj", "{F403A403-CEFF-4399-B51C-CC646C8E98CF}"
ProjectSection(ProjectDependencies) = postProject
{95BE171E-6438-4F45-9876-0B667D9F7830} = {95BE171E-6438-4F45-9876-0B667D9F7830}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomActions", "CustomActions\CustomActions.csproj", "{95BE171E-6438-4F45-9876-0B667D9F7830}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomActions", "CustomActions\CustomActions.vcxproj", "{87E7C13B-AE0E-4048-95CF-4523D510A3CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Debug|Any CPU.ActiveCfg = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Debug|Any CPU.Build.0 = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Debug|x64.ActiveCfg = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Debug|x64.Build.0 = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Debug|x86.ActiveCfg = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Debug|x86.Build.0 = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Release|Any CPU.ActiveCfg = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Release|Any CPU.Build.0 = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Release|x64.ActiveCfg = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Release|x64.Build.0 = Release|x64
{95BE171E-6438-4F45-9876-0B667D9F7830}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{95BE171E-6438-4F45-9876-0B667D9F7830}.Debug|x64.ActiveCfg = Release|Any CPU
{95BE171E-6438-4F45-9876-0B667D9F7830}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95BE171E-6438-4F45-9876-0B667D9F7830}.Release|Any CPU.Build.0 = Release|Any CPU
{95BE171E-6438-4F45-9876-0B667D9F7830}.Release|x64.ActiveCfg = Release|Any CPU
{95BE171E-6438-4F45-9876-0B667D9F7830}.Release|x64.Build.0 = Release|Any CPU
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Release|x86.ActiveCfg = Release|x64
{F403A403-CEFF-4399-B51C-CC646C8E98CF}.Release|x86.Build.0 = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Debug|Any CPU.ActiveCfg = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Debug|x64.ActiveCfg = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Debug|x86.ActiveCfg = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Release|Any CPU.ActiveCfg = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Release|Any CPU.Build.0 = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Release|x64.ActiveCfg = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Release|x64.Build.0 = Release|x64
{87E7C13B-AE0E-4048-95CF-4523D510A3CD}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -33,24 +33,27 @@ def make_parser():
return parser
def read_lines_and_start_index(file_path, start_tag, end_tag):
def read_lines_and_start_index(file_path, tag_start, tag_end):
with open(file_path, "r") as f:
lines = f.readlines()
start_index = -1
end_index = -1
index_start = -1
index_end = -1
for i, line in enumerate(lines):
if start_tag in line:
start_index = i
if end_tag in line:
end_index = i
if tag_start in line:
index_start = i
if tag_end in line:
index_end = i
if start_index == -1 or end_index == -1:
print("Error: start or end tag not found")
if index_start == -1:
print(f'Error: start tag "{tag_start}" not found')
return None, None
return lines, start_index
if index_end == -1:
print(f'Error: end tag "{tag_end}" not found')
return None, None
return lines, index_start
def insert_components_between_tags(lines, start_index, app_name, build_dir):
def insert_components_between_tags(lines, index_start, app_name, build_dir):
indent = g_indent_unit * 3
path = Path(build_dir)
idx = 1
@ -77,58 +80,48 @@ def insert_components_between_tags(lines, start_index, app_name, build_dir):
{indent}{g_indent_unit}<File Source="{file_path.as_posix()}" KeyPath="yes" Checksum="yes" />
{indent}</Component>
"""
lines.insert(start_index + 1, to_insert_lines[1:])
start_index += 1
lines.insert(index_start + 1, to_insert_lines[1:])
index_start += 1
idx += 1
return True
def gen_auto_component(app_name, build_dir):
target_file = Path(sys.argv[0]).parent.joinpath("Package/Components/RustDesk.wxs")
start_tag = "<!--$AutoComonentStart$-->"
end_tag = "<!--$AutoComponentEnd$-->"
lines, start_index = read_lines_and_start_index(target_file, start_tag, end_tag)
if lines is None:
return False
if not insert_components_between_tags(lines, start_index, app_name, build_dir):
return False
with open(target_file, "w") as f:
f.writelines(lines)
return True
return gen_content_between_tags(
"Package/Components/RustDesk.wxs",
"<!--$AutoComonentStart$-->",
"<!--$AutoComponentEnd$-->",
lambda lines, index_start: insert_components_between_tags(
lines, index_start, app_name, build_dir
),
)
def gen_pre_vars(args, build_dir):
target_file = Path(sys.argv[0]).parent.joinpath("Package/Includes.wxi")
start_tag = "<!--$PreVarsStart$-->"
end_tag = "<!--$PreVarsEnd$-->"
def func(lines, index_start):
upgrade_code = uuid.uuid5(uuid.NAMESPACE_OID, app_name + ".exe")
lines, start_index = read_lines_and_start_index(target_file, start_tag, end_tag)
if lines is None:
return False
indent = g_indent_unit * 1
to_insert_lines = [
f'{indent}<?define Version="{args.version}" ?>\n',
f'{indent}<?define Manufacturer="{args.manufacturer}" ?>\n',
f'{indent}<?define Product="{args.app_name}" ?>\n',
f'{indent}<?define Description="{args.app_name} Installer" ?>\n',
f'{indent}<?define ProductLower="{args.app_name.lower()}" ?>\n',
f'{indent}<?define RegKeyRoot=".$(var.ProductLower)" ?>\n',
f'{indent}<?define RegKeyInstall="$(var.RegKeyRoot)\Install" ?>\n',
f'{indent}<?define BuildDir="{build_dir}" ?>\n',
"\n",
f"{indent}<!-- The UpgradeCode must be consistent for each product. ! -->\n"
f'{indent}<?define UpgradeCode = "{upgrade_code}" ?>\n',
]
indent = g_indent_unit * 1
to_insert_lines = [
f'{indent}<?define Version="{args.version}" ?>\n',
f'{indent}<?define Manufacturer="{args.manufacturer}" ?>\n',
f'{indent}<?define Product="{args.app_name}" ?>\n',
f'{indent}<?define Description="{args.app_name} Installer" ?>\n',
f'{indent}<?define ProductLower="{args.app_name.lower()}" ?>\n',
f'{indent}<?define RegKeyRoot=".$(var.ProductLower)" ?>\n',
f'{indent}<?define RegKeyInstall="$(var.RegKeyRoot)\Install" ?>\n',
f'{indent}<?define BuildDir="{build_dir}" ?>\n',
]
for i, line in enumerate(to_insert_lines):
lines.insert(index_start + i + 1, line)
for i, line in enumerate(to_insert_lines):
lines.insert(start_index + i + 1, line)
with open(target_file, "w") as f:
f.writelines(lines)
return True
return gen_content_between_tags(
"Package/Includes.wxi", "<!--$PreVarsStart$-->", "<!--$PreVarsEnd$-->", func
)
def replace_app_name_in_lans(app_name):
@ -142,6 +135,44 @@ def replace_app_name_in_lans(app_name):
f.writelines(lines)
def gen_upgrade_info(version):
def func(lines, index_start):
indent = g_indent_unit * 3
major, _, _ = version.split(".")
upgrade_id = uuid.uuid4()
to_insert_lines = [
f'{indent}<Upgrade Id="{upgrade_id}">\n',
f'{indent}<UpgradeVersion Property="OLD_VERSION_FOUND" Minimum="{major}.0.0.0" Maximum="{major}.99.99" IncludeMinimum="yes" IncludeMaximum="yes" OnlyDetect="no" IgnoreRemoveFailure="yes" MigrateFeatures="yes" />" ?>\n',
f"{indent}</Upgrade>\n",
]
for i, line in enumerate(to_insert_lines):
lines.insert(index_start + i + 1, line)
return lines
return gen_content_between_tags(
"Package/Fragments/Upgrades.wxs",
"<!--$UpgradeStart$-->",
"<!--$UpgradeEnd$-->",
func,
)
def gen_content_between_tags(filename, tag_start, tag_end, func):
target_file = Path(sys.argv[0]).parent.joinpath(filename)
lines, index_start = read_lines_and_start_index(target_file, tag_start, tag_end)
if lines is None:
return False
func(lines, index_start)
with open(target_file, "w") as f:
f.writelines(lines)
return True
if __name__ == "__main__":
parser = make_parser()
args = parser.parse_args()
@ -158,6 +189,9 @@ if __name__ == "__main__":
if not gen_pre_vars(args, build_dir):
sys.exit(-1)
if not gen_upgrade_info(args.version):
sys.exit(-1)
if not gen_auto_component(app_name, build_dir):
sys.exit(-1)