2010-03-01 8 views
13

Un conjunto de productos de software difiere solo por sus cadenas de recursos, recursos binarios y por las cadenas/gráficos/claves de producto utilizadas por sus proyectos de instalación de Visual Studio. ¿Cuál es la mejor manera de crearlos, organizarlos y mantenerlos?Mismo origen, destinos múltiples con recursos diferentes (Visual Studio .Net 2008)

es decir, todos los productos consisten esencialmente en la misma funcionalidad básica personalizada por gráficos, cadenas y otros datos de recursos para formar cada producto. Imagine que está creando un conjunto de productos como "Excel for Bankers", Excel for Gardeners "," Excel for CEOs ", etc. Cada producto tiene la misma funcionalidad, pero difiere en nombre, gráficos, archivos de ayuda, plantillas incluidas, etc. .

El entorno en el que éstos se están construyendo es: Windows.Forms vainilla/Visual Studio 2008/C#/.NET

La solución ideal sería fácil de mantener por ejemplo, si introduzco una nueva cadena../Los nuevos proyectos de recursos a los que no he agregado el recurso deberían fallar en tiempo de compilación, no de ejecución (y la posterior localización de los productos también debería ser factible).

Espero haberme perdido la manera obvia y fácil de hacer todo esto. ¿Qué es?

Aclaración ============ (s) ================

Por "producto" me refiero al paquete de software que el instalador instala y vende al usuario final.

Actualmente tengo una solución, que consta de varios proyectos (incluido un proyecto de configuración), que crea un conjunto de conjuntos y crea un único instalador.

Lo que necesito para producir son múltiples productos/instaladores, todos con funcionalidades similares, que se construyen a partir del mismo conjunto de ensambles pero difieren en el conjunto de recursos utilizados por uno de los ensamblajes. ¿Cuál es la mejor manera de hacer esto?

------------ La Solución 95% ----------------- En base a la respuesta de Daminen_the_unbeliever, un archivo de recursos

por configuración se puede lograr de la siguiente manera:

  1. Cree un proyecto de biblioteca de clase ("Satélite").
  2. Eliminar el archivo .cs por defecto y añadir una carpeta ("Default")
  3. Crear un archivo de recursos en la carpeta "MyResources"
  4. Propiedades - establecer CustomToolNamespace a algo apropiado (por ejemplo, "XXX")
  5. Asegúrese de que el modificador de acceso para los recursos sea "Público". Agregue los recursos. Edita el código fuente. Consulte los recursos en su código como XXX.MyResources.ResourceName)
  6. crear configuraciones para cada variante de producto ("ConfigN")
  7. Para cada variante de producto, crear una carpeta ("VariantN")
  8. Copiar y Pegue el archivo MyResources en cada carpeta VariantN
  9. Descargue el proyecto "Satélite" y edítelo.archivo csproj
  10. Para cada etiqueta "VariantN/MyResources" <Compile> o <EmbeddedResource>, agregue un atributo Condition="'$(Configuration)' == 'ConfigN'".
  11. Guardar, recargar la .csproj, y ya está ...

Esto crea un archivo de recursos per-configuración, que puede (presumiblemente) se localizó posteriormente. Los mensajes de error de compilación se producen para cualquier configuración en la que falta un recurso. Los archivos de recursos pueden ser localizados usando el método estándar (crear un segundo archivo de recursos (MyResources.fr.resx) y editar .csproj como antes).

La razón por la cual esta es una solución del 95% es que los recursos utilizados para inicializar formularios (por ejemplo, títulos de formularios, textos de botones) no se pueden manejar fácilmente de la misma manera; el enfoque más fácil parece ser sobrescribirlos con valores de el conjunto satelital.

+0

La pregunta es un poco confusa para mí. Realmente te sugiero que revises tu pregunta inicial y vuelvas a publicar usando los términos técnicos en Visual Studio, así como aislar tu pregunta. – Roast

+0

Aclaraciones adicionales. Actualmente estamos buscando editar el archivo .csproj para incluir un archivo de recursos de reemplazo de acuerdo con la configuración de compilación. Desordenado para mantener. ¿Alguien sabe si esto es práctico? – MZB

+0

También considera crear una herramienta para comparar recursos para garantizar que exista el mismo conjunto de recursos en dos archivos para reducir las pruebas de regresión ... ¿Alguien sabe si existe una herramienta de este tipo? – MZB

Respuesta

11

Puede agregar condicionales a elementos dentro del archivo MSBuild. Por ejemplo, si tiene recursos "Debug" y recursos "Release", puede colocarlos en dos carpetas separadas (por ejemplo, Depurar y Liberar). Luego, dentro de su archivo de MSBuild que pueda tener:

<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> 

proporcionado todo de su acceso a los recursos son a través de la clase Resources.Resource1, a continuación, obtener dos conjuntos diferentes de recursos para la depuración y las versiones de lanzamiento. Obviamente, esto se puede extender a otras configuraciones.

Desafortunadamente, no creo que pueda forzar a los recursos a usar el mismo nombre base (proporcionado al constructor de ResourceManager), ya que se basa en la ruta dentro del proyecto y no puedo encontrar una manera de anularlo . Si necesita que utilicen el mismo nombre (si está creando manualmente ResourceManagers, por ejemplo), le sugiero que tenga un Resources1.resx (más el archivo cs asociado) en el nivel superior del proyecto, y no debajo de fuente de control. Como evento previo a la compilación, copie el archivo .resx requerido del directorio Debug o Release, según corresponda. (En esta situación, lo que probablemente quiere forzar a que no se compile los archivos .Designer.cs dentro de los subdirectorios.

Edición

se olvidó de mencionar (aunque se ha visto en el extracto anterior de la archivo de MSBuild) que usted tiene que fijar la herramienta de espacio de nombres personalizado en cada archivo .resx en el mismo valor (por ejemplo, recursos), de lo contrario, también por defecto incluyendo el nombre de la carpeta.

Editar 2

en respuesta para consultar sobre verificando que cada archivo de recursos contenga los mismos recursos: si está utilizando la clase Resource (p. Resources.Resource1.MyFirstStringResource) para acceder a sus recursos, el cambio de configuraciones dará como resultado errores de compilación si el recurso requerido no existe, por lo que lo encontrará con bastante rapidez.

Para los verdaderamente paranoicos (es decir, si su proceso de creación demora 3 días para construir todas las configuraciones, o algo igualmente loco), al final del día, los archivos .resx son solo archivos XML; solo necesita algo para verificar que cada archivo .resx con el mismo nombre de archivo contiene el mismo número de elementos < de datos >, con los mismos atributos de nombre.

+0

Creo que esto es lo que estoy buscando, solo tengo que descubrir cómo llegar desde aquí ... (No puedo encontrar nada que no sea documentación de referencia en el formato MSBuild, y no estoy seguro de su interacción con el IDE). Parece que debería crear 1 archivo de recursos adicional para cada producto (en el IDE), cada uno en directorios separados, solo consulte Recursos en el código del programa, luego edite el archivo .csproj por encima para solo compilar/incrustar el recurso apropiado en cada configuración Es mi entendimiento correcto? – MZB

+0

@Mike - Bueno, el fragmento de arriba del archivo .csproj de mi "área de juegos" solo tardó cinco minutos en reunirse. No hay soporte IDE para él per se, pero compila bien al cambiar entre configuraciones en el IDE. Una vez que haya creado dos archivos de recursos con el mismo nombre (en diferentes directorios) y haya cambiado su Namespace, al menos obtendrá errores de compilación hasta que haya realizado las modificaciones condicionales en el archivo csproj. –

0

¿Es lo que está buscando para múltiples configuraciones? Eche un vistazo a: Build Configurations

+0

No veo una manera de variar los recursos utilizados en un proyecto de acuerdo con la configuración de compilación, o ¿me he perdido algo? – MZB

+0

Creo que te has perdido algo. Con VS 2008, haga clic en y cree una nueva configuración "Test" y copie su configuración de Release of Debug. Luego haga clic en <...Propiedades> que mostrará un cuadro de diálogo con múltiples pestañas que le permitirá cambiar recursos, agregar comandos posteriores a la compilación (que podría ser cualquier programa que desee), configuraciones, rutas de archivos, etc. Supongamos que desea 4 configuraciones diferentes, llame al ellos B1, B2 ..B4. Todos podrían compilarse en diferentes directorios de destino, enlazar desde diferentes directorios, etc. – JonnyBoats

+0

Solo la pestaña "Compilar" parece permitir las opciones de configuración, lo que me limita a cambiar el directorio de salida y definir las definiciones condicionales. El problema es 4 conjuntos diferentes de recursos o configuraciones, ninguno de los cuales parece ser sensible a la configuración elegida. – MZB

1

Su enfoque - de usar multiple, separate resource-only projects (y ensamblajes) - es sonido, y es típico para aplicaciones localizadas, y en otros escenarios. Hay algunos problemas con el espacio de nombres y el alcance que debe tener en cuenta: VS2005 siempre genera tipos de recursos como internos (o Friend en VB), mientras que VS2008 le permite variar eso. Deberá hacer lo correcto para poder acceder a múltiples conjuntos de satélites desde su ensamblaje principal: haga un alcance público de los tipos de recursos.

Una vez que tiene la DLL principal y las diversas DLL de recursos, tiene opciones para la implementación. Una es desplegar las distintas DLL por separado, y cargar la adecuada en tiempo de ejecución. Supongamos que su EXE principal se llama app.exe; entonces también tendrías Sat1.dll, sat2.dll, sat3.dll, ... etc, para todos los ensamblajes satelitales. Sus proyectos de instalación solo incluirían las DLL adecuadas.

La otra opción es fusionar los archivos DLL con ILMerge. En este caso fusionaría app.exe con sat1.dll, obteniendo app1.exe. Del mismo modo, app.exe + sat2.exe => app2.exe.

Para buscar en Google esto, use "localización" y "ensambles de satélite".

3

Aquí está mi solución. El problema original fue que Autodesk libera cada dll de AutoCAD con algo diferente y rompe la compatibilidad cada 3 años. Pero nuestro código es realmente el mismo. Ese fue un punto doloroso en el camino de Develop-TFS-TFSbuild-DomainControllerInstallationOfApps.

La solución es la siguiente:

  1. que su proyecto madre con toda la estructura y, digamos que las referencias para AutoCAD 2012.
  2. A continuación, cree segundo proyecto, para AutoCAD 2013 en la misma solución y referencia su propio DLLS.
  3. Ahora tiene que establecer un símbolo de compilación para cada proyecto: acad2012 en el primer proyecto y acad2013 en el segundo.
  4. Luego, en el proyecto 2013, vaya a Agregar elemento existente y señale las fuentes del proyecto 2012 PERO LUEGO HAGA CLIC a la derecha del botón Agregar y señale Agregar como vínculo
  5. Si hay discrepancias en la biblioteca entre 2012 y 2013 puede rodearlos de #if acad2012 #endif or #if acad2013 #endif

de esa manera usted tendrá un solo código fuente para mantener y tener a los módulos compilados por separado :)

ACTUALIZACIÓN

Lo que necesito producir son múltiples productos/instaladores, todos con funcionalidades similares, que se construyen a partir del mismo conjunto de ensamblajes pero difieren en el conjunto de recursos utilizados por uno de los ensamblajes. ¿Cuál es la mejor manera de hacer esto?

  1. Configuración de los instaladores proyecta: Esto es exactamente lo que hacemos y exactamente lo que necesita. Después del paso 5 debes hacer dos proyectos de instalador. Me refiero a Windows Installer Xml projects or WiX projects Digamos que el primero es para 2012 y uno para 2013. El siguiente problema es la generación de los archivos XML que contienen todos los componentes para la construcción. Uso el kit de herramientas WiX con el siguiente script:

    heat.exe dir "$ (TargetDir)" salida privado -CG MyAppComponents -dr installFolder -sfrag -srd -VAR "var.FilesPath" "\" MyAppComponents.wxs

Este script construye el MyAppComponents.wxs con todo los archivos que necesitas Si desea familiarizarse con Wix vaya a obtener este libro: "WiX 3.6: Una guía de desarrollador para Windows Installer XML". Hice todo lo necesario después de leerlo.

  1. Agregue MyAppComponents.wxs directamente a su proyecto de instalador principal (permite que sea para 2012) y en cualquier otro proyecto "Agregar como enlace" (que sea para 2013 dlls). Si siguió las instrucciones en el paso 5, su script de compilación ya está hecho para compilar contra diferentes versiones de ensamblajes de dependencia. ¿Quieres un código fuente compilado contra dos dependencias diferentes, verdad? De esta forma lo tienes: uno .wxs que contiene todo y dentro de los archivos .cs tienes pragmas que guían la compilación.

Ahora cuando agrega un archivo nuevo a su solución, tendrá que agregarlo en su proyecto Mother luego "agregar como enlace" a sus otros proyectos y agregar el registro del componente en .wxs solo en un lugar para haz que se distribuya en todos los instaladores.

Con la secuencia de comandos desde el paso 6, tendrá todas sus dlls versionadas dentro de un .wxs, lo que significa que se compilarán en un único instalador. Por supuesto, puede hacer varios instaladores diferentes para todas sus versiones, pero a la larga es más sencillo crear un solo instalador y decidir durante la instalación qué versión del .dll se debe copiar en el disco o decidir el tiempo de ejecución que se cargará .dll memoria. Elegí decidir el tiempo de ejecución y funciona bien para mí.

  1. Después de que sus dos proyectos de instalación estén listos, puede usar TFS Build para la integración. Puede ir un paso más allá y agregar un ofuscador como Smart Assembly en su proceso de compilación, de modo que al final tenga dos o más instaladores separados con compilación separada de diferentes bibliotecas dependientes que contengan ensamblajes ofuscados.

Todo lo descrito anteriormente es directamente de trincheras y funciona. Si no expuse todos los pasos, simplemente envíeme un mensaje para aclararlos y profundizar más.

Me alejé de Configuraciones de compilación debido a las demasiadas FI y condiciones en ellas que se acumularán con el tiempo cuando "aparezca otra dll de Autodesk". No estoy muy seguro de esto. Quizás sea una solución, pero debes estar seguro de lo que estás haciendo para no frenar la compilación TFS si es un requisito.

Cuestiones relacionadas