Real-time alterations to XML to change the particle effect - xna

I am currently writing a Particle System using XNA. What I'd like to do is use an external file (XML for example) and be able to modify this file, whilst the application is running, and once saved, the changes will be reflected in the Particle System.
My original proposal:
Use a FileWatcher (can't remember the exact class name) to monitor the particle effect file and when the date changes, reload the file thus causing the changes to be made.
Any help would be appreciated.

You are on the right track.
Create a System.IO.FileSystemWatcher.
Subscribe to the Changed event.
When the Changed event occurs
If the path/file extension corresponds to a buildable resource type
Either
Directly create and invoke a content importer and processor. (Xna 4.0)
Or
Use MSBuild to build a dummy content project.
Replace references to the existing resource with the newly built resource
Dispose of the old resource if necessary
Notes:
The FileSystemWatcher sometimes
generates multiple change events for
a single change. Also, some
programs, like photoshop save to a
temporary file, then delete the
original and rename the temporary
file to the original name. My system
buffers file system events and
combines them into single events
where possible. Because they are
buffered this also allows me to apply
the events to the content at an
appropriate point in the program. If
you don't buffer these events could
trigger while the resource you are
trying to replace is in use.
Shawn Hargreaves has written about Effect compilation and Content Pipeline automation in XNA Game Studio 4.0.
AppHub has a Code Snippet WinForms Series 2: Content Loading which shows how to use MSBuild to build content dynamically. I have found this method is slower than invoking the importer and processor directly.
In my system, all references to dynamic resources are indirect references. These indirect references are allocated and tracked by a resource manager. When a resource is dynamically built the resource manager replaces the actual reference inside the indirect reference. A resource changed event is generated through the indirect reference so clients can take action if required.

Related

How to get access to an object between dynamically loaded packages?

I need to know the user name and other data of the logged-in user in a project organized using BPLs. That is, how and where do I need to declare the user object and its creation, and how to get access to that object when a package is loaded at runtime? I don't have enough experience working with packages.
In a regular app, for the programmer there is no difference between using runtime packages or all in a single exe
You can change the project to go with runtime packages or not, and your code won't change at all
That changes when you make a modular app that loads BPL modules on demand, chosing at runtime if a given module will be load, and doing it dynamically (ex. app made with a plugin-architecture in mind), then you need to design your own strategy to handle that
Myself, I work in that second way, and I do have some main modules wich give services to the "plugins", so when they are loaded, they do register themselves with the system: user control, navigation, whatever
There is nothing special to use objects in a package. You just add the unit name where the object is defined to the uses clause of the unit where the object is to be used.
You should really read the documentation on this topic. The you may ask more questions to clarify things you don't understand.

Download code and execute on-the-fly

Is it possible to download code and execute / inject it when application is executed?
I want to keep my .exe small and up2date without using an updater.
Been searching google for a while, but couldn't find anything execpt for just downloading other .exe's which always triggers Antivir's.
You should put your business logic in dll(s) and only the update logic in the exe. Each time you start the application it should check for updates. If it needs to, it will download new dll(s) and update its functionality.
By making the dll(s) to be dynamically loaded, you need not even restart the application when an update is performed IF you check for updates the first thing after your exe starts.
The process inside the exe would be the following:
1. Start small exe
2. Check for updates. If needed, download dll(s) in the specific location for dll(s).
3. Load dll(s) from that specific location
Of course, for ease in working with it, you should not allow multiple instances because if you already have it started and you start another instance, you will have another case to handle: you try to make an update but the files you need to overwrite are in use...
There is a way in which you can run an exe, injecting it in other process's address space. But for sure your software will be marked as malware by heuristic av's.
Here is the unit that does the trick if you are interested about the concept.

How to use project version information inside a Delphi application?

I use Project Options / Version to manage the version info (N.N.N.N format).
Anyway inside my project I duplicate those info.
So if in project options I am working on release 2.4.3.178
inside my application I have 4 integer variables that hold the 4 numbers.
I manually set them
Major := 2;
Minor := 4;
Release := 3;
Build := 178;
The reason of this is simple: I have licensing based on version number. So if the user buys release "2.4" it is not allowed to upgrade to version "3.0".
But if I rely on project version info the user can (with Resource Hacker tools) change the version info and therefore "activate" the product.
The user cannot change the 4 variables in the same way (not as easily at least).
This works but forces me duplicate the info.
Could you suggest a better approach?
Otherwise said: is there a way to write the version info using the data I write in those 4 variables. Something like in Post Build Events, but how do I pass data to post build events?
You'd need a pre-build event rather than a post-build event since you'd want to get the .res file built before linking.
I do something very similar with a simple Perl script that reads an include file (.inc) containing constant declarations of the version numbers. I read them in using a regex and then create my .rc file which I pass to brcc32. It's all invoked as a pre-build action.
Since you're on Delphi-XE and have Final Builder, why don't you put it to good use and make your "final" build from it? It can give a very nice solution to the version number problem, and can do a lot more.
Here's how I'd do it.
Set up a small INI file that holds the relevant parts of the version information.
Optionally make a small Delphi forms application that reads the version number from the INI files and gives you a chance to change it. When changes are saved to the INI file, the delphi application should automatically generate a small Delphi PAS file that defines the constants!
Create a FinalBuilder project that does the following:
Calls your Delphi exe to set up version number. You'll be in charge of changing whatever needs changing, and this is probably appropriate since your licensing scheme depends on version information.
Set up a few project variables to hold the version information numbers
Add "Read INI file" actions to read the version information from the ini files into your project variables.
(optional) Build the unit test project, if you have one.
(optional) Call the unit test project.
Add a "build Delphi project" action, set it up to build your project using whatever options you need. Add a small "Before" script to set up the version information numbers to what you've got in the project variables you just read from the INI file.
(optional) create setup packages using whatever tool you use.
(optional) upload those setup packages to a website.
In other words, take the opportunity to start using Final Builder.
Moving your version numbers into code is also easy to get around.
One way to pass the information is to generate a version.rc file programmatically (you write a tiny build tool yourself using delphi or a scripting language of your choice), and link the resources to the program, instead of using the built in version-info feature.
Your question seems to be fundamentally a matter of preventing the user from modifying (easily) the version number once you have determined it.
So my suggestion is that you encrypt the version number and you use the encrypted version, instead of the version in the VersionInfo structure.
I have used DCPCRYPT for things like this. But if you hope to be hacker-proof let me just say this; Anything you can do, hackers can undo. If you want to be more secure, you will also need to tamper proof your whole application. There are commercial tamper proofing solutions but none work fabulously out of the box with Delphi.

Need to create a compiled delphi app that can make a separate compiled app

I need to make an app that will let users select some options, click a button, and a separate compiled app is created. Is this possible? I am using delphi 7 and 2010.
Thanks for the replies. Here is a little more info.
It would have to be a graphical app and create a graphical app.
What I want is the user to fire up 'App A' (I originally made), be able to select some options (I apologize for the secrecy. I think this is a million dollar idea that probably 3 people may find useful :) then use the program to create 'App B.' 'App B' can then be distributed to end users and 'App B' is a single executable that includes a compiled app plus the configuration data. I don't care how, but I need 'App B' to be a single executable.
I wouldn't even need to use Delphi for the final compiled app. If there is some sort of "pseudo-compiler" that I can call from Delphi that would marry a precompiled exe and a separate config file into a single executable. That would work just fine as well.
Thank you for the replies and help.
Thank you.
I also faced a similar situation once. I had to produce an exe using my exe. I didn't want to go the compiling a source code because of complexity and license problems.
Lets call the parent app P and child app C. Also lets assume that whatever option C needs can be summed up in a config file (XML/INI etc). What I ended-up doing was:
Create P and C. Inserted C in resource data of P.
When user clicked the button after selecting options, P would extract C from its resource data.
Created an XML file containing the options selected by user and inserted it in C's resource data.
So whenever C will run, it will use the options given in the XML file stuffed in it. It looks like complicated and hacky but is reliable and simple. Do a google on "delphi embedding resource in exe" and you will find plenty of articles to do above.
It is possible. You will need a Delphi 7 (or compatible) compiler (command line at least) on the target machine. You will also need all the source code for the compiled application and that includes all the third party libraries if you use any.
When you have it all set just call the command line compiler (DCC32.EXE) with the proper parameters and paths.
You can use two approaches for this:
Call ShellExecute
Call CreateProcess
You will have more control over the execution with CreateProcess. Also you will have to watch out for legal issues and licences if you plan to use the compiler this way.
Given that the Delphi compiler can't be redistributed, one solution if the user has not a copy of Delphi may be to use a script engine (i.e. RemObjects PascalScript, but there are others), generate code for it, and embed that code (i.e. within a resource) in an executable that will execute it when launched.
Create a separate stub executable that implements all the logic you need, and that reads its configuration from its own local resources (look at the TResourceStream class to help you load a resource at runtime).
Include that stub executable as an RCDATA resource in your main app's resources when it is compiled.
At runtime, the main app can extract the stub executable from its resources when needed, save it to disk, and insert the necessary configuration data into the stub's resources using the Win32 API UpdateResource() function.
Without knowing more about why you think you need to do this, I assume you don't actually need to do this. Given the stated requirements, I'd simply have one app, written in Delphi, that looks for the existence of configuration data (.ini file, registry, etc..) In the absence of this, it presents a screen that "will let users select some options, click a button". Then the options are stored in a .ini file, and the rest of the program proceeds, making use of those options.
Alternately, I'd use some pascal scripting, such as provided by TMS.
If you are looking for a way to crank out custom-branded versions of an app, maybe use Inno Setup with a ResHacker step. i.e. gather requirements in Inno, spit out your .exe into a temp directory, use ResHacker to modify the .exe, copy it into the program folder.

How do you copy arbitrary data to the clipboard as a file?

We develop a database application. The user asks for a new feature: Copy blobs into the clipboard such that Windows Explorer can paste them as new files. One solution is to save the blobs into a temporary folder and add these temporary files to the clipboard.
But I'm looking for a better solution. Is it possible to hook the paste action in Windows Explorer and save the blobs to the destination path by myself?
I've never tried it but I think it is indeed possible. Please take a look at the MSDN Documentation for Shell Clipboard Formats. CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR are the formats you are likely supposed to handle.
Additionally, I found an article at Code Project which provides a demo program: How to drag a virtual file from your app into Windows Explorer.
Update: An example written in .NET:
Creating something from nothing
Creating something from nothing, asynchronously
From the MSDN article Handling Shell Data Transfer Scenarios
Existing files should be offered with the CF_HDROP format.
Offer file-like data with CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR
formats. This approach allows the
target to create a file from a data
object without needing to know
anything about the underlying data
storage. You should normally present
the data as an IStream interface. This
data transfer mechanism is more
flexible than a global memory object
and uses much less memory.
Two other good articles to read from MSDN are:
Shell Data Object
Shell Clipboard Formats
When I first started working on using the clipboard to transfer files I printed off all three articles and read them several times.
Dealing with the interfaces can be quite involved. I have found two good libraries out there to help with this.
The The Drag and Drop Component Suite for Delphi. If you scroll down on the home page you will see some FAQs are good reading. There are also a lot of sample applications with the download. I think the AsyncSource demos should be helpful for what you are looking for. The suite is freeware with source. The code seems to be well commented.
I am currently using the Transfer#Once component from Quasidata. It is not free but is very inexpensive. I initially used Transfer#Once because at the time it was better supported than the Drag and Drop component suite. However, that situation has reversed itself. Transfer#Once does not yet support Delphi 2009. When I get around to moving my application I will probably switch components. The Transfer#Once code is included with purchase. Personally I found the Drag and Drop code to be much easier to read and follow.
I'd say that explorer does the copying to the destination files itself, so there's no way to directly write the destination files. This makes sense, because the names of the source files can only come from the application that copied the data to the clipboard, which need not be explorer. OTOH the names of the destination files may actually differ, because files of the same name could already exist in the destination folder, and only explorer can create the modified names for the destination files (like by prepending "Copy of " or by appending " (2)" to the base file name).
You will need to provide the clipboard format for the Windows Explorer so that it can paste the files. The documentation of standard clipboard formats suggests that CF_HDROP is the right one. With this clipboard format you would provide a list of source file names, but the files do need to exist of course, so you will need to save them to disc.
You could try to make the process as light-weight as possible, though. Usually when a user copies data to the clipboard it is put there immediately, whether or not it will be used for a paste operation. For your application that would mean that you would need to create the files and put the list of file names into the clipboard, every time. However, Windows does support a mode called Delayed Rendering, which is used exactly for such cases. Basically you put only an empty stub of the data onto the clipboard, and only when another application tries to access the data it will be requested from your app. So you could implement this in a way that only when the user tries to paste the files into explorer you would save them to disc and return the list of file names.
It's been a while since I toyed with copy/paste, but I'm pretty sure you can do what you're suggesting (insert the blob as a new file into the clipboard).
I seem to remember that depending on how you add to the clipboard you can specify what sort of data you're copying. I think if you get that data type right, you'll be able to paste as though you'd copied from windows explorer.
I'll try and dig out some more details this evening if I have a chance (I don't have all my bookmarks here at work)...
[Edit] Have a look at the wxWidgets documentation on drag and drop. That was what I'd been working with and it gives some hints about data types.
What are you writing in? Delphi?
[Edit2] I think this may actually be a limitation of Windows(?). It might just be the wxWidgets documentation, but there's a suggestion that you only copy filenames rather than the files themselves. If that's the case, you're going to have to ue your original suggestion of creating a temp file first :-(

Resources