how to popup this form use delphi ?
is ShellExecuteEx or ShellExecute can do this?
From the command line you can do this. (at least, on Win7 for me...()
rundll32.exe van.dll,RunVAN
So, just wrap that in a suitable ShellExecute or similar call.
Note that the dialog is designed to pop up in the system tray. I don't know how you'd get it to appear somewhere more obvious.
Also, have a look at this thread. There's another way mentioned here that describes how to do it in a possibly more useful fashion:
https://groups.google.com/forum/?hl=en&fromgroups=#!topic/microsoft.public.development.device.drivers/nPn-PH3g_2Q
If you want to invoke this from your program, it's simpler just to skip the rundll32 call. You can load the DLL yourself and invoke the function. For example:
procedure RunVANW(hwnd: HWND; hinst: HINST; lpszCmdLine: LPSTR;
nCmdShow: Integer); stdcall; external 'van.dll';
procedure ShowViewAvailableNetworksDialog;
begin
RunVANW(0, 0, nil, 0);
end;
I would expect that this functionality is not available on older versions of Windows, and almost certainly will be modified on future versions of Windows. So you may prefer to write the DLL import using LoadLibrary and GetProcAddress, and switch behaviour at runtime depending on whether or not the RunVANW function is available.
Related
I´m writing a global keyboard hook in Delphi 2007 and Windows 10. I´ve found different signatures for a Delphi LowLevelKeyboardProc callback. Someones like this and windows documentation (https://learn.microsoft.com/es-es/previous-versions/windows/desktop/legacy/ms644985(v=vs.85))
LowLevelKeyboardProc() never is executed
prompt that lparam is a pointer to a TKBDLLHOOKSTRUCT record.
Other ones however (http://www.delphifaq.com/faq/delphi_windows_API/f512.shtml and https://www.swissdelphicenter.ch/en/showcode.php?id=1722), show
function KeyHookFunc(Code, VirtualKey, KeyStroke: Integer): LRESULT; stdcall;
completely ignoring the TKBDLLHOOKSTRUCT record pointer.
Which one is correct?
I'm guessing the first one is the correct one but I need to be sure. I´ve been using such signature but when I call another Function in the same unit (and DLL) passing lParam it causes Access Violation when accessing it. All functions and procedures within the DLL use stdcall
All of the callback declarations are correct, although the latter two links do not give examples of LowLevelKeyboardProc but KeyboardProc. IOW, they are not low level keyboard hooks.
Note the latter two wouldn't work in 64 bits due to Integer usage instead of WPARAM, LPARAM and LRESULT.
I have a code exmple.
unit Unit1;
interface
uses
...
type
...
function Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: BOOL): BOOL; stdcall;
var
...
implementation
{$R *.dfm}
uses
...
function Wow64EnableWow64FsRedirection; external kernel32 name 'Wow64EnableWow64FsRedirection';
procedure LaunchOSK;
begin
Wow64EnableWow64FsRedirection(False);
try
ShellExecute(0, 'OPEN', PChar('osk.exe'), nil, nil, SW_SHOWNORMAL);
finally
Wow64EnableWow64FsRedirection(True);
end;
end;
end.
This code works fine in 64-bit OS. However, naturally when you try to use this in a 32-bit OS (XP) you get an error message (The procedure entry point Wow64Enable64FsRedirection could not be located in the dynamic link library kernel32.dll.). If you isolate Wow64EnableWow64FsRedirection and just run ShellExecute it launches fine.
I have beaten my head the past 2 days trying different things I have Googled and not one them of works as far as safely starting OSK in both 32 and 64 bit. Even a well known Delphi guru's suggestion does not work.
I do not need a lecture about disabling Wow64EnableWow64FsRedirection. Since it is temporary no harm no foul.
What I need is understanding how I can take this code and isolate the Wow64Enable64FsRedirection interface procedure and its accompanying implementation part and the necessary parts of the LaunchOSK procedure when the application is running on XP for example. Is this possible??? Compiler statements are useless, right?
If this is not possible then I will have to resort in producing 2 apps (one for XP and the other for 64 bit) which is a last resort.
Thanks in advance.
You can use dynamic loading and simply check whether the GetProcAddress function returns a valid function address.
Or you can use delayed loading and call the imported function only if the OS version and bitness matches necessary requirements.
Your code uses load time linking. The imported function must be present in the system or your executable will not start.
Instead you need to use run time linking. Use LoadLibrary and GetProcAddress to link to the function. If GetProcAddress fails to find the function then it isn't available and of course you don't need to call it because you are on a 32 bit OS.
The right way to do this though is to spawn a 64 bit process which can then launch the OSK process. And if ever you really do need to disable redirection do heed the documentation which tells you to use Wow64DisableWow64FsRedirection.
Finally it's always best to use CreateProcess to launch a process. There's nothing to be gained from involving the shell and file associations. Why ask the shell to call CreateProcess when you can do so directly?
OK, that's normally good advice, but once again, OSK is special. See Delphi - On Screen Keyboard (osk.exe) works on Win32 but fails on Win64.
I have a dll which defines a simple functions to show a message:
library testdll;
uses SysUtils, Classes, Dialogs;
{$R *res}
procedure ShowDll;stdcall;
begin
ShowMessage('ShowDLL testdll.dll');
end;
exports ShowDLL;
begin
end.
And my main file call this dll dynamicly using this procedure:
i defined a new type:
type
testdll = procedure;stdcall;
Then on my button click event:
procedure TForm1.Button1Click(Sender:TObject);
var
dllHandle: THandle; //Don't use Cardinal; it's limited to 32-bits
test : testdll;
begin
dllHandle := LoadLibrary('testdll.dll');
if dllHandle <> 0 then
begin
#test := GetProcAddress(dllHandle,'ShowDLL');
if Assigned(test) then
ShowDLL
else
ShowMessage('Func not found');
end
else
ShowMessage('dll not found');
end;
This works. But I don't know if it's possible to handle not defined functions with my dll. My purpose here is to call a function without knowing if it will be defined in my dll. So i would like the dll to tell me if the functions exists or not.
For example here i only have a ShowDLL procedure. If i call another method which does not exists it will show 'Func not found' from my main application. But i would my dll to tell me this. Is this possible? If yes, how could i achieve this pls?
EDIT: I can't modify the main function this is only a test. In my final version there will be only the dll. So exporting all functions into my main application is not possible here. That's why i want to know id the dll alone can handle it rather than doing this in my main application which i can't do.
I don't have acces to the main application to modify any code in it. I only know what are functions that will be used in this application that i will later export in my dll using exports statement. So what i try to achieve is to catch a not defined function with the dll if it's possible.
Your code already demonstrates how to detect the presence of an export. Namely to call GetProcAddress and compare the result with nil.
You can reduce the amount of boiler plate code by using delay loading. This essentially lets the compiler generate the code the performs the checks. This relies on the delayed keyword.
procedure testdll; stdcall;
external 'testdll.dll` delayed;
When you call this function, if it cannot be found, an exception is raised. Indeed this behaviour can be customised, as described in the documentation: http://docwiki.embarcadero.com/RADStudio/en/Libraries_and_Packages#Delayed_Loading
Update
In a comment to this answer you state that the executable cannot be changed. In which case, the message that you wish to avoid will be shown if the function is missing. You ask if the missing export can be handled by the DLL but that is not possible. When you call GetProcAddress, no code inside the DLL is executed. All the processing is done external to the DLL by reading its PE metadata.
The obvious conclusion is that the DLL must export the function. If the true DLL does not, put another DLL in its place. Use an interposer DLL that exports the function. Implement the function by delegating to the true DLL, if the true DLL exports the function. Otherwise do something else, whatever you please.
I would like to build a custom setup, with an aero form, but I don't know how to start it.
Is there any way to use DWM API with inno setup?
function dwm(Wnd: HWnd; cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight: integer ): Longint; external 'DwmExtendFrameIntoClientArea#dwmapi.dll stdcall';
DWM API is a native API so you can access it using the DLL Import method.
Then you can call API functions in your script code.
But I would recommend against doing this. Since the DWM only works on Vista or later and it can be disabled by stopping the NT Service. It could prevent your installation from working on a machine that it was designed to work on.
Now that you posted your code...
Original declaration of the API you posted.
HRESULT WINAPI DwmExtendFrameIntoClientArea(
HWND hWnd,
__in const MARGINS *pMarInset
);
My best guess is that it should look like this instead.
type
Margins = record
cxLeftWidth : Integer;
cxRightWidth: Integer;
cyTopHeight: Integer;
cyBottomHeight: Integer;
end;
function DwmExtendFrameIntoClientArea(Wnd: HWnd;
var pMarInset : MARGINS) :
HRESULT;
external 'DwmExtendFrameIntoClientArea#dwmapi.dll cdecl';
you can use the third party tool ISSkin for inno setup
http://isskin.codejock.com/
hope this helps
I would not use such an approach in a setup program, but if you you really need it I would develop it in Delphi, wrap it in a DLL with a simpler API, and call that DLL from InnoSetup.
There doesn't appear to be a simple component available to create a folder selection dialog in Delphi 2009, although a file selection dialog is provided by way of the TOpenDialog.
What is the most common way to create a modern folder selection dialog using Delphi?
There are two overloaded routines in FileCtrl.pas called SelectDirectory
For a modern look, use the second form, with sdNewUI
var
dir : string;
begin
dir := 'C:\temp';
FileCtrl.SelectDirectory('Select', 'C:\', dir, [sdNewFolder, sdNewUI], Self);
end;
NOTE: sdNewFolder, sdNewUI etc are only available from D2006+
you can use SelectDirectory from FileCtrl unit
using FileCtrl;
var
St: string;
begin
St:='c:\';
if SelectDirectory(St,[],0) then
begin
end;
end;
You can download a component PBFolderDialog from "http://bak-o-soft.dk/Delphi/PBFolderDialog.aspx" which is quite easy to use and offers access to all options of the Windows "SHBrowseForFolder" dialog; something which the built-in ones not do.
It's freeware with source and not too difficult to port to Delphi 2009.
See the sample code:
Delphi tip#157: select folder dialog
http://www.scalabium.com/faq/dct0157.htm