Anna Blanca 1 Posted July 16 Hello. I'm trying add Form in my DLL, and i hide it with next constraction: procedure Start; begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.ShowMainForm := False; Application.Run; end; exports Start; Earlier, in previous versions Delphi, my DLL worked normal, but exactly in 12-th Delphi version, all broked. When i launch my library through app, it's working normal, but when i launch through rundll32.exe - no one component on Form1 not working. What Embarcadero broked in this time and how fix it? P.S. I attach my project to this topic, you can open it and look all youselfe. Fucking DLL.zip Share this post Link to post
Remy Lebeau 1621 Posted July 16 (edited) Your Start() function is not compatible with rundll32. It's a wonder your code ever worked at all. You are invoking undefined behavior. Read: INFO: Windows Rundll and Rundll32 Interface Your Start() function MUST have the following signature in order for rundll32 to call it correctly: procedure Start(hwnd: HWND; hinst: HINSTANCE; lpszCmdLine: PAnsiChar; nCmdShow: Integer); stdcall; Edited July 16 by Remy Lebeau Share this post Link to post
Anna Blanca 1 Posted July 16 (edited) 19 hours ago, Remy Lebeau said: Your Start() function is not compatible with rundll32. It's a wonder your code ever worked at all. You are invoking undefined behavior. Hm-m-m, earlier, in Delphi 11, all worked normal and my library launched by rundll32.exe normal. So, and what is HINSTANCE? When i use it in my code, IDE underlining it by red.... No one module in uses not help. Edited July 16 by Anna Blanca Share this post Link to post
DelphiUdIT 253 Posted July 17 6 hours ago, Anna Blanca said: So, and what is HINSTANCE? When i use it in my code, IDE underlining it by red.... No one module in uses not help. HInstance is the instance (var) of the module, derived from System.pas (type HINST). Should be always defined and available 'cause it is used at loading time (look SysInit.pas) FYI, MainInstance in the HInstance of the MAIN APPLICATION (not the module like dll, library, ...). Share this post Link to post
Anna Blanca 1 Posted July 17 6 hours ago, DelphiUdIT said: FYI, MainInstance in the HInstance of the MAIN APPLICATION (not the module like dll, library, ...). In this case, my DLL is main application. So, what library i must add in uses? And i want message you, if my DLL launch normal, when i not hide Form1, when i not use Application.ShowMainForm := False; Share this post Link to post
Cristian Peța 122 Posted July 17 12 minutes ago, Anna Blanca said: my DLL is main application A DLL is a library and it can run only in the processes of a main application (rundll32 or other app). Share this post Link to post
Remy Lebeau 1621 Posted July 17 (edited) 17 hours ago, Anna Blanca said: Hm-m-m, earlier, in Delphi 11, all worked normal and my library launched by rundll32.exe normal. "Seeming to work fine" is a possible result of Undefined Behavior. That doesn't mean the code was right, though. rundll32 requires a very specific signature for the entry point function that it calls, and your code was not satisfying that requirement. Fix that first, and if your UI problem still occurs then we can focus on that next. 17 hours ago, Anna Blanca said: So, and what is HINSTANCE? When i use it in my code, IDE underlining it by red.... No one module in uses not help. Sorry, I keep forgetting that Delphi doesn't define HINSTANCE as a type. Use System.HINST or Winapi.Windows.HINST or THandle instead. Edited July 17 by Remy Lebeau Share this post Link to post
DelphiUdIT 253 Posted July 17 (edited) 26 minutes ago, Remy Lebeau said: Sorry, I keep forgetting that Delphi doesn't define HINSTANCE. Use System.HINST or Winapi.Windows.HINST or THandle instead. I wrote that, HINSTANCE is a global var. HINST is the type. Edited July 17 by DelphiUdIT Share this post Link to post
DelphiUdIT 253 Posted July 17 16 hours ago, Anna Blanca said: So, and what is HINSTANCE? When i use it in my code, IDE underlining it by red.... No one module in uses not help. Edited 15 hours ago by Anna Blanca Share this post Link to post
DelphiUdIT 253 Posted July 17 This are the project. Fucking DLL RUNDLL32.zip Share this post Link to post
Anna Blanca 1 Posted July 20 On 7/17/2025 at 6:42 PM, Remy Lebeau said: Sorry, I keep forgetting that Delphi doesn't define HINSTANCE as a type. Use System.HINST or Winapi.Windows.HINST or THandle instead. On 7/17/2025 at 6:57 PM, DelphiUdIT said: I wrote that, HINSTANCE is a global var. HINST is the type. Thanks for you all, but one problem is still now. I can't make LNK-file from my DLL: procedure TForm1.CreateLink(const PathObj, PathLink, Desc, Param: String); var IObject : IUnknown; SLink : IShellLink; PFile : IPersistFile; begin IObject := CreateComObject(CLSID_ShellLink); SLink := IObject as IShellLink; PFile := IObject as IPersistFile; SLink.SetArguments(PChar(Param)); SLink.SetDescription(PChar(Desc)); SLink.SetPath(PChar(PathObj)); PFile.Save(PWChar(WideString(PathLink)), FALSE); end; procedure TForm1.Timer1Timer(Sender: TObject); var S : String; begin S := TPath.GetHomePath + '\Linker.lnk'; CreateLink('FileName.jpg', S, 'Company', 'Argument'); Timer1.Enabled := False; end; When i use it in my DLL - nothing no happen. But when i use this in sample EXE - all working normal. Share this post Link to post
DelphiUdIT 253 Posted July 20 (edited) Hello, first of all is better that you tell us what do you expectt from the runing DLL (e.g. found a LNK file in .....). I think there is some issues about your knowledge (I talk about Windows 11). If you run from a cmd prompt a RUNDLL32, the HOMEPATH you refer is "C:\Users\YOUR ACCOUNT NAME\AppData\Roaming" So, here is where the LNK file is created. And it is always created. About the pointed link file (JPG): this file, without none path should be under UNKNOWN PATH. So the file will never be linked. If you comile and run like an EXE instead, the path where the JPG file is "linked" is in the same directory as exe is. The DLL works perfect as expected. Notes: 1) Like I wrote before, you should PUT the "Timer1.Enabled := False;" at the begining of the event procedure. 2) Is missing the "CoInitializeEx(nil, COINIT_MULTITHREADED);": without that the CreateComObject will fail. Edited July 20 by DelphiUdIT Share this post Link to post
Remy Lebeau 1621 Posted July 20 (edited) 4 hours ago, Anna Blanca said: When i use it in my DLL - nothing no happen. But when i use this in sample EXE - all working normal. Where does it fail, exactly? Your code is not doing any error handling/reporting. Are you creating a plain DLL, or a Runtime Package BPL? It is not safe to use Delphi-managed types like String across the DLL boundary in a plain DLL, without extra work (ie, like using the ShareMem unit in both EXE and DLL, etc). Did you verify your timer is running correctly inside your DLL? Does the thread that is calling into the DLL first call CoInitialize/Ex()? IShellLink is a COM object, so the COM library needs to be initialized on any thread that wants to access any COM object. DO NOT be tempted to call CoInitialize/Ex() inside your DLL, unless it uses COM in a thread that it creates for itself. It is the responsibility of a thread creator to decide how COM interacts with that thread, not the responsibility of functions called by a thread. Edited July 20 by Remy Lebeau Share this post Link to post
Anna Blanca 1 Posted Monday at 03:58 PM On 7/20/2025 at 5:41 PM, DelphiUdIT said: Hello, first of all is better that you tell us what do you expectt from the runing DLL (e.g. found a LNK file in .....). I think there is some issues about your knowledge (I talk about Windows 11). If you run from a cmd prompt a RUNDLL32, the HOMEPATH you refer is "C:\Users\YOUR ACCOUNT NAME\AppData\Roaming" So, here is where the LNK file is created. And it is always created. About the pointed link file (JPG): this file, without none path should be under UNKNOWN PATH. So the file will never be linked. If you comile and run like an EXE instead, the path where the JPG file is "linked" is in the same directory as exe is. The DLL works perfect as expected. Notes: 1) Like I wrote before, you should PUT the "Timer1.Enabled := False;" at the begining of the event procedure. 2) Is missing the "CoInitializeEx(nil, COINIT_MULTITHREADED);": without that the CreateComObject will fail. O'K, but LNK-file not created. But earlier, in Delphi 11, it's created normal. Share this post Link to post
Anna Blanca 1 Posted Monday at 04:01 PM 22 hours ago, Remy Lebeau said: Are you creating a plain DLL, or a Runtime Package BPL? I'm creating plan DLL. 22 hours ago, Remy Lebeau said: It is not safe to use Delphi-managed types like String across the DLL boundary in a plain DLL, without extra work (ie, like using the ShareMem unit in both EXE and DLL, etc). I'm not acrossin DLL boundary. I'm just trying meke LNK-file in DLL, working through rundll32.exe, nothing more. Share this post Link to post
Remy Lebeau 1621 Posted Monday at 04:30 PM (edited) 29 minutes ago, Anna Blanca said: I'm creating plan DLL. As mentioned earlier, CoInitialize/Ex() is required to work with COM objects, like ShellLink. But there is no call to CoInitialize/Ex() in your code. In a VCL application, that is called automatically for you. But in this case, rundll32 will not call it for you, so you will have to call it yourself. Call CoInitialize/Ex() at the beginning of your Start() function, and call CoUnintialize() before exiting from Start(), eg: procedure Start(hwnd: HWND; hinst: HINST; lpszCmdLine: PAnsiChar; nCmdShow: Integer); stdcall; begin if Failed(CoInitialize(nil)) then begin // report the error some where ... Exit; end; try ... finally CoUninitialize; end; end; And add some error handling/logging to your CreateLink() function, eg: procedure TForm1.CreateLink(const PathObj, PathLink, Desc, Param: String); var IObject : IUnknown; SLink : IShellLink; PFile : IPersistFile; begin try IObject := CreateComObject(CLSID_ShellLink); SLink := IObject as IShellLink; PFile := IObject as IPersistFile; OleCheck(SLink.SetArguments(PChar(Param))); OleCheck(SLink.SetDescription(PChar(Desc))); OleCheck(SLink.SetPath(PChar(PathObj))); OleCheck(PFile.Save(PWChar(WideString(PathLink)), FALSE)); except // report the error somewhere ... end; end; 29 minutes ago, Anna Blanca said: I'm not acrossin DLL boundary. I'm just trying meke LNK-file in DLL, working through rundll32.exe, nothing more. If all you want is command-line access to the ShellLink object, then why use rundll32 at all? You could use a Powershell script instead. Look at the New-Object command: Creating COM objects with New-Object 29 minutes ago, Anna Blanca said: I'm just trying meke LNK-file in DLL, working through rundll32.exe, nothing more. Have you tried debugging your DLL yet? Are you aware that the IDE can debug a DLL project? Simply set rundll32 as the Host for the project, and then you can run the project and step through your code normally. Where exactly is your code actually failing to behave the way you are expecting? Edited Monday at 04:32 PM by Remy Lebeau Share this post Link to post
DelphiUdIT 253 Posted Monday at 05:59 PM (edited) 1 hour ago, Anna Blanca said: I'm creating plan DLL. I'm not acrossin DLL boundary. I'm just trying meke LNK-file in DLL, working through rundll32.exe, nothing more. Try this. The DLL is present, but you can build the project, and then simply run directly from terminal line this (you must be in the path where the DLL is present): RUNDLL32 d.dll,Start Pay attention that you MUST CHANGE THE PATH AND THE FILENAME LINKED IN THE SOURCE, if you want that the link open the right file. NOTE: In the other console windows that should open, is going to be printed the path of the LNK file. Fucking DLL RUNDLL32.zip Edited Monday at 06:01 PM by DelphiUdIT Share this post Link to post
Anna Blanca 1 Posted Wednesday at 07:43 PM On 7/21/2025 at 7:30 PM, Remy Lebeau said: If all you want is command-line access to the ShellLink object, then why use rundll32 at all? You could use a Powershell script instead. Look at the New-Object command: I want make ShellLing object only with Delphi resources. On 7/21/2025 at 7:30 PM, Remy Lebeau said: Have you tried debugging your DLL yet? Are you aware that the IDE can debug a DLL project? Simply set rundll32 as the Host for the project, and then you can run the project and step through your code normally. How i can make it? Share this post Link to post
Anna Blanca 1 Posted Wednesday at 07:48 PM On 7/21/2025 at 7:30 PM, Remy Lebeau said: As mentioned earlier, CoInitialize/Ex() is required to work with COM objects, like ShellLink. But there is no call to CoInitialize/Ex() in your code. In a VCL application, that is called automatically for you. But in this case, rundll32 will not call it for you, so you will have to call it yourself. Call CoInitialize/Ex() at the beginning of your Start() function, and call CoUnintialize() before exiting from Start(), eg: May be, better make that: procedure Start(hwnd: HWND; hinst: HINST; lpszCmdLine: PAnsiChar; nCmdShow: Integer); stdcall; begin if Failed(CoInitialize(nil)) then begin CoUninitialize; end; end; Not? Share this post Link to post
Remy Lebeau 1621 Posted Wednesday at 08:01 PM 13 minutes ago, Anna Blanca said: I want make ShellLing object only with Delphi resources. Why, though? This is clearly not the best solution for your use-case since you are having so much trouble with it for such a small task. 13 minutes ago, Anna Blanca said: How i can make it? Just as I described earlier. Configure your DLL project's Run settings to specify rundll32 as its Host application. Then you can run the project normally in the IDE, it will execute rundll32, and the debugger will attach to that process and let you debug the DLL code. Share this post Link to post
Remy Lebeau 1621 Posted Wednesday at 08:03 PM 13 minutes ago, Anna Blanca said: May be, better make that: Not? Absolutely not. Why would you consider uninitializing something it when it fails to initialize? Share this post Link to post