2010-03-01 53 views
13

一组软件产品的区别仅在于其资源字符串,二进制资源以及Visual Studio Setup项目使用的字符串/图形/产品密钥。创建,组织和维护它们的最佳方式是什么?相同来源,具有不同资源的多个目标(Visual Studio .Net 2008)

即所有产品基本上由图形,字符串和其他资源数据定制的相同核心功能组成,以形成每个产品。 想象一下,您正在创建一系列产品,如“银行家的Excel”,“园丁的Excel”,“首席执行官的Excel”等。每个产品具有相同的功能,但名称,图形,帮助文件,包含的模板等不同。

中,这些正在兴建的环境是:香草Windows.Forms的/ Visual Studio 2008中/ C#/ .NET

如果我介绍一个新的字符串理想的解决方案将是很容易保持如。 /新的资源项目我没有添加资源,应该在编译时失败,而不是运行时(并且后续产品的本地化也应该是可行的)

希望我已经错过了这一切的这种盲目显而易见的方式。它是什么?

============澄清(S)=====

所谓 “产品” 我指的是包由安装程序安装并销售给最终用户的软件。

目前我有一个解决方案,由多个项目(包括一个安装项目)组成,它构建一组程序集并创建一个安装程序。

我需要制作的是多个产品/安装程序,它们都具有类似的功能,它们是从同一套程序集构建而成,但其中一个程序集使用的资源集不同。这样做的最好方法是什么?

------------ 95%的解决方案-----------------

基于Daminen_the_unbeliever的答案,一个资源文件每个配置可以实现如下:

  1. 创建一个类库项目(“卫星”)。
  2. 删除默认的cs文件,并添加一个文件夹(“默认”)
  3. 文件夹中创建一个资源文件“为MyResources”
  4. 属性 - 设置CustomToolNamespace的东西 适当的(如“XXX”)
  5. 确保资源的访问修饰符是“公共”。添加 的资源。编辑源代码。 参考资源,你的代码 为XXX.MyResources.ResourceName)
  6. 为每个产品变型(“ConfigN”)
  7. 对于每个产品结构的变形,创建一个文件夹(“VariantN”)
  8. 复制并将MyResources文件粘贴到每个VariantN文件夹中
  9. 卸载“Satellite”项目并编辑。csproj文件
  10. 对于每个“VariantN/MyResources”<Compile><EmbeddedResource>标记, 添加Condition="'$(Configuration)' == 'ConfigN'"属性。
  11. 保存,重新加载的.csproj,你就大功告成了...

这将创建一个每个配置资源文件,它可以(大概)进一步本地化。编译错误消息是针对缺少资源的任何配置生成的。资源文件可以使用标准方法进行本地化(创建第二个资源文件(MyResources.fr.resx)并像以前一样编辑.csproj)。

这是一个95%解决方案的原因是,用于初始化表单(例如表格标题,按钮文本)的资源不能以相同的方式轻松处理 - 最简单的方法似乎是用来自卫星组件。

+0

这个问题有点不清楚。我真的建议你回顾一下你最初的问题,并重新发布在Visual Studio中使用技术术语以及隔离你的问题。 – Roast 2010-03-01 19:57:45

+0

补充说明。目前正在根据构建配置编辑.csproj文件以包含替换资源文件。凌乱保持。有人知道这是否实用? – MZB 2010-03-01 23:29:19

+0

另外考虑创建一个工具来比较资源,以确保两个文件中存在相同的资源集合以减少回归测试...任何人都知道这样的工具是否存在? – MZB 2010-03-03 21:45:56

回答

11

您可以添加条件到MSBuild文件中的元素。因此,例如,如果您有“调试”资源和“发布”资源,则可以将它们放在两个单独的文件夹中(例如调试和发布)。然后,你的MSBuild文件中,你可能有:

<ItemGroup> 
    <Compile Include="Debug\Resource1.Designer.cs" Condition=" '$(Configuration)' == 'Debug' "> 
     <AutoGen>True</AutoGen> 
     <DesignTime>True</DesignTime> 
     <DependentUpon>Resource1.resx</DependentUpon> 
    </Compile> 
    <Compile Include="Program.cs" /> 
    <Compile Include="Properties\AssemblyInfo.cs" /> 
    <Compile Include="Queue.cs" /> 
    <Compile Include="Release\Resource1.Designer.cs" Condition=" '$(Configuration)' == 'Release' "> 
     <AutoGen>True</AutoGen> 
     <DesignTime>True</DesignTime> 
     <DependentUpon>Resource1.resx</DependentUpon> 
    </Compile> 
    <Compile Include="Stack.cs" /> 
    </ItemGroup> 
    <ItemGroup> 
    <Content Include="XMLFile1.xml" /> 
    </ItemGroup> 
    <ItemGroup> 
    <EmbeddedResource Include="Debug\Resource1.resx" Condition=" '$(Configuration)' == 'Debug' "> 
     <Generator>ResXFileCodeGenerator</Generator> 
     <LastGenOutput>Resource1.Designer.cs</LastGenOutput> 
     <CustomToolNamespace>Resources</CustomToolNamespace> 
    </EmbeddedResource> 
    <EmbeddedResource Include="Release\Resource1.resx" Condition=" '$(Configuration)' == 'Release' "> 
     <Generator>ResXFileCodeGenerator</Generator> 
     <LastGenOutput>Resource1.Designer.cs</LastGenOutput> 
     <CustomToolNamespace>Resources</CustomToolNamespace> 
    </EmbeddedResource> 
    </ItemGroup> 

提供了所有你访问你的资源都可以通过Resources.Resource1类,那么你得到两套不同的资源用于调试和发布版本。显然,这可以扩展到进一步的配置。

不幸的是,我不认为你可以强制资源使用相同的baseName(提供给ResourceManager构造函数),因为它基于项目内的路径,而且我找不到一种方法来覆盖。如果您确实需要它们使用相同的名称(例如,如果您手动创建ResourceManagers),那么我会建议在项目的顶层有一个Resources1.resx(加上相关的cs文件),而不是源代码管理。作为预生成事件,根据需要将所需的.resx文件从Debug或Release目录中复制出来。 (在这种情况下,你可能要迫使它的子目录中的不编译了.Designer.cs文件。

编辑

忘了提(尽管它从上面摘录见过MSBuild的文件),您必须设置自定义工具命名空间上的每个.resx文件相同的值(例如资源),否则它也默认为包括文件夹名称。

编辑2

响应查询一下检查每个资源文件是否包含相同的资源 - 如果您正在使用Resource类(例如, Resources.Resource1.MyFirstStringResource)来访问你的资源,那么如果所需的资源不存在,切换配置会导致构建错误,所以你会很快找到它。

对于真正的偏执狂(即如果您的构建过程需要3天来构建所有配置,或者同样疯狂),在一天结束时,.resx文件只是XML文件 - 您只需要一些东西来检查每个具有相同文件名的.resx文件包含相同数量的<数据>元素,具有相同的名称属性。

+0

我认为这就是我正在寻找的东西 - 只需要弄清楚如何从这里到达那里......(找不到除MSBuild格式的参考文档之外的东西,并且不确定它与IDE的交互。)看起来我应该为每个产品(在IDE中)创建一个额外的资源文件,每个资源文件位于单独的目录中,仅引用程序代码中的资源,然后根据上述内容编辑.csproj文件,以仅编译/嵌入适当的资源每个配置。我的理解是否正确? – MZB 2010-03-03 21:36:23

+0

@Mike - 好吧,上面摘录自我的“play area”.csproj文件只用了五分钟就敲完了。本身没有IDE支持,但在IDE中的配置之间切换时它编译得很好。一旦创建了两个具有相同名称(位于不同目录中)的资源文件并更改了它们的命名空间,那么在对csproj文件进行条件编辑之前,至少会发生构建错误。 – 2010-03-04 07:11:25

0

您正在寻找多种配置?看看:Build Configurations

+0

我看不到一种方法来根据构建配置来改变项目中使用的资源 - 或者我错过了什么? – MZB 2010-03-01 20:35:33

+0

我想你错过了什么。使用VS 2008点击<配置管理器>并创建一个新的配置“测试”并复制您的发布调试配置。 然后点击<...属性>,它会弹出一个多标签的对话框,让你改变资源,添加后生成命令(可以是你喜欢的任何程序),设置,文件路径等。 因此,假设你想要4种不同的配置,他们B1,B2 ..B4。他们都可以构建到不同的目标目录,从不同的目录链接等。 – JonnyBoats 2010-03-02 03:30:39

+0

只有“构建”选项卡似乎允许每个配置选项 - 这限制了我改变输出目录和定义条件定义。问题是4种不同的资源或设置 - 这两种资源或设置似乎都不敏感于选择哪种配置。 – MZB 2010-03-02 12:47:31

1

您的方法 - 使用multiple, separate resource-only projects(和程序集) - 听起来很健全,并且对于本地化应用程序以及其他场景很典型。有一些命名空间和范围问题需要注意 - VS2005总是生成资源类型作为内部(或VB中的朋友),而VS2008允许你改变它。为了能够从主程序中访问多个卫星程序集,您必须做正确的事情 - 公开资源类型的范围。

一旦拥有主DLL和各种资源DLL,就可以选择部署。一种是分别部署不同的DLL,并在运行时加载正确的DLL。假设你的主EXE被称为app.exe;那么对于所有的卫星程序集,您还可以拥有Sat1.dll,sat2.dll,sat3.dll等等。你的安装项目只包含任何合适的DLL。

另一个选择是合并DLL与ILMerge。在这种情况下,你会合并app.exe和sat1.dll,获得app1.exe。同样app.exe + sat2.exe => app2.exe。

要谷歌周围这个,使用“本地化”和“卫星集会”。

3

这是我的解决方案。原来的问题是,Autodesk发布每个AutoCAD dll都有不同的东西,并且每3年就会打破一次兼容性。但我们的代码实际上是一样的。这是Develop-TFS-TFSbuild-DomainControllerInstallationOfApps的一个痛苦点。

的解决方案如下:

  1. 让你妈项目,所有的结构,可以说为AutoCAD 2012
  2. 引用然后创建第二个项目,为AutoCAD 2013在同一个解决方案,参考它自己的DLLS。
  3. 现在您必须为每个项目设置一个编译符号 - 第一个项目为acad2012,第二个为acad2013。
  4. 然后在2013项目中,转到添加现有项目并指向2012项目的来源,然后单击添加按钮右侧的点击并指向添加为链接
  5. 如果2012年和2012年之间存在任何图书馆差异2013,你可以围绕他们#if acad2012 #endif or #if acad2013 #endif

这样,你将有只有一个源代码维护,并有单独编译的模块:)

UPDATE

我需要制作的是多个产品/安装程序,它们都具有类似的功能,这些功能都是由相同的一组程序构建而成,但其中一个程序集使用的资源集不同。这样做的最好方法是什么?

  • 设置的安装程序项目:这正是我们做什么,你需要什么。第5步之后,您必须制作两个安装程序项目。我的意思是Windows Installer Xml projects or WiX projects可以说第一个是2012年,第二个是2013年。接下来的问题是生成包含构建所有组件的XML文件。我使用以下脚本的WiX工具包:

    热。exe文件目录 “$(TARGETDIR)” 〜CG MyAppComponents -dr INSTALLFOLDER -sfrag -srd -var “var.FilesPath” 退房手续 “\ MyAppComponents.wxs”

  • 此脚本将建立与所有MyAppComponents.wxs你需要的文件。如果您想了解Wix,请阅读本书:“WiX 3.6:Windows Installer XML开发人员指南”。阅读完后,我做了所有需要的东西。

    1. 将MyAppComponents.wxs直接添加到您的主安装程序项目(让它为2012)以及任何其他项目“添加为链接”(让它为2013 dlls)。如果您按照步骤5中的说明进行操作,那么您的构建脚本已经可以针对不同版本的依赖程序集进行编译。你想要针对两种不同的依赖关系编译一个源代码吗?这样你就可以得到它 - 一个包含所有内容的.wxs文件,并且在.cs文件中包含指导编译的编译指示。现在

    当你添加新的文件到您的解决方案,你需要将它才能增加你的母亲项目,然后“添加为链接”到其他项目,只在一个地方加入.wxs组件登记让它在所有安装程序中分发。

    使用第6步中的脚本,您将拥有一个.wxs内的所有版本化的dll,这意味着它们将被编译在一个安装程序中。当然,您可以为您的所有版本创建多个不同的安装程序,但从长远来看,只需制作一个安装程序并在安装过程中决定将哪个版本的.dll复制到磁盘或决定运行时需要加载的.dll文件记忆。我选择了决定运行时间,它对我来说工作正常。

    1. 在您的两个安装项目区域准备就绪后,您可以使用TFS Build进行集成。您可以更进一步,在构建过程中添加智能汇编等混淆器,以便在最后有两个或更多独立安装程序,并在包含混淆程序集的不同相关库上单独构建dll。

    上面所述的一切都是直接来自沟渠,它的工作原理。如果我没有清楚地列出所有步骤,只需发一条消息澄清并进一步阐述。

    由于过多的IF和条件会随着时间的推移而出现“另一个Autodesk dll出现”时,我转移了构建配置。我对此不太确定。也许这是一个解决方案,但你必须非常确定你在做什么,以便在这种需求的情况下不会制动TFS Build。

    相关问题