-
Content Count
1090 -
Joined
-
Last visited
-
Days Won
23
Posts posted by aehimself
-
-
@Kryvich Thank you for the suggestion, but that will only get rid of an exception "Already connected" if the button is pressed twice during the lifetime of the application. I know it's not a nice and error handling code, it was meant as a test run only. Emba broke Indy's SSL certificate handling somehow (see: https://community.idera.com/developer-tools/b/blog/posts/rad-studio-10-3-3-indy-server-ssl-certificate-patch) and despite having a patch I feel more comfortable using a more up-to-date source.
There are no 260, only 250 packages, but they compile and install nicely on 10.3.3.
Does the deadlock appear if you run the code above? I had the same experience with the (unpatched) Emba version and the latest Git snapshot version too.
-
22 hours ago, Kas Ob. said:First thought here is bizarre memory fragmentation, this can happen if the application have many thread that been created and destroyed, because the reserved stack for each thread by default is 1 mb , and OS will try to find 1mb as whole to reserve, in case of failure to find such one piece the symptoms and messages shown will be red herring.
I had this issue once on a 32 bit application running on a Windows 2000 test machine with 64-128 MB of RAM (strangely enough, Win2k3 with 128 MB ran the same code perfectly). Solution was easy though - instead of launching and destroying a thread when the work is done and recreating it when needed again, I just left the threads in an empty loop, signaling when I need them to do their job.
Took me a couple of days to figure it out, though 🙂
-
Hello,
I started to experiment with Indy (looking for a worthy successor to port some legacy TServerSocket-TClientSocket apps to). As Emba had some issues with Indy lately I decided to wipe it off, pulling an up-to-date version from https://github.com/IndySockets/Indy/ and installing that one.
I have a deadlock issue with my hello world app, where it seems that TidIOHandler.ReadFromSource does not return and my project throws a "disconnected" exception upon exiting. Setup is fairly simple: TidTCPServer with defaultport set to 1024, TidTCPClient with host set to 127.0.0.1 and port set to 1024.
The whole project contains the following:
procedure TForm1.Button1Click(Sender: TObject); begin IdTCPServer1.Active := True; IdTCPClient1.Connect; IdTCPClient1.IOHandler.WriteLn('Hello, world'); end; procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); Var s: String; begin s := AContext.Binding.PeerIP + ': ' + AContext.Connection.IOHandler.ReadLn; TThread.Queue(nil, procedure Begin Memo1.Lines.Add(s) End); end;
TCPServerExecute get hits twice. First, it reads "Hello, world" and puts it to the memo correctly. The second time, it goes into the method mentioned above and never returns (can not debug the exact location, as my Delphi is showing the line indicator somewhere random...).Again, this is my first test run of Indy (copied the code from https://stackoverflow.com/questions/31039580/how-can-i-send-and-recieve-strings-from-tidtcpclient-and-tidtcpserver-and-to-cr) and have zero knowledge in the component yet. Am I doing something wrong? What would be the smallest, least complicated solution for me so I can start my learning curve?
Thanks!
-
On 1/27/2020 at 7:30 PM, David Heffernan said:Build the dcus into a dll and link to that.
This is a ridiculously perfect and simple idea. Fortunately I have source for everything, but I'll keep this in my mind for later!
-
Is it possible to learn this power? 🙂 To make functions without code? 🙂
-
@Dalija Prasnikar Nice, thank you! Exactly what I was looking for 🙂
Just out of curiosity, where it is declared? It says System, but I can not see the implementation. I like to see what I am using 🙂
-
Hello all,
I'm implementing a custom typed class, e.g.:
TMyClass<T> = Class strict protected list: TDictionary<String, T>; public Function Get(Identifier: String): T; End; Function TMyClass<T>.Get(Identifier: String): T; Begin If list.ContainsKey(Identifier) Then Result := list[Identifier] Else Result := ???; End;
Question is simple. Is there a default null value for T which I can substitute ??? with? For Strings, it should return '', for numerical values 0, for classes nil and so on.
Thanks!
-
@Anders Melander The good thing is that my prototype consists of exactly the same 4 parts; which makes me believe I'm not drifting too far away from the original goal 🙂
My database structure is not large, consists of 10-ish, 11-ish tables, containing only one circular reference until now. It wouldn't even be impossible to hard code (or generate to source, that is) the shortest possible paths an all possible queries, but I am really against these kind of solutions. I was planning to test this idea on a large database (~1500 tables, multiple circular references, standalone tables, etc.) but I need to extract the fields and connections first.
As for the concerns yes - I have them in mind. Especially the crawler. While it works well in my scenario but it's unoptimized and I worry about it's performance on more complex structure. That's something which will turn out on the long run.
Scoping is already fully supported. I don't have many fields with the same name but yes, I already saw it as a possible problem source. I also have a theory of a mechanism to analyze and learn the more common requests so future ones can be more close to what the user wanted, but this is strictly a theory until now, and won't even start to work on it until I decide to go with my solution or to purchase a component doing this already.
And thank you very much for your post, it was tremendously informative!
-
1 hour ago, Lars Fosdal said:@aehimself Just a thought. You may need to support "as" naming to handle duplicate field names in table joins or IsNull code.
select aStrField, IsNull(aIntField, 0) as aIntField from aTable
Without the as - the aIntField will not be named in the result set - at least not for MS SQL.
Then there is the question of count, max, min, and so forth...
Once you open for custom queries - you basically open a can of feature requests 😉
I'm not too worried about duplicate file names, as I'm planning to generate the query with TABLENAME.FIELDNAME all the times (thus the mapping) and if the output will show MyField and MyField_1 in the column header... then so be it.
As for the IsNull you might be right but not during data display (my database component handles null values as 0, which is perfect in my case) but at WHERE clauses... I recall having an issue on MSSQL not returning correct rows as it handled NULL and 0 (or '', I don't remember exactly) differently. We will see how exactly it will turn out, especially with the "can" you are talking about 🙂
As for the external components I think I will have to gather my strength and finalize my solution. After all it's less than 400 lines (only field mapping and the crawler until now, though) and does not increase the budget. Good news is that I'm either doing this or implementing the requested XML documentation commenting. And I rather code than to do documentation 😄
-
On 1/15/2020 at 8:23 AM, haentschman said:Hi...
Imho is not a good idea to allow the end user to generate statements. Especially with an input in a TDEDIT.
SQL injection: https://en.wikipedia.org/wiki/SQL_injection
Good point, but the user is not allowed to write SQL queries at all 🙂 The method I'm working on / looking for is allowing the user to select (enter) field names, maps those to real fields in the database (attempted sql injection will fail at this level as '; DROP TABLE Users; will not map to any field in the database) and based on the mapped fields constructs a SELECT query with proper joins.
Maybe I'm not viewing this scenario from all aspects, but I don't see the possibility of a vulnerability here.
-
I also started to use %USERPROFILE% and %APPDATA% as local data storages. If people want to exchange their information, they can export and import; but not necessarily everyone wants to see the same information.
Just imagine your application running on a terminal server used by 100+. They will surely want to separate their data.
-
Hi all,
I have an application where I would like the user to be able to "build" what data he wants to see. As I can not expect the user to be an expert in SQL, I need to have an interface where he can just check (or enter) the fields, my program will parse it, generate the necessary SQL query (with proper joins and such), executes it and returns the data.
I wrote a small program to "design" the database of the application - it is generating SQL scripts and the code for my custom table-as-an-object implementation - so I have access to all the field and relational information and can output it in any format needed.
I already have a prototype which can judge which field in which table to select and a crawler (path finder, basically) which can determine the shortest route between two tables. They seem to be working fine but there's still a lot of work with it (optimizations, beautifying - the usual) which I am soooooo unwilling to do at the moment.
So my question is - do I really have to reinvent the wheel? Is there a framework available which can do this for me?
And yes, I really hate to redesign working prototypes to production-ready implementations 🙂
-
17 hours ago, PeterPanettone said:function TformMain.SaveShortcutShellLinkAsAdministrator(const AFile: string; AShellLink: JclShell.TShellLink): Boolean; begin [...] else begin MessageDlg('Could not create a temporary ShellLink Shortcut', mtError, [mbOK], 0); EXIT; end; [...] if not Result then EXIT; [...] if not FileExists(AFile) then EXIT; [...] end;
On 12/20/2019 at 10:29 AM, PeterPanettone said:I have found a new DEFINITION of "Early Return":
"STUPIDITY TRYING TO LOOK SMART"
Jokes aside 🙂
A couple of questions popped up in my mind:
- Are you sure that "RunAs" is an allowed verb for ShellExecute? https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutea does not seem include it, only https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-shellexecuteinfoa (JCL's ShellExecAndWait is using the Ex version, so the code itself is good, it's only a misleading comment)
- Tip: If the file exists but corrupted (hashes do not match) delete the target file as its useless anyway; but...
- Why are you comparing the hashes before and after moving? Did you experience corruption in any occasion? I'm only asking because I personally never met this before.
- A little bit more resource friendly way of verification might be to check the exit code of move. I'd say might, because as it never failed on me I don't know what exit code it returns if it corrupted the data. So take this with a grain of salt.
-
Yes, that was my fear too. Solution is rather easy though - don't use overloads 🙂 I started to experiment and came to the realization that Self can be used in a class function / procedure. It only won't reference an instance, only the class of the calling object - even if it is a child. The below works perfectly:
TBase = Class strict protected Function GetAsJSON: String; Virtual; Procedure SetAsJSON(inJSONString: String); Virtual; public Var1: Integer; Class Function New(inJSONString: String): TBase; Class Function New2(inInteger: Integer): TBase; Virtual; Property AsJSON: String Read GetAsJSON Write SetAsJSON; End; TChild = Class(TBase) strict protected Function GetAsJSON: String; Override; Procedure SetAsJSON(inJSONString: String); Override; public Var2: String; Class Function New2(inInteger: Integer; inString: String): TChild; ReIntroduce; End; // Class Function TBase.New(inJSONString: String): TBase; Begin Result := Self.Create; Result.AsJSON := inJSONString; End; Class Function TBase.New2(inInteger: Integer): TBase; Begin Result := Self.Create; Result.Var1 := inInteger; End; Class Function TChild.New2(inInteger: Integer; inString: String): TChild; Begin Result := TChild(inherited New2(inInteger)); Result.Var2 := inString; End;
I don't like that there are two "New" methods now, but it feels a lot more clean.
-
-
On 12/31/2019 at 12:15 PM, Stefan Glienke said:That code would not even compile as the two New overloads in TBase don't differ from each other parameter wise.
Did not pay enough attention when writing the example 🙂 Let me correct myself:
TBase = Class public Var1: Integer; Class Function New(inJSONString: String): TBase; Overload; Virtual; Class Function New(inVar1: Integer): TBase; Overload; Virtual; End; TChild = Class(TBase) public Var2: String; Class Function New(inJSONString: String): TChild; ReIntroduce; Overload; Class Function New(inVar1: Integer; inVar2: String): TChild; ReIntroduce; Overload; End;
-
I think the answer is no but maybe I just did not find the correct way - yet.
Imagine the following:
TBase = Class public Var1: String; Class Function New(inJSONString: String): TBase; Overload; Virtual; Class Function New(inVar1: String): TBase; Overload; Virtual; End; TChild = Class(TBase) public Var2: Integer; Class Function New(inJSONString: String): TChild; ReIntroduce; Overload; Class Function New(inVar1: String; inVar2: Integer): TChild; ReIntroduce; Overload; End;
When I type TChild.New, all four variants are accessible. So the question is: is it possible to completely reintroduce the base classes all overloaded methods, so in the child only the newly declared are accessible?
-
Killing a thread is not a good idea in about 99% of the times 🙂 The best case is that it will leak memory and / or abandon TCP connections.
Worst case? It can leave corrupted temporary files around, render your application unusable and requiring a restart or even leave the system in an unbootable state (depending what it is doing which gets forcefully interrupted).
Sometimes you have no other option though...
There are some REALLY good advices there. Maybe you can launch the image processing in a child process - in regards to the host applications state killing a process can be less painful than a killing a thread.
-
1
-
-
1 minute ago, PeterPanettone said:That's not a definition. Try harder.
There you go, I found it: https://dictionary.cambridge.org/us/dictionary/english/sarcasm
I'll try to act like an adult and stop this discussion right here. If you would like to learn more about coding styles, Google is - as always - your friend. In the mean time, please learn how not to get offended when people say their favorite color is not the same as yours.
-
2
-
-
1 minute ago, PeterPanettone said:Define "unnecessary nesting".
I'm no expert, but I'd say it's... nesting, which is... unnecessary? 😐
-
2
-
-
4 minutes ago, PeterPanettone said:That's not an "experience" but a FALSE ASSUMPTION.
No, it's not. @Anders Melander said: "It's based on the experience that unnecessary nesting makes the code harder to read." which is not false and not an assumption. It's a general statement.
I only can quote myself. Don't get offended. We are talking about personal preferences here.
-
1
-
-
1 minute ago, Anders Melander said:Code style to tentacles in three posts. I didn't see that coming.
There's always a connection. It's not spaghetti, it's tentacle code!
-
1
-
-
11 minutes ago, PeterPanettone said:I too, if they are LOGICAL. But the above are not.
For me the changes make sense what @Anders Melander mentioned.
But please - do not be OFFENDED. We are NOT saying it's bad code. As stated above - it's only PREFERENCE. 🙂
-
5 hours ago, Anders Melander said:It's a refactoring; It improves the readability of the code without changing the functionality.
I'm a fan of early returns, I use them all the times. For me it does improve readability but my colleagues complain that it makes it harder for them.
This is a matter of preference IMO, nothing else.
-
1
-
Delphi 10.3.3 - Indy from 0ba2688b Git "Hello World"
in Indy
Posted
While the program is running, it works for me too, I only get an error message when I close it:
The strange thing is that ServerExecute gets hit twice only at the first button press, consecutive WriteLn-s trigger the event only once.
And let me correct myself - it's not a deadlock, simply a blocking read operation from a socket, which has nothing in the queue. Me thinks, that is.