-
Content Count
44 -
Joined
-
Last visited
-
Days Won
2
Everything posted by TiGü
-
Cross platform version of Windows.WinAPI.IsDebuggerPresent ?
TiGü replied to Lars Fosdal's topic in Cross-platform
Funny, the embedded PASCAL code editor don't recognized the (* and *) comments. -
Cross platform version of Windows.WinAPI.IsDebuggerPresent ?
TiGü replied to Lars Fosdal's topic in Cross-platform
Hm...in Delphi Tokyo we can find in SysSysctlTypes.inc: (* TODO -otgerdes -cTranslate: kinfo_proc (needs proc.h) struct kinfo_proc { struct extern_proc kp_proc; // proc structure struct eproc { struct proc *e_paddr; // address of proc struct session *e_sess; // session pointer struct _pcred e_pcred; // process credentials struct _ucred e_ucred; // current credentials struct vmspace e_vm; // address space pid_t e_ppid; // parent process id pid_t e_pgid; // process group id short e_jobc; // job control counter dev_t e_tdev; // controlling tty dev pid_t e_tpgid; // tty process group id struct session *e_tsess; // tty session pointer #define WMESGLEN 7 char e_wmesg[WMESGLEN+1]; // wchan message segsz_t e_xsize; // text size short e_xrssize; // text rss short e_xccount; // text references short e_xswrss; int32_t e_flag; #define EPROC_CTTY 0x01 // controlling tty vnode active #define EPROC_SLEADER 0x02 // session leader #define COMAPT_MAXLOGNAME 12 char e_login[COMAPT_MAXLOGNAME]; // short setlogin() name #if CONFIG_LCTX pid_t e_lcid; int32_t e_spare[3]; #else int32_t e_spare[4]; #endif } kp_eproc; }; *) -
Cross platform version of Windows.WinAPI.IsDebuggerPresent ?
TiGü replied to Lars Fosdal's topic in Cross-platform
Okay, here we have solutions for macOS and Linux. https://stackoverflow.com/questions/2200277/detecting-debugger-on-mac-os-x It looks like easy to convert (depends of the status of the source\rtl\osx-Units). -
Cross platform version of Windows.WinAPI.IsDebuggerPresent ?
TiGü replied to Lars Fosdal's topic in Cross-platform
That's good to know! Thank you for the clarification. I stumbled upon this interesting blog post: https://xorl.wordpress.com/2017/11/20/reverse-engineering-isdebuggerpresent/ There must be similar mechanics on iOS, Android, Linux and macOS. I personally know too little about that. 😞 -
Cross platform version of Windows.WinAPI.IsDebuggerPresent ?
TiGü replied to Lars Fosdal's topic in Cross-platform
But as we can see in the class procedure TThread.NameThreadForDebugging(AThreadName: string; AThreadID: TThreadID); there are following lines: ... {$ELSEIF Defined(ANDROID)} if (System.DebugHook <> 0) or (getenv(EMBDBKPRESENTNAME) <> nil) then {$ELSE} ... So, i guess it's defined for Windows and Android and working on both platforms. Hast du wirklich deine IDE auf Deutsch gestellt? -
Cross platform version of Windows.WinAPI.IsDebuggerPresent ?
TiGü replied to Lars Fosdal's topic in Cross-platform
var IsCrossPlatformDebuggerPresent: Boolean; begin IsCrossPlatformDebuggerPresent := System.DebugHook <> 0; end; -
Solution(s) for coder with quite poor eyesight
TiGü replied to Tommi Prami's topic in Delphi IDE and APIs
Do you use Windows 10? Why not increase the DPI for the current Monitors? You can use a 1920 x 1200 Monitor with a 125%, 150% or 175% scaling. Source: https://www.tenforums.com/tutorials/5990-change-dpi-scaling-level-displays-windows-10-a.html -
Have a look to Microsofts Team Foundation Server: https://en.wikipedia.org/wiki/Team_Foundation_Server
- 49 replies
-
- git
- subversion
-
(and 1 more)
Tagged with:
-
Caching with class variables
TiGü replied to Primož Gabrijelčič's topic in Tips / Blogs / Tutorials / Videos
Hi Primož, that's a nice piece of code, but i notice in my Delphi Tokyo, that the ens-Result for the TEnumSet (for valid values) is empty. But if you add a untyped Move, than it works: program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.TypInfo, System.Rtti, System.SysUtils; resourcestring SValueLiesOutsideAllowedRange = 'Value %d lies outside allowed range for %s (%d .. %d)'; type TypeInfoCache<T> = class class var FMinIntVal: Integer; FMaxIntVal: Integer; FIsSet: Boolean; public class constructor Create; class property MaxIntVal: Integer read FMaxIntVal; class property MinIntVal: Integer read FMinIntVal; class property IsSet: Boolean read FIsSet; end; Range<T> = record private class function MaxIntVal: Integer; static; inline; class function MinIntVal: Integer; static; inline; class procedure RaiseException(const Value: Integer); static; public class function Check(const Value: Integer): T; static; end; { Range<T> } class function Range<T>.Check(const Value: Integer): T; begin if (Value < MinIntVal) or (Value > MaxIntVal) then RaiseException(Value); if TypeInfoCache<T>.IsSet then begin Move(Value, Result, SizeOf(T)); // here is the magic end; end; class function Range<T>.MaxIntVal: Integer; begin Result := TypeInfoCache<T>.MaxIntVal; end; class function Range<T>.MinIntVal: Integer; begin Result := TypeInfoCache<T>.MinIntVal; end; class procedure Range<T>.RaiseException(const Value: Integer); begin raise Exception.CreateFmt(SValueLiesOutsideAllowedRange, [Value, PTypeInfo(TypeInfo(T)).Name, MinIntVal, MaxIntVal]); end; { TypeInfoCache<T> } class constructor TypeInfoCache<T>.Create; var ti: PTypeInfo; typeData: PTypeData; i: Integer; begin ti := TypeInfo(T); FIsSet := ti.Kind = tkSet; if FIsSet then ti := GetTypeData(ti).CompType^; typeData := GetTypeData(ti); FMinIntVal := typeData.MinValue; if FIsSet then begin FMaxIntVal := 0; for i := typeData.MinValue to typeData.MaxValue do FMaxIntVal := FMaxIntVal or (1 shl i); end else FMaxIntVal := typeData.MaxValue; end; type TEnum = (en1, en2, en3); TEnumSet = set of TEnum; var en: TEnum; ens: TEnumSet; begin try try en := Range<TEnum>.Check(0); en := Range<TEnum>.Check(2); en := Range<TEnum>.Check(3); except on E: Exception do Writeln('Expected exception: ', E.ClassName, ' ', E.Message); end; try ens := Range<TEnumSet>.Check(0); ens := Range<TEnumSet>.Check(2); ens := Range<TEnumSet>.Check(7); ens := Range<TEnumSet>.Check(8); except on E: Exception do Writeln('Expected exception: ', E.ClassName, ' ', E.Message); end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; if DebugHook <> 0 then Readln; end. -
OT: I liked the depressive design, it fit well with the daily frustrating experience with the IDE. 👿
-
Debugging multiple DLLs simultaneously
TiGü replied to Neutral General's topic in Delphi IDE and APIs
I guess it will have a good reason/requirement why he needs to use an application with multiple DLLs. -
Debugging multiple DLLs simultaneously
TiGü replied to Neutral General's topic in Delphi IDE and APIs
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Winapi.Windows; procedure Main; var I: Integer; begin Writeln('Start'); while not IsDebuggerPresent do begin Writeln('I''m waiting for you!'); Sleep(100); end; for I := 1 to 1000 do Writeln(' I:', I); Writeln('End'); end; begin try Main; Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Try the good old While-Not-IsDebuggerPresent-Trick! -
They aren't necessary. Unfortunately, you can't hide them with Delphi Tools. https://stackoverflow.com/questions/24718716/delphi-xe6-dll-unwanted-export-tmethodimplementationintercept
-
Wow, it could be easier. You have to set the Converter.Options after casting to the EarsivWebService interface. Then they are not reset and you can avoid the AfterExecute handler. unit Earsiv.View; interface uses System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, EarsivWebService1, Soap.SOAPHTTPClient, Soap.OpConvertOptions; type TForm5 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private FRIO: THTTPRIO; FEarsivWebService: EarsivWebService; public end; var Form5: TForm5; implementation {$R *.dfm} procedure TForm5.FormCreate(Sender: TObject); begin FRIO := THTTPRIO.Create(nil); FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService'; FEarsivWebService := (FRIO as EarsivWebService); FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams]; end; procedure TForm5.Button1Click(Sender: TObject); var Request: faturaOlustur; Response: faturaOlusturResponse; begin Request := nil; Response := nil; Request := faturaOlustur.Create(); Request.input := 'Hello'; Request.fatura := belge.Create(); Request.fatura.belgeFormati := belgeFormatiEnum.PDF; try Response := FEarsivWebService.faturaOlustur(Request); finally if Assigned(Response) then begin if Assigned(Response.return) then begin ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText); end; Response.Free; end; Request.Free; end; end; end.
-
Hm, after the first request, the Converter.Options are fine and included soDocument and soLiteralParams...so there is room for improvement (calling MyHTTPRIO1AfterExecute only once and disconnect it afterwards from FRIO.OnAfterExecute or something).
-
Hi @ertank! I play with your code and do some debugging in the depths of the Delphi SOAP sources. As you can see in the TOPToSoapDomConvert.ProcessResponse (Line 2037 in Tokyo 10.2.3) it calls a inline class helper function IsBareLiteral. Making long story short: Set every time the THTTPRIO.Converter.Options (see Unit Soap.OpConvertOptions) and the Response will be filled. Try this: unit Earsiv.View; interface uses System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, EarsivWebService1, Soap.SOAPHTTPClient, Soap.OpConvertOptions; type TForm5 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private FRIO: THTTPRIO; WS: EarsivWebService; procedure MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream); public end; var Form5: TForm5; implementation {$R *.dfm} procedure TForm5.Button1Click(Sender: TObject); var Request: faturaOlustur; Response: faturaOlusturResponse; begin if not Assigned(FRIO) then begin FRIO := THTTPRIO.Create(nil); FRIO.OnAfterExecute := MyHTTPRIO1AfterExecute; FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService'; // the following line are not enough, see MyHTTPRIO1AfterExecute FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams]; WS := (FRIO as EarsivWebService); end; Request := nil; Response := nil; Request := faturaOlustur.Create(); Request.input := 'Hello'; Request.fatura := belge.Create(); Request.fatura.belgeFormati := belgeFormatiEnum.PDF; try Response := WS.faturaOlustur(Request); finally if Assigned(Response) and Assigned(Response.return) then begin ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText); end; Request.Free; Response.Free; end; end; procedure TForm5.MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream); begin FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams]; end; end.