PDA

View Full Version : Registry entry for application data



Bidmaron
August 18th, 2018, 16:57
FG has the ability to redirect the data folder away from windows default appdata. What registry entry should I look in to find that location? I'm trying to write a tool that works external to FG but needs access to data folder.

gamerhawaii
August 18th, 2018, 17:53
HKEY_CURRENT_USER\Software\Fantasy Grounds\2.0\DataDir

Bidmaron
August 19th, 2018, 01:54
Thanks

Bidmaron
August 19th, 2018, 05:34
I am a Mac guy, and I'm getting an error in my C# program that attempts to start Fantasy Grounds. This is my code line giving the error:

Process.Start(@"C:\Program Files x86\Fantasy Grounds II\FantasyGrounds.exe");

This gives me the following Fantasy Grounds error:

24376

I do not get an error of any kind when I start FG from the windows start menu.

I went to file explorer to see if there was some kind of command that should be included in the exe line, but the properties of the start menu item did not show any such thing.

Dulux, or some windows guru, can you tell me please what I am doing wrong?

Andraax
August 19th, 2018, 05:49
My first guess would be that it's running the executable in the wrong directory.

Bidmaron
August 19th, 2018, 13:00
That's what I'm thinking, too, Andraax, but I'm a Windows retard, and I can't figure out what else I need to do before that .Start call to get things set up correctly. (Pretty sure it is using my program's path as some kind of default directory).

Andraax
August 19th, 2018, 13:25
Find what the "default directory" is for the entry in the start directory (probably something like "C:\Program Files x86\Fantasy Grounds II") and change to that directory before running it.

I'm not a C# programmer, but I found this sample online using a specified working directory with Process.Start:


ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = @"%ProgramFiles%";
_processStartInfo.FileName = @"Notepad.exe";
_processStartInfo.Arguments = "test.txt";
_processStartInfo.CreateNoWindow = true;
Process myProcess = Process.Start(_processStartInfo);

Bidmaron
August 19th, 2018, 15:15
I found that directory using the registry entry that gamerhawaii located (and now I know how to use RegEdit to go look in that file). Thanks for the tip on creating the process instance. I was going to try SetCurrentDirectory, but I think what you have is actually the ticket. I will let you know how it goes. Thanks, Andraax.

Bidmaron
August 19th, 2018, 22:34
Well, that didn't work either. Here is my code:


ProcessStartInfo fgRunner = new ProcessStartInfo();
fgRunner.WorkingDirectory = @"c:\Users\AppData\Roaming\Fantasy Grounds II";
fgRunner.FileName = myFile;
fgRunner.UseShellExecute = false;
try
{
Process myProcess = Process.Start(fgRunner);
}
catch (Exception er)
{
MessageBox.Show("Unable to start Fantasy Grounds." + "\r\t(" + er.GetType().ToString() + er.Data + ": " + er.Message + ")", "Error", MessageBoxButtons.OK);
return false;
}

I know hard-coding the directory is a bad practice, and I intend to get that from the registry once I get this working, but right now, when my code runs, FG tries to start, but it issues the same message from my post #4 above.

Andraax
August 19th, 2018, 23:10
I doubt that "c:\Users\AppData\Roaming\Fantasy Grounds II" is the directory where your executable is installed. More than likely it's "C:\Program Files x86\Fantasy Grounds II".

Bidmaron
August 19th, 2018, 23:28
Sorry, myFile is the fully qualified path to the executable. Again, FG starts, it just gives that message. Do you think the working directory needs to be set to the program's location? The error message kind of makes no sense if that's the case, but I guess it's worth a try.

Of course, even once FG starts, there is no way I know of to tell it what campaign to launch, so I still have to rely upon the user to start up his campaign.

Bidmaron
August 19th, 2018, 23:38
Andraax, you are a genius. I had to set the working directory to the install location (which I got from the registry), and the executable name had to be the fully-qualified file name. Just "FantasyGrounds.exe" would not work. Of course, there is still the fact that the user must start his campaign, but at least I got the main program started.

gamerhawaii
August 20th, 2018, 02:50
You can automate the user portion of FG a little bit using either AutoIt or ImageSearch

For example, if you know exactly on the screen where FG will start, AutoIt works great. For example something like this:

using System;
using System.Windows.Forms;
using AutoIt;
using System.Runtime.InteropServices;



System.IO.Directory.SetCurrentDirectory("C:\\Games\\Fantasy Grounds");
AutoItX.Run("FantasyGrounds.exe", "C:\\Games\\Fantasy Grounds");
AutoItX.WinWait("Fantasy Grounds");

if (AutoItX.WinActive("Fantasy Grounds") == 0)
{
AutoItX.WinActivate("Fantasy Grounds");
}
AutoItX.WinWaitActive("Fantasy Grounds");
AutoItX.Sleep(1000);
AutoItX.MouseMove(595, 419);
AutoItX.MouseClick("left");
AutoItX.Sleep(1000);
AutoItX.MouseMove(771, 456);
AutoItX.MouseClick("left");
AutoItX.Sleep(1000);
AutoItX.MouseMove(1317, 823);
AutoItX.MouseClick("left");

If you do not want to go to a particular place but search the screen for a button, use ImageSearch. For example something like this:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

...

[DllImport("ImageSearchDLL.dll")]
private static extern IntPtr ImageSearch(int x, int y, int right, int bottom, [MarshalAs(UnmanagedType.LPStr)]string imagePath);

private bool SearchForImage() {
string fullImageName = <image looking for, e.g., image of the “Load Campaign” button>
if (System.IO.File.Exists(fullImageName))
{
// pick your own screen coordinates to check instead of these
IntPtr found = ImageSearch(800, 700, 1100, 900, fullImageName);
string foundString = Marshal.PtrToStringAnsi(found);
if (foundString != "0")
{
return true;
}
}
return false;
}

gamerhawaii
August 20th, 2018, 02:58
Combining these two (AutoIt and ImageSearch) works great for automating stuff like what you are probably trying to do.

For example, in only ~200 lines of code I combined them in a C# program to automatically roll characters in Baldurs Gate, Icewind Dale, and Temple of Elemental Evil until the combined ability rolls for a character were high enough. (Yes, I know cheating. It was the fun of figuring out how to do it.)

Bidmaron
August 20th, 2018, 02:58
Wow, I had no idea something like this existed. I will have to stew on this a little. I wasn't too bothered not being able to go farther than the launch screen because the user might not want to run the same campaign as last time. I don't think I want to duplicate the launch screen. Currently, I just put up a dialog that asks the user to startup in host, client, or local mode as desired in the appropriate ruleset/campaign and just keep checking to see if FG has started up fully and written the signal node to the intercommunication xml file.

Bidmaron
August 29th, 2018, 16:28
OK, here's the next one:
Where is client mode CampaignRegistry data stored? I know it is stored because I wrote some test code to set a field inside CampaignRegistry, and it persisted when I shutdown and restarted the client (localhost connected to my own campaign). And I know it isn't in the campaign's CampaignRegistry the host uses because I opened it in Notepad++, and my field wasn't there.

I am thinking it is crammed into the cache .dat file?

Moon Wizard
August 29th, 2018, 22:24
It’s stored in the client campaign data in the cache. Most of the files except hot keys are stored in an encrypted cache to prevent player peeking.

Regards,
JPG

Bidmaron
August 30th, 2018, 03:32
Just curious. Thanks!

One thing I will say is the more I get into the ruleset (corerpg) and the lua xml thing, the more I admire the design of the whole thing. Really remarkable.

Bidmaron
October 2nd, 2018, 15:45
I am just using this thread for questions so as to avoid thread proliferation.

This is a question for Moon Wizard or Trenloe (although is someone else knows the answer, I'm listening).
Comm has two ThrowDice functions. The second has the signature: function throwDice( data )

The question: Is this function asynchronous? That is, will a call result in an immediate return followed by an onDiceLanded at a later point?
What if there are no dice in the call?

I am asking this because I am trying to implement an onTime event kind of structure, to where I can call something asynchronously so that the user interface stays responsive while we are waiting on the time to arrive.

Moon Wizard
October 2nd, 2018, 16:10
If there are dice, the physics simulation is kicked off, and onDiceLanded is called when the simulation completes. If there are no dice; then I believe it’s an immediate call to onDiceLanded.

Regards,
JPG

Bidmaron
October 2nd, 2018, 16:11
Moon wizard, is there any way to achieve my desired effect which is to asynchronously loop to keep the UI responsive while waiting for something?

Moon Wizard
October 2nd, 2018, 16:16
Not without really kludgy option like forcing a list to constantly re-sort, which would get called once per frame. These sort of kludges will work, but can cause draw overhead as the UI elements up the chain are recalculated and redrawn every frame.

I’ve seen one extension use this method for a CT timer; but it’s not a great solution (due to extra draw overhead).

There have been a couple requests over the years to add timer functionality; but it hasn’t percolated to the top of the priorities.

Regards,
JPG

Bidmaron
October 2nd, 2018, 16:18
I believe I own the ideainformer entry requesting it from 2008 I think. But it has so very few votes like most of the programming requests. That is a natural result because users have no idea what could be done with some of those requests.