DNN multiple modules on a single package - c#

Is it possible to create a dotnetnuke (v5) package that contains multiple modules?
I mean: there is a "moduleDefinitions" element on the manifest that looks like supporting more than one module, but adding another child to it doesn't sort any effect.
The dnn manifest looks like:
<dotnetnuke type="Package" version="5.0">
<packages>
<package name="MyModuleName" type="Module" version="01.00.00">
<friendlyName>MyModuleName</friendlyName>
<components>
<component type="Module">
<desktopModule>
<moduleName>MyModuleName</moduleName>
<foldername>MyModuleName</foldername>
<supportedFeatures />
<businessControllerClass />
<moduleDefinitions>
<moduleDefinition>...</moduleDefinition>
<!-- this one is ignored -->
<moduleDefinition>...</moduleDefinition>
<moduleDefinitions>
Anyway I need to package two or more modules on the same package. Is it possible?

Multiple module definition elements should work just fine. If there are multiple definitions within a module, when you add the module to the page, an instance of each definition will be added. There will still only be one entry in the extensions list.
If you want two independent modules, you will need two <package> elements (it won't work to have two <component type="Module"> elements in a <package>).

Related

How can I use Wix Properties

I'm working with Wix v4 to create a msi package. I had the problem, that I must set a Property in a CustomAction (C#) at the beginning of the installation.
This works fine, but now I'm a little bit confused. The property can't be used in all my cases.
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<Property Id="ANUMMER" Value="A2000-0000" />
<Binary Id='CustomActionReadConfig' SourceFile='...'/>
<InstallUISequence>
<!-- Set the property over session["ANUMMER"] = "..." -->
<Custom Action="CustomActionReadConfig" Before="AppSearch" />
</InstallUISequence>
The ini file hasn't a problem
<IniFile Id="Programm.ini" Action="createLine" Key="ANUMMER" Name="Programm.ini" Section="Programm" Value="[ANUMMER]" Directory="Dir" />
For the directory I found the follow workaround
<SetDirectory Action="SetApplicationFolder" Id="APPLICATIONFOLDER" Value="[ProgramFilesFolder]\[COMPANYNAME]\[MYPROGRAMM]\[ANUMMER]" Sequence="ui"/>
But the shortcuts can' use it and I didn't find a workaround
<Shortcut Id="DesktopShortcut" Directory="DesktopFolder" Name="Programm [ANUMMER]" WorkingDirectory="Dir" Advertise="yes" Icon="DesktopIcon.exe" IconIndex="0" />
<Shortcut Id="DesktopShortcut" Directory="DesktopFolder" Name="Programm" WorkingDirectory="Dir" Advertise="yes" Icon="StartMenuIcon.exe" IconIndex="0">
<ShortcutProperty Key="Name" Value="Programm [ANUMMER]"/>
</Shortcut>
Like this, I need this property in some further cases. Do I use it wrong or do I have to use an special escape combination? Can't I use properties in Name attributes? Is there an other way, to use the input as variable witch I can set in the CustomAction? Or what is the basic problem, that I can't use such a custom runtime property in sutch ways?
Thanks for help
After searching for further options I found the reason for the problem for this in an other question here: Dynamically assigning name to shortcut at run time in WIX
The property value can be used in Formatted type. I wanted to use it in LongFileNameType (Simple Type) or in strings.
If someone knows a way, to fill a variable at runtime to solve this problem, it would be nice to share it with us.
Info: The value could also be a localization variable with the format !(loc.VARIABLE).

Write Properties (name=value) to a file from an MSBuild project

For an MSBuild project, I would like to output some kind of a .config file that would be redistributed along the generated binary so the parameters used at build time can be checked by the users of the binary, programmatically.
Output file format:
PropertyName1=ValueA
PropertyName2=ValueB
...
Ideally, the list of properties to write would contain just their names. Maybe like:
<ItemGroup>
<MyExposedDictionary Include="Configuration" />
<MyExposedDictionary Include="Platform" />
<MyExposedDictionary Include="PropertyName1" />
...
</ItemGroup>
With MyExposedDictionary being the argument to give to some DotConfigFileWriter task, as well as the path of the destination file.
I found several ways to write down values to a file, including a sub-target with some C# code in it, but I'm new to MSBuild and I'm not sure how I can merge those requirements into a single Target to make it re-usable.
In case someone comes here with the same requirement, here is what I ended up with. Not really happy with the result as I was hoping for something more generic but at least it does the job and blends well in my project:
<Target Name="WriteBuildProperties" BeforeTargets="PreBuildEvent">
<WriteLinesToFile File="$(DotConfigFile)" Overwrite="true" Lines="" />
<WriteLinesToFile File="$(DotConfigFile)" Lines="ProjectName=$(ProjectName)" />
<WriteLinesToFile File="$(DotConfigFile)" Lines="Configuration=$(Configuration)" />
...
</Target>
If someone happen to have a more elegant solution, please jump in!
I am not sure where your problem is located. I have a similar requirement that a file is created by the program which just was compiled. I edited the properties of the project: in the build events enter a Post-build action like
REM create special file
"$(ProjectDir)$(OutDir)MyProgram.exe" /WriteFile MyFile.xml
Of course, you must also change your program such that it does the right thing when called with that parameter (and stops after having completed that action - does not show a GUI or start as a Windows Service).

Registration free (sxs) COM DirectShow filter

There are questions asking on how to get Registration free COM working, and this is not one of those. I have a DirectShow video source filter (catagory 860BB310-5D01-11d0-BD3B-00A0C911CE86) implemented in .Net with the help of an edited version of the code available here: Pure .Net DirectShow Filters by Maxim Kartavenkov.
I need to get ffmpeg to recognize my .Net DirectShow filter as a video source using Registration Free COM (Side by Side / sxs). Built into the .Net framework is support for COM component servers, so theoretically as long as the manifests are correct, ffmpeg should detect the filters.
Here is a snippet of the relevant sections of my manifest files currently.
<!-- FFMPEG MANIFEST -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity name="ffmpeg.exe" version="1.0.0.0" type="win32" processorArchitecture="*"/>
<dependency>
<dependentAssembly asmv2:codebase="DShowVideoFilter.manifest">
<assemblyIdentity name="DShowVideoFilter" version="1.0.0.0" publicKeyToken="26A05D7C90FBA3E8"/>
</dependentAssembly>
</dependency>
</assembly>
<!-- DIRECTSHOW FILTER MANIFEST -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="DShowVideoFilter" version="1.0.0.0" publicKeyToken="26A05D7C90FBA3E8" />
<clrClass
clsid="{65722BE6-3449-4628-ABD3-74B6864F9739}"
progid="DShowVideoFilter.VideoCaptureFilter"
threadingModel="Both"
runtimeVersion="v2.0.50727"/>
<file name="DShowVideoFilter.dll">
</file>
<file name="DShowVideoFilter.tlb">
<typelib
tlbid="{B618E67B-64C8-48E9-9F94-F13214B76808}"
version="1.0"
helpdir=""
flags="hasdiskimage"/>
</file>
</assembly>
So, I get no errors when running ffmpeg (like you would if there was a manifest error) - and I am confident that everything that is configured correctly (related to traditional sxs com loading), the problem I think (unconfirmed) is that ffmpeg loads DShow filters via DirectShow's intelligent connect system, which requires the filter and pins to be registered. Here are some documents that talk about how filters need to be registered that I've found:
#1 Registering DirectShow Filters
#2 Implementing DllRegisterServer
Now, in Maxim Kartavenkov's DShow base classes, he takes care of #2 automatically. Here is a significantly shortened version of the method that registers the filters implementing BaseFilter.
[ComRegisterFunction]
public static void RegisterFunction(Type _type)
{
AMovieSetup _setup = (AMovieSetup)Attribute.GetCustomAttribute(_type, typeof(AMovieSetup));
BaseFilter _filter = (BaseFilter)Activator.CreateInstance(_type);
string _name = _filter.Name;
DsGuid _category = new DsGuid(_setup.Category);
IFilterMapper2 _mapper2 = (IFilterMapper2)new FilterMapper2();
RegFilter2 _reg2 = new RegFilter2();
_reg2.dwVersion = (int)_setup.Version;
_reg2.dwMerit = _setup.FilterMerit;
_reg2.rgPins = IntPtr.Zero;
_reg2.cPins = 0;
IntPtr _register = Marshal.AllocCoTaskMem(Marshal.SizeOf(_reg2));
Marshal.StructureToPtr(_reg2, _register, true);
hr = _mapper2.RegisterFilter(_type.GUID, _name, IntPtr.Zero, _category, _instance, _register);
Marshal.FreeCoTaskMem(_register);
}
That is the method (particularly mapper2.RegisterFilter) that allows ffmpeg to find the DShow filter when it is registered traditionally (with RegAsm) into the registry, which creates registry keys for the filter and pins as described by #2 link.
tldr;
So the question is, how to emulate the function of RegisterFilter or the intelligent connect registry entries this within a manifest file as to allow the sxs context to find my DirectShow filter when ffmpeg searches for it.
This is almost one of those questions asking on how to get registration-free COM working.
As you correctly say, it's not a problem with getting it to work at the most basic level. However, the fact that the manifest doesn't generate SxS loading errors only means it's a valid manifest XML. To know if it's semantically correct, such as finding missing dependencies or typos in names, CLSIDs and/or versions, test with CLSIDFromProgID followed by CoCreateInstance natively, or Type.GetTypeFromCLSID/Type.GetTypeFromProgID followed by Activator.CreateInstance in .NET.
Unfortunately for cases like this, registration-free COM is only applicable for base COM functionality, like typical class, interface proxy/stub and type library registration, with a tiny bit of OLE (see miscStatus attributes). For categories or subkeys not used by COM itself, registration is necessary.
Why? Because no one else followed lead, not even COM+.

Registering generic types and services with Castle Windsor IoC

Hello again stackoverflowians,
I thought it was about time that I learnt how to use a DI framework. I've heard a lot of good things about Castle Windsor so I decided to go with that. Now there are PLENTY of tutorials out there on how to use it, however, I cannot find much useful information about what to do when Generics get involved. Here is my issue.
I have a BaseDAO
namespace Utilities.DataAccess
{
public class BaseDAO<T> : IBaseDAO<T>
{
public BaseDAO(IConnectionProvider _connectionProvider)
{
// Stuff
}
}
}
Im a little bit new to generics in this context and I have seen some tutorials which have a 'BaseDAO' with no generic declaration and simply the interface it implements with the generics on it. I have used the above way of doing things on many previous projects (without IoC) and its worked fine for me...anyways, onwards to the App.config !
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="castle"
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"></section>
</configSections>
<castle>
<components>
<component
id="BaseDAO"
service="Utilities.DataAccess.Interfaces.IBaseDAO`1, Utilities.DataAccess"
type="Utilities.DataAccess.BaseDAO`1, Utilities.DataAccess" />
<component
id="NHibernateConnection"
service="Utilities.DataAccess.ConnectionProviders.IConnectionProvider, Finchtils"
type="Utilities.DataAccess.ConnectionProviders.NHibernateConnection" />
<component
id="XMLConnection"
service="Utilities.DataAccess.ConnectionProviders.IConnectionProvider, Finchtils"
type="Utilities.DataAccess.ConnectionProviders.XMLConnection, Utilities" />
</components>
</castle>
</configuration>
Now as some of you may of figured by now, this is a utility library. I intend to use this assembly for each project I create so that I don't have to write the same data access code which remains the same across all solutions. The implications of such of course is that I cannot tell castle exactly what type parameter I will pass to the BaseDAO, in one project it might be a Customer object, another entirely different. I have read on other forums that this is entirely possible as when you request the object from the container you can specify the type then like;
BaseDAO<Customer> baseDao = container.Resolve<BaseDAO<Customer>>();
Although it is against my design efforts, I have tried to use the following notation in the App.config
<component
id="BaseDAO"
service="Utilities.DataAccess.Interfaces.IBaseDAO`1[[Utilities.DataInterface.IEntity]], Finchtills.DataAccess"
type="Utilities.DataAccess.BaseDAO`1[[Utilities.DataInterface.IEntity]], Finchtils.DataAccess" />
However, this has not worked either, in any case I get the following error:
Utilities.Testing.DataAccess.Unit.Testing_BaseDAO (TestFixtureSetUp):
System.Exception : The type name Utilities.DataAccess.BaseDAO`1, Utilities.DataAccess could not be located.
----> System.IO.FileNotFoundException : Could not load file or assembly 'Utilities.DataAccess' or one of its dependencies. The system cannot find the file specified.
Reading this error, I think it could be one of two things:
I am missing something from the config file to do with the generics of the types and services.
I have named something incorrectly I.E an assembly name.
I have treated the assembly name as the project that item is contained within, in other words, at no point have i used <solution name>.<project name>.<item folder>.<item name> but merely started at the project level...I assume that any config option would know what solution it is being called from.
Thank you for any help you may be able to give on this subject.
The assembly name can be found in Visual Studio thus:
In the solution explorer, double-click the properties node
Open the Application tab
Assembly name is near the top right corner
Or, if you're compiling at the command line, you use the /out argument.
Also, you need to specify the assembly for the type arguments (inside the square brackets). So, assuming all your types are in the DataAccess assembly, and that the assembly is called (for brevity's sake) "DataAccess":
<component
id="BaseDAO"
service="Utilities.DataAccess.Interfaces.IBaseDAO`1[[Utilities.DataInterface.IEntity, DataAccess]], DataAccess"
type="Utilities.DataAccess.BaseDAO`1[[Utilities.DataInterface.IEntity, DataAccess]], DataAccess" />
But I agree with other commenters that it's better to do the registrations in code. You don't have to use the verbose type syntax, for one, and you get compiler checking of your types. There are some disadvantages, however: it's harder to tell if you have unused types because the registration call counts as using the type.

A design for adding resources to a project

I have classes Project,Resource and File.
where
A Project contains LIST of Resources.
Each Resource contains LIST of of Files of particular type.
This is mapped to an XML :
<Project>
<Resource id=1>
<File id="1" path="" type="A" />
<File id="2" path="" type="B" />
<File id="3" path="" type="B" />
<File id="4" path="" type="B" />
</Resource>
<Resource id=2>
<File id="1" path="" type="A" />
<File id="2" path="" type="B" />
<File id="3" path="" type="B" />
<File id="4" path="" type="B" />
</Resource>
</Project>
So basically every resource has to have at-most one file of type "A" and any number of files of type "B" . The file type is selected by user from a dialog where he selects the file and adds to the resource.
The problem is for every file of type "A", i need to create a new Resource and hence and new node in XML.(which my current code isn't able to do)
Initially i came with the following (generalised for brevity)
Project p =new Project("Untitled project"); //Will happen once per project
Resource res = p.CreateProjectResource("resource1");
//various params to create resource
p.AddResource(res);
//now lets add files to a resource
AddFileHelper(res,"C:\myfile1.bin","A",guid.toString());
AddFileHelper(res,"C:\myfile32.bin","B",guid.toString());
AddFileHelper(res,"C:\myfile56.bin","B",guid.toString());
//The next statement should create a new resource and add the file to
//the new created design
AddFileHelper(res,"C:\myfile4.bin","A",guid.toString()); //
//some helper class :
//Adds a file of type "type" to a resource "res" with file ID as "id"
private AddFileHelper(Resource res,string path,FileType type,string id)
{
// path is user defined file path from OpenFile dialog,
//type is selected from a Dropdown (of Enum values "A","B",...)
//id is GUID
res.AddFile(path,type,id);
//************ OR it could be also written as *******
//ResFile file =new ResFile(path,type,id);
//res.AddFile(file);
//Update XML file here..
}
The main problem is the User does not create the resources "explicitly" (except for the first resource) and creation of new Resource depends on the type of the file being added by the user.
Also due this design it is difficult to figure out the Resource given a File id.
Only way to track is using the file collection in each Resource class.
Any help??
Thanks All.
This is in reference to a question I asked before post
The problem as I understand it:
As of now, your AddFileHelper only adds files to your project resource labeled ''resource1'' which is a problem because every time a filetype “A” is passed your AddFileHelper, you to make a new resource for your project (''resource2'') and add it to that.
There is a very simple way to do this. Within AddFileHelper test the FileType of the added file and determine whether or not you need a new resource to be added to your project. If the type isn't “A” you'll call the code that you have now and add the file with:
res.AddFile(path, type, id);
If the type to add is “A” and you need a new resource, just redefine res and increment a counter variable of how many resources you have in your project:
Resource res = p.CreateProjectResource(resourceName);
resourceCounter++;
Where resourceName is the string:
string resourceName = ''resource'' + resourceCounter;
All this should be implemented as your AddFileHelper method.
Regarding the overall structure of your code, the AddFileHelper should be a project class method. Here's why:
The AddFile method, and the AddFileHelper method sound similar but do two very different things. The AddFile method belongs to the resource class because it acts on a well defined resource object. However, the AddFile method is not enough for your purposes because the resource file to append to is not immediately apparent to the client who has a file and wants to add it to your project. Bbefore the AddFile method can be called, the target resource needs to be determined. The job of the AddFileHelper method is to determine which resource will call the AddFile method. Therefore, the AddFileHelper method belongs to the project class and the AddFile method to the resource class.
The logical connection between the AddFileHelper method and the project class might be more apparent if you renamed the method to FileResourceAssignment or something like that.

Categories