WMDropFiles problem on win7 - delphi

I've implemented the following procedure and it works properly when I compile it on my computer running windows vista, computer #1. If I share the created .exe file to another computer running win7, computer #2, it runs fine aswell. The problem is when I let the computer #2 compile it, it wont simply recognize that anything's dropped on the application. There's no response at all in this code. It's built and compiled without errors or warnings.
I've been searching the net for a while without finding anything that explains why this happens or someone else with this problem.
Both computers use Delphi 2010 with the same components installed.
Is this the way to go to allow the user to drop files onto the application? If not, how should it be done nowdays?
Any ideas why it works when it's compiled on computer #1 but not computer #2? (The program works properly on both computers when compiled on computer #1)
Any help or comment is highly appreciated.
procedure TfMainForm.WMDROPFILES(var msg: TWMDropFiles);
const
MaxLength = 255;
var
nFiles : integer;
i : integer;
fileName : array [0..MaxLength] of char;
fileNames : TStringArray;
begin
// Get number of files dropped
nFiles := DragQueryFile(msg.Drop, $FFFFFFFF, fileName, MaxLength);
// Get filenames
SetLength(fileNames, nFiles);
for i := 0 to nFiles - 1 do begin
DragQueryFile(msg.Drop, i, fileName, MaxLength);
fileNames[i] := fileName;
end;
// Add files
projectHandler.addFiles(fileNames);
//release memory
DragFinish(msg.Drop);
end;

I'm going to take a wild guess that if you are running from within the IDE on computer #2. I bet that if you compile on computer #2 but start the executable from explorer rather than from the IDE, it works. The final piece of the jigsaw is that I bet you are running your IDE on computer #2 as administrator.
On Vista and Windows 7 you can't send messages to a process with a higher integrity level. If your process is being run as administrator then it will have a higher integrity level than explorer and so won't accept the dropped files.
If my guess is correct I recommend that you stop running Delphi as administrator, it doesn't need this.
As for whether or not WM_DROPFILES is a reasonable approach, I see no problems with using it.

At http://www.web-developer.de/content/download/7387/137496/file/Listings.zip you can find an example written using Delphi XE (compiles with D2010 as well). The subfolder "2_WmDropFiles" contains a project "WmDropFiles.dpr" that shows how to an app that runs elevated can receive files from an app which does not run elevated. The comments etc. are in German, so please use Google translate when in doubt.
Hope this helps,
Olaf

Related

Can't detect network drive under Debugger with Delphi 2007 on Windows 10

It is probably me being stupid, but I am having problems detecting if a network drive is up, but only when running the program in the IDE – when running the program outside of the IDE, the network drive is correctly detected. The IDE works fine on Windows 7.
While the program in question is different, I can reproduce the issue by creating a new project and adding the following into the Forms OnActivate event:
var
bRet: Boolean;
LTemp2: string;
LFreeSpace: Int64;
LTotalSpace: Int64;
begin
LTemp2 := 'T:\';
bRet := GetDiskFreeSpaceEx(PAnsiChar(LTemp2), #LFreeSpace, #LTotalSpace, nil);
ShowMessage('GetDiskFreeSpaceEx: Drive T: is up? '+BoolToStr(bRet, True));
end;
Assuming I have a networked drive T:, if I run the program in the IDE then the above always returns False, but if I run the built program from a desktop shortcut then it returns True. I get the same behaviour if I run it via a button click after the program starts. Doing DiskSize() and FindFirst() on the root directory give the same results.
It is a clean Windows 10 install, not an upgrade, with a clean install of CodeGear 2007 with all the patches applied. I have tried “Run as administrator” and all the Compatibility Modes back to Windows 7.
Am I doing something stupid?
After R. Hoek's great insight, and while it does not fully sort out the issue, it is at least enough for a workaround. By the way, at least in my case, it does not matter if I launch Delphi 2007 with "Run as administrator" or not.
I added a TOpenDialog hooked up to a button: once I run this and select a file on T: then GetLogicalDrives() works fine.
So what I now suspect is that I installed Delphi 2007 as an administrator - not sure how, but I think I will re-install everything.
Even if that does not resolve it, and since it only occurs in the IDE and not in production usage, I can add code to pop up a TOpenDialog if GetLogicalDrives() returns 4.
Weird. Thank you all very much.
By the way, one aspect of this discussion may not have been clear: Delphi 2007 was running under the user account (and it could see the network drive without problems) - it is only the program which is being debugged that cannot see the networked drive. That is why using the TOpenDialog resolved the issue (until Delphi or the computer was restarted).

Unable to load Firebird client library on Windows 10

Tw days ago, I installed Windows 10 build 1709 16299.192 and Embarcadero Delphi 10.2.2 Tokyo.
Since I installed them, my applications can't load the Firebird client library at runtime.
If I have an exe file compiled with older Windows and Delphi 10.2.2, it works fine, but every exe file compiled with the new Windows and Delphi are not working.
If I test a connection through TFDConnection, it connects successfully, but when I run the application I get this error:
[firedac][phys][fb]-314 cannot load vendor library [c:\users\username\desktop\projectname\bin\fbclient.dll] The specified module could not be found
Hint: check it is in the PATH or application EXE directories, and has x86 bitness.
The path is correct, and the client library is for x86. The same application was working before installing Windows 10 build 1907 16299.192.
I tried DevArt UniDac and compiled as Win64, still have the same problem.
Reinstalling Windows and Delphi 10.2.2 (tested with 2 versions 25.0.28979.1978 and 25.0.29039.2004) still didn't help.
I think it's a permissions issue, but I don't know how to fix it. I gave bds.exe all permissions over all groups, but still not working.
I have only this code on my test application
procedure TForm1.FormCreate(Sender: TObject);
var
Path: string;
begin
Path := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
FDPhysFBDriverLink1.VendorHome := Path;
FDPhysFBDriverLink1.VendorLib := 'fbclient.dll';
FDConnection1.Params.Database := Path + 'FBDV3.0.FDB';
FDConnection1.DriverName := 'FB';
FDConnection1.Params.UserName := 'sysdba';
FDConnection1.Params.Password := 'masterke';
FDConnection1.LoginPrompt := False;
FDConnection1.Connected := True;
end;
Included Files and Folders in bin Folder:
plugins (Folder contain engine12.dll)
fbclient.dll
ib_util.dll
icudt52.dll
icudt52l.dat
icuuc52.dll
I just had to install the Microsoft Visual C++ 2010 Redistributable.
It took me hours of trying and trying many things, I couldn't find any clue what causes it, even by debugging deep into the FD sources (Delphi 10.4.2). Too bad there is no useful error message anywhere. But then I used SysInternals Process Explorer and found this dependency. Thanks to #Remy.
(Just copying msvcr100.dll didn't help in my case.)
Of course I cannot say if this would have helped here, but at least it could help many others. The symptoms were the same - it worked in the IDE (data explorer), but not in the compiled application, even though the dll was there.
By debugging I also verified that the error message asking for not only fbclient.dll, but also fbembed.dll, is not a sign of any wrong parameters: it is always looking for the second one if the first one cannot be loaded (not only if it is not found).

Prepare exe for distribution

May I ask for some guidance please ?
Development machine – Windows 7 64bit
IDE – Delphi 7 pro (with 7.1 update)
Target machine for install – Windows XP (SP3) – NB this is the Win 7 Virtual Machine
I have built a small application, nothing more than a test app. A grid, a TADOConnection connected to an MS accdb file and a few TADOTables. Using Inno Setup I have also built an installer. I promise, it’s a very simple app.
When I install the ‘application’ on the XP virtual machine, everything goes according to plan, ie no error message and the installer completes. However, the application will not start. On the same XP VM, I have D7 installed and, here’s where it get’s weird, if the IDE is running, my application will launch without issue. If I close the IDE, it, my application, will fail to start again.
All I get is an hourglass for a second or two, and that’s it … no error message, no horrible MS dialog asking me if I want to send them info about this dreadful application, in fact I get no feedback whatsoever.
NB - Whether run from the IDE, or outside of the IDE, on the Win 7 machine, the application runs just fine.
I’m obviously missing something quite obvious, but I’m lost. I have even tried ….
program Project1;
uses
Dialogs,
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
ShowMessage('Starting');
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
But I do not get to see the ShowMessage dialog.
I have read the many ‘Hello World’ tutorials. Gleaned a great deal of knowledge from generous SO contributers (thank you). But there must be another tutorial that teaches me what to do in order to ‘prepare’ my application for inclusion in an installer. I thought that if I unchecked the ‘Build with runtime packages’ in Project Options and then did Project > Project Build, I could build a file with everything I needed to run the application outside of the IDE.
May I ask if anyone could point me to the last piece of the jigsaw, please ?
Incidentally, is there a way to debug an executable outside of the IDE ? Perhaps some switch within Delphi that would produce a log file when the application starts … or tries to.
Thanks for your time ?
Regards,
John.
EDIT - I mentioned earlier that the file will run outside of the IDE on my W7 machine. I got this wrong ... it won't run unless D7 is up and running too. Also, I made a copy of the original folder with this file in and started messing with the Project Options switches. Suddenly, the new file is twice the size and runs OK. Problem ... I can't replicate whatever I changed on the original file / Project to know for certain what I have done is the cause / fix.
Edit 2 - OK - the issue definately has something to do with the different file sizes. I have created a folder on the XP volume and dropped a copy of all of my BPLs from the Output directory in Win 7 Delphi install. Dropped my exe (the file that will NOT run outside of the IDE) in there, and also my accdb file too. Double click and ... Hey Presto - it runs. the grid displays my sample data ... beautiful.
Here's the thing ... Project > Options > Packages > Build with Runtime Packages is UNchecked. This should build me a LARGE exe file - (is that correct) but it builds a relatively small exe that needs the BPL's !!!!
Will do some more testing ...
You probably have your tconnection as connected in the ide.
That lets you see how things will look with real data within the IDE, but now when you run your application, it tries to connect right at the start, when maybe not everything is set up correctly yet.
One possible solution: leave the connection component disconnected, and connect at a later stage, for example via a "connect" button.
At least it will be easier to properly handle exceptions like that.

Safest way of using Outlook ActiveX

Just after running my Delphi application i check for the installed MS Outlook version because my app works differntly if in the machine there is a Outlook version greater than 2007.
I also wrote an Outlook Addin that sometimes crashes. I suspect
those crashes are related to the Outlook instances I create at startup.
Is there a way to create these ActiveX instances in a "softer way". As i create the OLE object now I see in Tray Bar an icon whose hint says "Outlook is being used by another application", may be if it were possible to remove this I would also see my problems disappear.
Somehow what I would like to achive is the same done here, where the wdDoNotSaveChanges parameter allows a "smoother" use of the OLE Object.
This is the code i use to check for Outlook version:
var
OutlookApp: OLEVariant;
Version : String;
begin
{ Create the OLE Object }
Try
OutlookApp := CreateOLEObject('Outlook.Application');
Version := OutlookApp.version;
OutlookVersion := StrToint(SubstrEx(1,Version,'.'));
OutlookApp := VarNull;
except
on E: Exception do
begin
OutlookVersion := -1;
end;
End;
Your approach is different from the one suggested by Microsoft here:
How to: Check the Version of Outlook .
Their version uses the Microsoft Installer functionality to detect the location of the Outlook executable, then extract the file version straight from there. This approach doesn't suffer from any of the problems you might encounter when instancing Outlook like you do. It is also a lot faster.
It does however suffer from one major disadvantage: it will only work if Outlook is deployed properly, the Microsoft way. On consumer machines this isn't so much of a problem, but in enterprise environments you might (/will) occasionally run into stripped down custom installs by overzealous IT departments that do not include the necessary MSI footprint.
Depending on your target audience, that might not be a real problem at all.

How should developers cope with so many GUI configuration combinations?

These days, any decent Windows desktop application must perform well and look good under the following conditions:
XP and Vista and Windows 7.
32 bit and 64 bit.
With and without Themes.
With and without Aero.
At 96 and 120 and perhaps custom DPIs.
One or more monitors (screens).
Each OS has its own preferred font.
Oh my! What is a lowly little Windows desktop application developer to do? :(
I'm hoping to get a thread started with suggestions on how to deal with this GUI dilemma.
First off, I'm on Delphi 7.
a) Does Delphi 2010 bring anything new to the table to help with this situation?
b) Should we pick an aftermarket component suite and rely on them to solve all these problems?
c) Should we go with an aftermarket skinning engine?
d) Perhaps a more HTML-type GUI is the way to go. Can we make a relatively complex GUI app with HTML that doesn't require using a browser? (prefer to keep it form based)
e) Should we just knuckle down and code through each one of these scenarios and quit bitching about it?
f) And finally, how in the world are we supposed to test all these conditions?
For the moment I would like to answer only one question:
f) Use virtual machines and (if possible) automated tests. I know it is a big job to set this up but you will never regret.
I, too, am a lowly Windows developer (D7) - much more interested in solving my vertical market application user's problems than coping with M$ foibles.
I cobbled up up a component to deal with all with these issues, plus some more.
As far as I know, all the pieces were in the public domain, and I have credited them where possible.
These are some of the properties:
type
TAppEnvironment = class(TComponent)
private
{ Private declarations }
// environment management
FEnvError : TEnvError; // environment error code
FEnvErrorMsg : string; // environment error message
FEnvLocalComputerName : string; // name of the client computer
FEnvCurrentUserName : string; // logged-on user
FEnvCurrentUserAdmin : Boolean; // is logged-on user Admin?
FEnvProduct : string; // windows edition
FEnvProductFlavour : string; // windows flavour (Home/Pro)
FEnvBuildNumber : string; // windows build number
FEnvServicePack : string; // windows service pack
FEnvThemeActive : Boolean; // Windows Theme active
// calc using product & theme
FEnvTitleHeight : integer; // window title height
FEnvMenuHeight : integer; // window menu height
FEnvStatusHeight : integer; // window status bar height
FEnvBorderHeight : integer; // window border height
FEnvMainHeight : integer; // main menu window height
FEnvMainWidth : integer; // main menu window width
FEnvHeightAdjust : integer; // window height adjust
FEnvWidthAdjust : integer; // window width adjust
FEnvLocalPath : string; // App exe home folder
FEnvAppFolderName : string; // application name less extension
FEnvAppFileVersionStr : string; // like 6.0.0.4567
FEnvAppFileVersion : TFileVersion; // HiVersion, LoVersion, etc.
And some utilities:
function EnvironmentReady : TEnvError;
function GetLocalComputerName : string; // network needs this
function GetAppFolderName : string;
function BuildNumber : Integer;
procedure GetFileInfo(const AFileName: string; var RFileInfo: TFileInfo);
function GetLocalPath : string;
procedure getEnvWindowAdjust(bar : TStatusBar);
function setAppFileVersionStr : string;
function GetFileTime(const FileName: string): LongInt;
function initEnvironment : Boolean;
function exitEnvironment : Boolean;
function AlreadyRunning : Boolean;
function specialBuild : Boolean;
I have a function to size each form correctly, using FEnvTitleHeight, etc.
All the dumb user paths are also generated, depending on Windows version.
I have no clue as to how to manage the process, but if people want, I will toss the whole thing into the pot - so that the masters can work it over.
Excellent question.
I've been developing my application for over 10 years, starting with Delphi 2, 3 and then 4 and then staying there and waiting many years to upgrade to Delphi 2009 because Unicode was a must. I'll upgrade again when the 64 bit version comes out.
So I've run the gamut of Operating Systems: Windows 98, Windows 2000, XP, Vista and now 7. Each breaks your UI somewhat, but Delphi has been pretty good about it. At some point in time, you have to decide you cannot support the older OS's anymore, and moving to Unicode finally cut out Windows 98 from my supported list.
Generally, I've found that core Delphi gives you the best UI support. Some third party packages may appear to provide more, but their inconsistencies are worse problems than their benefits might be. Minimize other packages where you can.
The one UI goal I've had is to go for the Windows Vista Logo Program, and more recently the Windows 7 program, and Microsoft does provide a lot of information on what the standards should be that relate the your conditions 1 to 7 in your question. But getting a Delphi program to use a manifest and go through Microsoft's hoops was in the end, not worth the hassle and cost to me, especially since my non-compliant program worked just fine on Vista and 7.
Keeping my program running and keeping the UI looking the same on Windows XP, Vista and 7 when I am developing on a 64-bit Vista machine means I use Microsoft Virtual Machine when I need to. I have been told my program also works on Wine, so that's another test machine.
Now answering your questions:
a) Does Delphi 2010 bring anything new to the table to help with this situation?
Yes. Every version adds new VCL components that have been added to the new OS's. e.g. Windows 7's new UI's have been added.
b) Should we pick an aftermarket component suite and rely on them to solve all these problems?, and c) Should we go with an aftermarket skinning engine?
As I said above, I think its better to do it in Delphi itself than in a 3rd party package.
d) Perhaps a more html type gui is the way to go. Can we make a relatively complex gui app with html that doesn't require using a browser? (prefer to keep it form based)
My application is like a Word Processor with Rich Text. I've looked at HTML-based editor suites and there are a few, but I don't think its the way to go for a desktop application. If you want a web-based application, you would be better off with .NET and Prism.
e) Should we just knuckle down and code through each one of these scenarios and quit bitching about it?
Upgrade to Delphi 2010 first. You'll find Delphi itself will handle most of those situations for you.
f) And finally, how in the world are we supposed to test all these conditions?
Doing it yourself is a big task, even with virtual machines. What you've got to do is have an open Beta and get as many different users in different environments to test your program for you. Then you'll handle all the environments that are most important to your users.
Now, if you think getting user interface compatibility in different Windows environments is tough, just wait until Embarcadero comes up with their version of Delphi that will compile for the Mac. Your current UI worries will seem trivial by comparison to what it will then become.
For te scaling of your forms on multiple resolutions / DPI sizes: we use DevExpress LayoutControl for that. It makes sure that the controls on your form always align to use the available space, no matter what. And it does a lot more. Have a look at their site.
Delphi 2010 brings native Unicode support.
Delphi 2010 brings Windows Vista/Seven controls.
There is no 64 bit Delphi compiler for the moment beeing.
You should'nt have any problem to handle dpi and monitor count questions with Delphi 7
Delphi makes that fairly easy, but in the end you'll have run your software on all Windows versions and visually check that everything looks fine. Automated test are great to test the functionality, but the cosmetics can be checked visually only.
Delphi 2009 brought in support for theming (it is an application level setting). When you run a Delphi 2009 or above application in Vista / Windows 7, it changes the message boxes to TaskDialogs, so you get some UI improvements for free.
We had a bit of a struggle porting to Delphi 2009, and Unicode, but that was a 'technical debt' that we had to pay at some point.
Hope this helps.

Resources