Wix : 如何安装共享文件夹

Wix : how to install a shared folder

我是 运行 WiX 3.11,带有 C# VSTO 加载项。 我需要创建一个功能来安装一个文件夹,注册它以便与所有人共享并在卸载时删除共享。

我尝试了 2 种不同的方法但没有成功(为简化起见更改了名称和 ID):

  1. 在下面链接的帮助下,我尝试在创建文件夹时创建权限:
    WiX set App_Data folder permission to modify for NetworkService
    Wix: CustomAction to set Folder permissions
 <Directory Id="TARGETDIR" Name="SourceDir">    
   <Directory Id="WINDOWSVOLUME">
    <Directory Id="INSTALLFOLDER" Name=".">
     <Directory Id="FOLDERTOSHARE" Name="Share">
       <Component Id="ShareFolderPermissions" Guid="SOMEGUID">
         <CreateFolder>
           <util:PermissionEx User="Everyone" GenericAll="yes" />
         </CreateFolder>
       </Component>
     </Directory>
   </Directory>
 </Directory>

在我的新功能中引用了 ShareFolderPermissions。
我试过稍微调整一下,但对我不起作用。

  1. 我的第二个解决方案是尝试通过 CustomActions 使用 Windows 命令来完成工作(剧透:无论如何我稍后都需要 CustomActions)。
    它在某些时候工作得很好,但我一直无法实施整个过程。

我使用了一个非英语网站来设置如何创建一个 WiX CustomAction 项目以导入我的 Product.wxs 文件,我在下面给出了帮助我在 C# 中设置命令行的内容.
How to use Windows command with C#
Net share documentation

Product.wxs (xml):

<?if $(var.Configuration) = MyShareConfiguration?>
  <Property Id="SHAREFEATURE" Value="1" />
<?endif?>
  
<Feature Id="ShareFeature" Title="ShareSetup" Level="0">
  <Condition Level="1">SHAREFEATURE</Condition>
  <ComponentGroupRef Id="MyShareFiles"/>
</Feature>
  
<CustomAction Id="CustomActionShareFolder" BinaryKey="CustomActionProject" DllEntry="ShareFolder" Execute="immediate" Return="check" Impersonate="no" />
<CustomAction Id="CustomActionUnShareFolder" BinaryKey="CustomActionProject" DllEntry="UnShareFolder" Execute="immediate" Return="check" Impersonate="no" />

<Binary Id="CustomActionProject" SourceFile="CustomActionProjectPath" />

<InstallExecuteSequence>
  <Custom Action="CustomActionShareFolder" After="InstallFiles"> SHAREFEATURE AND (NOT REMOVE) </Custom>
  <Custom Action="CustomActinUnShareFolder" Before="RemoveFiles"> SHAREFEATURE AND (REMOVE~="ALL") </Custom>
</InstallExecuteSequence>

CustomAction.cs 在我的 CustomAction 项目 (C#) 中,为清楚起见删除了日志:

private static readonly string SHAREFEATURENAME= "MyShareFeatureName";
private static void ExecuteCMD(string command) 
{
    System.Diagnostics.Process process = new System.Diagnostics.Process();
    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
    {
        WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
        FileName = "CMD.exe",
        Arguments = command,
        CreateNoWindow = true,
        UseShellExecute = true,
        Verb = "runas"
    };
    process.StartInfo = startInfo;
    process.Start(); 
}

[CustomAction] 
public static ActionResult ShareFolder(Session session)
{
    ActionResult result = ActionResult.Success;
    string directoryPath = session.GetTargetPath("FOLDERTOSHARE"); // See Directory setup in 1.
    string command = string.Format("/c net share {0}=\"{1}\"", SHAREFEATURENAME, directoryPath.Remove(directoryPath.Length - 1)); // Remove '\' at the end of the path

    try
    {
        ExecuteCMD(command);
    }     
    catch (Exception)
    {
        result = ActionResult.Failure;
    }

    return result; 
}

[CustomAction] 
public static ActionResult UnShareFolder(Session session) 
{
    ActionResult result = ActionResult.Success;
    string command = string.Format("/c net share {0} /delete", SHAREFEATURENAME);

    try
    {
        ExecuteCMD(command);
    }
    catch (Exception)
    {
        result = ActionResult.Failure;
    }

    return result; 
}

我已经在一个单独的应用程序项目中使用从我的 msi 日志中获得的硬编码值测试了我的命令。

msiexec /i "C:\MyPackage\Example.msi" /L*V "C:\log\example.log"

来自单独项目的代码(故意更改名称):

static void Main(string[] args)
{
    string command = "/c net share SHAREFEATURENAME=\"MyFolderPath\"";
    //string command = "/c net share SHAREFEATURENAME /delete";

     Console.WriteLine("Command : " + command);

     Process cmd = new Process();
     cmd.StartInfo.FileName = "cmd.exe";
     cmd.StartInfo.RedirectStandardInput = true;
     cmd.StartInfo.RedirectStandardOutput = true;
     cmd.StartInfo.CreateNoWindow = true;
     cmd.StartInfo.UseShellExecute = false;
     cmd.StartInfo.Arguments = command;
     cmd.StartInfo.Verb = "runas";
     cmd.Start();

     cmd.StandardInput.WriteLine("echo test");
     cmd.StandardInput.Flush();
     cmd.StandardInput.Close();
     cmd.WaitForExit();
     Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}

只要 VS 以管理员身份运行,来自单独项目的代码就可以正常工作。
在我的 msi 中,我设置了 Impersonate="no",因此它要求提升安装/卸载权限。

两个命令都被正确调用并且结束时没有错误。但是,永远不会共享目标文件夹。

有人可以帮我吗?

据我所知,您所描述的应该可以通过 built-in WiX 构造来实现。这里有一些提示,我想避免过多的代码和标记重复。请至少遵循 link 2。 Link 1 只是为了记录:

  1. (我知道你说你需要它们)。

  2. 也许试试this WiX sample for folder sharing