SQLite 的相对路径不适用于 WIX 工具集

Relative path for SQLite not working with WIX Toolset

我正在使用 SQLite 数据库并使用 WIX 工具集创建 WPF 应用程序的安装程序。问题是,当我从 Visual Studio 直接 运行 时,下面的相对路径工作正常,但是当我使用 WIX 创建安装程序并且安装此安装程序 运行 程序后,它会出现致命错误对于数据库文件。 在项目目录中,我创建了一个数据库文件夹,数据库文件位于其中,如下图所示:

通过WIX Toolset创建安装程序后,安装文件如下:

inventory_control.db 文件路径:

dbConnectionString 路径:

我已经为相对路径连接字符串编写如下代码:

相对路径:

  string relativePath = @"Database\inventory_control.db";
        string currentPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
        //string path = currentPath.Substring(0, currentPath.Length - 21);
        string path = Path.GetDirectoryName(currentPath);
        string absolutePath = System.IO.Path.Combine(path, relativePath);
        string dbConnectionString = string.Format("Data Source={0};Version=3;Pooling=True;Max Pool Size=100;", absolutePath);

        //string dbConnectionString = "Data Source=inventory_control.db";
        sQLiteConnection = new SQLiteConnection(dbConnectionString);

dbConnectionString 给出正确的当前路径。 当我从 Visual Studio 直接 运行 时,上面的相对路径工作正常,但当我使用 WIX 创建安装程序时,它不起作用。它给出了一个致命错误。如何解决?

WIX 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"><?define Inventory Control_TargetDir=$(var.Inventory Control.TargetDir)?>
    <Product Id="f941ba49-4369-44d4-aa0c-b77f20aa41db" Name="Inventory Control" Language="1033" Version="1.0.0.0" Manufacturer="devtros.com" UpgradeCode="ce092371-53cc-4be9-ab5d-c7a2685af970">
        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

    <Icon Id="app_icon.ico" SourceFile="$(var.ProjectDir)app_icon.ico" />
    <Property Id="ARPPRODUCTION" Value="app_icon.ico" />

    <WixVariable Id="WixUIBannerBmp" Value="Images\background.bmp" />
    <WixVariable Id="WixUIDialogBmp" Value="Images\background.bmp" />
    <WixVariable Id="WixUILicenseRtf" Value="$(var.ProjectDir)License.rtf" />

    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
    <UIRef Id="WixUI_InstallDir" />

        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
        <MediaTemplate EmbedCab="yes" />

        <Feature Id="ProductFeature" Title="Inventory Control" Level="1">
            <ComponentGroupRef Id="ProductComponents" />
      <ComponentRef Id="ApplicationShortcut" />
      <ComponentRef Id="ApplicationShortcutDesktop" />
            <ComponentGroupRef Id="Database_files" />
        </Feature>
    </Product>

    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLFOLDER" Name="Inventory Control">
          <Directory Id="Files" Name="Files" />
          <Directory Id="Database" Name="Database" />
        </Directory>
            </Directory>
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ApplicationProgramsFolder" Name="Inventory Control" />
      </Directory>
      <Directory Id="DesktopFolder" Name="Desktop" />
        </Directory>
    </Fragment>

  <Fragment>
    <DirectoryRef Id="ApplicationProgramsFolder">
      <Component Id="ApplicationShortcut" Guid="9bd13330-6540-406f-a3a8-d7f7c69ae7f9">
        <Shortcut Id="ApplicationStartMenuShortcut" Name="Inventory Control" Description="Inventory Control" Target="[INSTALLFOLDER]Inventory Control.exe" WorkingDirectory="INSTALLFOLDER" />
        <RemoveFolder Id="RemoveApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall" />
        <RegistryValue Root="HKCU" Key="Software\Inventory Control" Name="installed" Type="integer" Value="1" KeyPath="yes" />
      </Component>
    </DirectoryRef>
    <DirectoryRef Id="DesktopFolder">
      <Component Id="ApplicationShortcutDesktop" Guid="cde1e030-eb64-49a5-b7b8-400b379c2d1a">
        <Shortcut Id="ApplicationDesktopShortcut" Name="Inventory Control" Description="Inventory Control" Target="[INSTALLFOLDER]Inventory Control.exe" WorkingDirectory="INSTALLFOLDER" />
        <RemoveFolder Id="RemoveDesktopFolder" Directory="DesktopFolder" On="uninstall" />
        <RegistryValue Root="HKCU" Key="Software\Inventory Control" Name="installed" Type="integer" Value="1" KeyPath="yes" />
      </Component>
    </DirectoryRef>
  </Fragment>

    <Fragment>
        <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
            <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
            <!-- <Component Id="ProductComponent"> -->
                <!-- TODO: Insert files, registry keys, and other resources here. -->
            <!-- </Component> -->
            <Component Id="Inventory_Control.exe" Guid="0a7e7061-201b-4d49-adeb-4449e9c4da3e">
              <File Id="Inventory_Control.exe" Name="Inventory Control.exe" Source="$(var.Inventory Control_TargetDir)Inventory Control.exe" />
            </Component>
            <Component Id="Inventory_Control.exe.config" Guid="28323615-8159-4116-b1ac-e29a70bf2593">
              <File Id="Inventory_Control.exe.config" Name="Inventory Control.exe.config" Source="$(var.Inventory Control_TargetDir)Inventory Control.exe.config" />
            </Component>
            <Component Id="System.Windows.Controls.Input.Toolkit.dll" Guid="7d678201-767a-416b-b645-b2cb7d514893">
              <File Id="System.Windows.Controls.Input.Toolkit.dll" Name="System.Windows.Controls.Input.Toolkit.dll" Source="$(var.Inventory Control_TargetDir)System.Windows.Controls.Input.Toolkit.dll" />
            </Component>
            <Component Id="System.Data.SQLite.dll" Guid="178a5aef-c027-4215-81ae-f148ab6cd472">
              <File Id="System.Data.SQLite.dll" Name="System.Data.SQLite.dll" Source="$(var.Inventory Control_TargetDir)System.Data.SQLite.dll" />
            </Component>
            <Component Id="Zen.Barcode.Core.dll" Guid="20e34fc3-0066-4ffd-b401-518bc1177098">
              <File Id="Zen.Barcode.Core.dll" Name="Zen.Barcode.Core.dll" Source="$(var.Inventory Control_TargetDir)Zen.Barcode.Core.dll" />
            </Component>
            <Component Id="WPFToolkit.dll" Guid="8d974e65-defb-4675-b9e0-ff617e5ab1da">
              <File Id="WPFToolkit.dll" Name="WPFToolkit.dll" Source="$(var.Inventory Control_TargetDir)WPFToolkit.dll" />
            </Component>
        </ComponentGroup>
    </Fragment>

  <Fragment>
    <ComponentGroup Id="Database_files" Directory="Database">
      <Component Id="Database_inventory_control.db" Guid="0104b919-0aa9-4dc5-9492-14c474d97cf1">
        <File Id="Database_inventory_control.db" Name="inventory_control.db" Source="$(var.Inventory Control_TargetDir)Database\inventory_control.db" />
      </Component>
    </ComponentGroup>
  </Fragment>
</Wix>

SQLite.Interop.dll: The file SQLite.Interop.dll needed to be installed along with the rest of the runtime files in order for SQLite to function properly.

There are two flavors of the file, x86 and x64 format. It is probably advisable to install both files in their respective folders:

Your installation folder hierarchy - mock-up:

  • YourBinary.exe
  • x86\SQLite.Interop.dll
  • x64\SQLite.Interop.dll
  • System.Data.SQLite.dll
  • Etc...

Read-Write DB Location: And then your database should be stored in a writeable path (or you need to make the path writeable for regular users using custom ACL permissioning - which is never a great idea).

Exceptions: Obviously try - catch your database connection, update and access code to detect these kinds of issues.


  1. 文件夹混乱: 数据库文件夹里面有没有数据库文件?它有点像 inventory_control.db 文件安装到主应用程序文件夹,而不是 Database 子文件夹?

    • 也许该文件是由 application.exe 在错误的文件夹中生成的?
    • 或者您出于测试目的复制了主文件夹中的文件?
  2. Hard-Coded Dev-Box Sins?Inventory Control.exe.config?

    • 那里是否有相关设置可以覆盖您的代码值?
    • 里面会不会有硬编码的开发箱问题?
  3. Path Builder:我假设您在启动期间拥有来自应用程序的 "message boxed" 路径,以确保它们是正确的?我喜欢复制路径并执行 Start => Run 并粘贴路径以查看它是否打开。当消息框显示时按 CTRL + C。粘贴到记事本中。提取路径在Start => Run.

    中试试
    • string path = currentPath.Substring(0, currentPath.Length - 21);。硬编码文件名字符数获取父目录路径不是很健壮吗?
    • 你能用Path.GetDirectoryName(currentPath)改进一下吗?
    • 或者甚至:string dir = currentPath.Substring(0,currentPath.LastIndexOf('\'));
  4. 附加调试器和调试二进制文件?:也许您可以安装调试二进制文件并附加到它们以进行调试此处描述:。只是为了获得真正的逐步调试会话。

  5. Path Spaces:那个数据库连接字符串。它的路径需要引号吗?如 "path with spaces"?您的 visual Studio 项目的路径中可能没有任何空格,但安装后路径中有空格。


你源代码中的这个结构看起来很奇怪,为什么有必要?:

  • <?define Inventory Control_TargetDir=$(var.Inventory Control.TargetDir)?>