Sign in to follow this  
Followers 0
twitchyliquid64

Issue with Debug vs. Release Solution configurations in VC++08

18 posts in this topic

Hi all,

I am presently creating a program in C++, and part of this program uses the WINAPI QueryPerformanceCounter() function to work out the time taken for certain events.

The issue I am having is when I convert the double that my calculation gives me into a string, using

sprintf(tempbuff, "%.15g", tok->fValue);

When in the 'Debug' solution Config, it works perfectly well, producing numbers like 1.8736523754e+006

However, when in the release solution Config, it will produce something completely wrong:

1873652.3754...

What is causing this? How can I fix the problem? What is the difference between the two configs anyway?

Thankyou in advance.


ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites



Aren't those numbers the same? One is in scientific notation, the other is not, but appear to me to be the same number.

1 person likes this

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

i actually just made up those two numbers, they are not actual output.

In any case, that still does not explain the differences caused by Changmg configuration


ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites

I just ran it again, the correct one outputs something like 2.23..............e+060

the wrong one is like: 22398762363

Entirely different orders of magnitude.

In retrospect...I think they are both wrong, considering in the timeframe its measuring, it should be about 2ms, not 2^60 ms.

if (!QueryPerformanceFrequency((LARGE_INTEGER *)&freq))
        return PARSER_SUCCESS;
    if (!QueryPerformanceCounter((LARGE_INTEGER *)&now))
        return PARSER_SUCCESS;

    result->type = OPT_DOUBLE_TOK;

    result->fValue = (((double)now - (*parameters)[0].fValue) / (double)freq) * 1000.0;
    return PARSER_SUCCESS;
//MOST of tht is from the autoit source. Credit to them.

ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites

I think it does because a double has finite amount of bits so it needs to be converted to scientific notation. A string can display the entire value as long as it doesn't repeat infinitely. That's my best guess.

Share this post


Link to post
Share on other sites

I think it does because a double has finite amount of bits so it needs to be converted to scientific notation. A string can display the entire value as long as it doesn't repeat infinitely. That's my best guess.

How does this account for the differences when compiling in a 'Debug' or 'Release' configuration?


ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites

How does this account for the differences when compiling in a 'Debug' or 'Release' configuration?

Check if you're not compiling for 32 or 64 bit and the rest of your code adjusts to that according. It's the only thing that changes when you switch debug/release, apart from preprocessors (#ifdef DEBUG in C++ I think).

Share this post


Link to post
Share on other sites

You're using C++ so why are you using sprintf()? Use a stream.

Share this post


Link to post
Share on other sites

You're using C++ so why are you using sprintf()? Use a stream.

I'm guessing you mean using string stream.

does that have much additional overhead over something like sprintf?


ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites

does that have much additional overhead over something like sprintf?

No. Instead of 0.0000000000000000001ms it might take 0.0000000000000000001ms.

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

I'm guessing you mean using string stream.

does that have much additional overhead over something like sprintf?

Yes, creating a string stream object and then using the overloaded operators does create a lot of unnecessary code* if all you need to do is write to a character buffer. Streams are more in the 'spirit' of C++ but the printf variants are still part of the standard CRT library, and do create more compact code. The downside of printf functions is that datatypes aren't able to be checked at compile time. You could also use the _e,_f,_gcvt_s functions..

*edit: by unnecessary code, I mean the resultant code the compiler creates (the stream constructor and allocation of memory, the individual operator calls for each and every type [ "mystream << s << v << endl" = 3 function calls), the reallocation that occurs when the stream buffer is filled [worst-case being for each item inserted in a stream], and the destructor and deallocation of memory when its no longer used..).

Edited by Ascend4nt

Share this post


Link to post
Share on other sites

Ascend4nt, I don't really think your post is wise. Experienced C++ programmers can make the choice as to whether or not to use streams but it's incredibly clear we are not dealing with an experienced programmer here. That much is obvious by the complete lack of understanding about what QueryPerformanceCounter() values are. It's also unlikely that the user understands type-safety and just why sprintf() is so dangerous.

Also, why would the compiler generate unnecessary code? It doesn't. It generates necessary code. The code that it generates, however, is often deemed too much for a simple task. There is a pretty clear difference between "lots of code" and "unnecessary code". Type safety and syntactic convenience comes at a price, after all.

All in all not your most impressive post.

Share this post


Link to post
Share on other sites

I figured someone would nitpick about the 'unnecessary code' remark in my post, which is why I added the little *footnote. That should have been more than clear enough for anyone reading it to understand that I was responding directly to the overhead question by twitchyliquid. If you want to make this into a debate about 'proper' C++ coding techniques than you're barking up the wrong tree. I don't care about debating abstract ideals. When I program, I liked to get my hands dirty. I learn what is done behind the scenes. And I avoid wasteful techniques whenever possible. For something as simple as converting a float into a string, suggesting the programmer use a stream is overkill. In fact, the best and simplest alternative to that single line in the 1st post is to use _fcvt_s (which I had already offered as an alternative).

All in all not your most impressive post.

How characteristic. Always trying to get digs in whenever possible. Perhaps for once you can leave your ego at the door.

Share this post


Link to post
Share on other sites

I figured someone would nitpick about the 'unnecessary code' remark in my post, which is why I added the little *footnote. That should have been more than clear enough for anyone reading it to understand that I was responding directly to the overhead question by twitchyliquid.

You define "unnecessary code" by listing off all code that is necessary. Baffling.

If you want to make this into a debate about 'proper' C++ coding techniques than you're barking up the wrong tree. I don't care about debating abstract ideals.

Clearly you don't care about any ideals because you just told an inexperienced C++ user to use a non-type safe function for something that I believe is no more than a debugging statement.

And I avoid wasteful techniques whenever possible.

This must only be in programming because your post was certainly wasteful. It was bad advice and your meaning was poorly written to the point you knew it was poorly written and chose to try and deflect any notion of that with data that contradicts your own claim. That seems pretty damn wasteful to me.

For something as simple as converting a float into a string, suggesting the programmer use a stream is overkill.

Define overkill. Never mind, don't bother. I don't really care what perverse definition you put to it.

In fact, the best and simplest alternative to that single line in the 1st post is to use _fcvt_s (which I had already offered as an alternative).

I think I liked it better when you weren't suggesting non-standard functions. I don't feel like pointing out why writing portable code is a good thing unless there is a specific demand for platform bound code.

How characteristic. Always trying to get digs in whenever possible. Perhaps for once you can leave your ego at the door.

You gave shit advice and I called you on it. I fail to see how that is "ego". In fact I'm still mystified at this ego people claim I have. I have no ego. I have flashes of arrogance from time to time but no more. I think many of you confuse knowledge and knowledge of self-limits as ego.

Anyway, I decided to take the Harvey Dent approach to your fate on this forum. I flipped a coin. Heads you go away for good, tails you stay another day. Unfortunately the coin landed on tails. Next time I'm not flipping a coin. If you give bad advice to somebody who doesn't know any better I will make you go away. If you try this bullshit analysis crap on me again you will go away. I should remove you now as it's very clear from your parting remark that you did not learn any worthwhile lesson from your previous encounter with me. People who do not learn have no place here.

Plus there's the fact that I just plain don't like you.

Share this post


Link to post
Share on other sites

Ascend4nt, I don't really think your post is wise. Experienced C++ programmers can make the choice as to whether or not to use streams but it's incredibly clear we are not dealing with an experienced programmer here. That much is obvious by the complete lack of understanding about what QueryPerformanceCounter() values are. It's also unlikely that the user understands type-safety and just why sprintf() is so dangerous.

Your entirely correct. I am not experienced with C++ (barely been doing it for 6 months). I have no idea what you mean by sprintf() being dangerous (buffer overflows possibly?) and what QueryPerformanceCounter() values actually mean.


ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites

*If* you are using C, then there is no need to use QueryPerformanceCounter... Especially since your comment shows a parser, which I don't see any reason to need high precision timing. If you want ms precision timing that's simple to use:

clock_t start = clock( );

/* Do stuff */

printf( "%gn", ( clock( ) - start ) / ( ( double )CLOCKS_PER_SEC ) * 1000.0 );

Share this post


Link to post
Share on other sites

Mat,

this is an implementation of timerdiff() as a builtin to my interpreter. i must use queryperformancecounter.


ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • likehu
      By likehu
      Hello,
      I have compiled a reference DLL in VS 2015 Community and this  DLL works fine with project for which it is used. There is an interface from which u can access functions in DLL.
      Developers stated that this DLL is almost universal and can be used with any language with minor changes.
      I am trying to access its function from Autoit script and got an error 3, after calling DLLCall - "function" not found in the DLL file.
      Please have a quick look, I feel I miss something in C++ library with exporting functions and I do not know what to add as I am new to C++.
      Thank you.
      Source files and script also attached.
       
      Here is my script.
      Local $dll = DllOpen("C:\Users\Home\Desktop\dll\user.dll") ConsoleWrite("$dll handle = " & $dll & @CRLF) ;$dll handle = 1 Local $result = DllCall($dll, "double:cdecl", "ProcessQuery", "str", "dll$mynumber") If @error > 0 Then ConsoleWrite("Error: " & @error & @CRLF) ;Error = 3 If IsArray($result) Then ConsoleWrite("Array returned!" & @CRLF & "dll$mynumber: " & result[1]) Else ConsoleWrite("$result is not array. : " & $result & @CRLF) ;$result = 0 EndIf DllClose($dll) And here is dll source. As I understand, function "ProcessQuery" exported with help of DLL_IMPLEMENTS
      user.h
      //****************************************************************************** // // This file is part of the OpenHoldem project // Download page: http://code.google.com/p/openholdembot/ // Forums: http://www.maxinmontreal.com/forums/index.php // Licensed under GPL v3: http://www.gnu.org/licenses/gpl.html // //****************************************************************************** // // Purpose: Very simple user-DLL as a starting-point // // DO NOT CHANGE ANYTHING IN THIS FILE! // // This Header defines an interface // Functions and data-types must exactly match. // //****************************************************************************** #ifndef _INC_USER_H #define _INC_USER_H // Import and export directives // for use by this DLL and by OpenHoldem #ifdef USER_DLL #define DLL_IMPLEMENTS extern "C" __declspec(dllexport) #define EXE_IMPLEMENTS extern "C" __declspec(dllimport) #else #define DLL_IMPLEMENTS extern "C" __declspec(dllimport) #define EXE_IMPLEMENTS extern "C" __declspec(dllexport) #endif // Number of saved table-states // This number must not be changed, as we do a "& 0xFF" // at various places to normalize the index. const int kNumberOfHoldemStatesForDLL = 256; // SHoldemePlayer // used for sequence of 256 consequive table-states // !!!! Needs 2 more cards for Omaha, if not entirely removed struct holdem_player { char m_name[16] ; //player name if known double m_balance ; //player balance double m_currentbet ; //player current bet unsigned char m_cards[2] ; //player cards unsigned char m_name_known : 1 ; //0=no 1=yes unsigned char m_balance_known : 1 ; //0=no 1=yes unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler bytes }; struct holdem_state { char m_title[64] ; //table title double m_pot[10] ; //total in each pot unsigned char m_cards[5] ; //common cards unsigned char m_is_playing : 1 ; //0=sitting-out, 1=sitting-in unsigned char m_is_posting : 1 ; //0=autopost-off, 1=autopost-on unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler byte unsigned char m_dealer_chair ; //0-9 holdem_player m_player[10] ; //player records }; // Functions implemented and exported by the DLL, // imported by OpenHoldem DLL_IMPLEMENTS double __stdcall ProcessQuery(const char* pquery); DLL_IMPLEMENTS void __stdcall DLLOnLoad(); DLL_IMPLEMENTS void __stdcall DLLOnUnLoad(); // Functions implemented and exported by OpenHoldem, // imported by the DLL EXE_IMPLEMENTS double __stdcall GetSymbol(const char* name_of_single_symbol__not_expression); EXE_IMPLEMENTS void* __stdcall GetPrw1326(); EXE_IMPLEMENTS char* __stdcall GetHandnumber(); EXE_IMPLEMENTS void __stdcall ParseHandList(const char* name_of_list, const char* list_body); EXE_IMPLEMENTS char* __stdcall ScrapeTableMapRegion(char* p_region, int& p_returned_lengh); EXE_IMPLEMENTS void __stdcall SendChatMessage(const char *message); EXE_IMPLEMENTS void __stdcall WriteLog(char* format, ...); // Variables exported by OpenHoldem // avoiding the message-mess of WinHoldem, // no longer sending any state-messages // http://www.maxinmontreal.com/forums/viewtopic.php?f=174&t=18642 EXE_IMPLEMENTS extern holdem_state state[kNumberOfHoldemStatesForDLL]; EXE_IMPLEMENTS extern int state_index; #endif // _INC_USER_H  
      user.cpp    Here is dll$mynumber parameter.
      //****************************************************************************** // // This file is part of the OpenHoldem project // Download page: http://code.google.com/p/openholdembot/ // Forums: http://www.maxinmontreal.com/forums/index.php // Licensed under GPL v3: http://www.gnu.org/licenses/gpl.html // //****************************************************************************** // // Purpose: Very simple user-DLL as a starting-point // // Required OpenHoldem version: 7.7.6 // //****************************************************************************** // Needs to be defined here, before #include "user.h" // to generate proper export- and inport-definitions #define USER_DLL // #define OPT_DEMO_OUTPUT if you are a beginner // who wants to see some message-boxes with output of game-states, etc. // It is disabled upon request, // * as it is not really needed // * as some DLL-users don't have MFC (atlstr.h) installed // http://www.maxinmontreal.com/forums/viewtopic.php?f=156&t=16232 #undef OPT_DEMO_OUTPUT #include "user.h" #include <conio.h> #include <windows.h> #ifdef OPT_DEMO_OUTPUT #include <atlstr.h> #endif OPT_DEMO_OUTPUT // Supporting macros #define HIGH_NIBBLE(c) (((c)>>4)&0x0F) #define LOW_NIBBLE(c) ((c)&0x0F) // Card macro #define RANK(c) ( ISKNOWN(c) ? HIGH_NIBBLE(c) : 0 ) #define SUIT(c) ( ISKNOWN(c) ? LOW_NIBBLE(c) : 0 ) #define ISCARDBACK(c) ((c) == CARD_BACK) #define ISUNKNOWN(c) ((c) == CARD_UNDEFINED) #define ISNOCARD(c) ((c) == CARD_NOCARD) #define ISKNOWN(c) (!ISCARDBACK(c) && !ISUNKNOWN(c) && !ISNOCARD(c)) // ProcessQuery() // Handling the lookup of dll$symbols DLL_IMPLEMENTS double __stdcall ProcessQuery(const char* pquery) { if (pquery==NULL) return 0; if (strncmp(pquery,"dll$mynumber",13)==0) { return 12345.67; } return 0; } // OnLoad and OnUnload() // called once and at the beginning of a session // when the DLL gets loaded / unloaded // Do initilization / finalization here. DLL_IMPLEMENTS void __stdcall DLLOnLoad() { #ifdef OPT_DEMO_OUTPUT MessageBox(NULL, "event-load", "MESSAGE", MB_OK); #endif OPT_DEMO_OUTPUT } DLL_IMPLEMENTS void __stdcall DLLOnUnLoad() { #ifdef OPT_DEMO_OUTPUT MessageBox(NULL, "event-unload", "MESSAGE", MB_OK); #endif OPT_DEMO_OUTPUT } // DLL entry point // Technically required, but don't do anything here. // Initializations belong into the OnLoad() function, // where they get executed at run-time. // Doing things here at load-time is a bad idea, // as some functionalitz might not be properly initialized // (including error/handling). BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: #ifdef OPT_DEMO_OUTPUT AllocConsole(); #endif OPT_DEMO_OUTPUT break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: #ifdef OPT_DEMO_OUTPUT FreeConsole(); #endif OPT_DEMO_OUTPUT break; } return TRUE; }  
      Source.zip
      DllAccess.au3
    • SkysLastChance
      By SkysLastChance
      Okay so I am not sure if I can do this or not with the code I currently have but, I would like to send lastname and the first name with a comma inbetween. 
      so it would look like "last name,first name" 
      right now I just have it sending the last name.
      any help or sugestions are appreciated. 
       
      $r = 1 Local $aArray = _Excel_RangeRead($oExcel, Default, Default) For $i = 1 To UBound($aArray) - 1 ;$i =0 Start from row A $sR1 = $aArray[$i][0] ;status $sR2 = $aArray[$i][1] ;first name $sR3 = $aArray[$i][2] ;Last name $sR5 = $aArray[$i][5] ;Email Address WinWaitActive ("[CLASS:MGUIWin]") Sleep (100) ControlSend("[CLASS:MGUIWin]", "", "Edit2", $sR3, & @CR) $r = $r + 1 If $r > $sBox Then Exit Endif Next  
    • david1337
      By david1337
      Hey guys
      This may be quite simple, but I haven't manage to solve it yet :/
      All I want to do is get the ID of Xitem, so I can click it with " _GUICtrlListView_ClickItem" .
      So I need to find the item based on the that fact that I know the text/string name of that item.
       
      #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> Example() Func Example() GUICreate("listview items", 300, 300, -1, -1) Local $idListview = GUICtrlCreateListView("col1", 10, 10, 200, 150) ;,$LVS_SORTDESCENDING) Local $idButton = GUICtrlCreateButton("ID_of_Xitem?", 75, 170, 70, 20) Local $idItem1 = GUICtrlCreateListViewItem("Aitem", $idListview) Local $idItem2 = GUICtrlCreateListViewItem("Xitem", $idListview) Local $idItem3 = GUICtrlCreateListViewItem("Zitem", $idListview) GUISetState(@SW_SHOW) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idButton MsgBox(0,"","ID of Xitem is ?") _GUICtrlListView_ClickItem($clv, ?) EndSwitch WEnd EndFunc ;==>Example  
    • powerbass4
      By powerbass4
      Hi, I need the help of some "C++ Pros" of you....

      The "WINAPI GetLogicalProcessorInformation" function does not exists in the AutoIt Includes, so I decided to build it on my own ....no success so far.
      I adapted easy functions, but this one seems to be odd and unfamiliar.

      I hope somebody can help me.... and after that this function should be added to the Includes (WinAPISys.au3).
       
      BOOL WINAPI GetLogicalProcessorInformation( _Out_ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, _Inout_ PDWORD ReturnLength ); https://msdn.microsoft.com/en-us/library/windows/desktop/ms683194(v=vs.85).aspx
       
      typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { ULONG_PTR ProcessorMask; LOGICAL_PROCESSOR_RELATIONSHIP Relationship; union { struct { BYTE Flags; } ProcessorCore; struct { DWORD NodeNumber; } NumaNode; CACHE_DESCRIPTOR Cache; ULONGLONG Reserved[2]; }; } SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; https://msdn.microsoft.com/en-us/library/windows/desktop/ms686694(v=vs.85).aspx
    • 31290
      By 31290
      Hi guys,
      I'm facing a problem that I can't solve, despite trying hard.
      I have an .ini file with several sections:
      [Latitude E5440] URL=http://downloads.dell.com/published/pages/latitude-e5440-laptop.html [Latitude E5450] URL=http://downloads.dell.com/published/pages/latitude-e5450-laptop.html [Latitude E5470] URL=http://downloads.dell.com/published/pages/latitude-e5470-laptop.html [Latitude E7240] URL=http://downloads.dell.com/published/pages/latitude-e7240-ultrabook.html [Latitude E7250] URL=http://downloads.dell.com/published/pages/latitude-e7250-ultrabook.html [Latitude E7270] URL=http://downloads.dell.com/published/pages/latitude-e7270-ultrabook.html Then I collect the computer model name and try to look if it exists in the ini file. But, when performing the search, I only got the index in the array.
      For example, my computer model is a "Latitude E7240". An "_ArraySearch" gives me "4" as a result and because this is also the fourth place of my search in the ini file. It works well if I move the section anywhere else in the file and always give me the correct position.
      Question is: How can I convert the index number to the section name so I can tell my script that if it's found in the ini file, the download URL variable will be set to the corresponding key in the ini file.
      Here's my code so far:
      Can someone give me an hand on this?
      Thanks
      -31290-