We are developing a console software, with Delphi 7.
To simplify, this software is using an embedded TCP server to answer to external requests from a CGI. These answers contain generated HTML pages with Teechart graphs, and data extracted from a database, using DbExpress.
On Windows 7 and Windows 2008 R2 servers, we noticed significant increase of the run time of our software – 2 or 3 times the original process time on Windows XP or Windows Server 2003 – in a standard context of execution: software launched as a Service with the system user account.
But when our software is launched as a simple user, from command prompt, or directly from the IDE (debug mode), the problem simply disappear.
My first question is : has anyone already noticed this problem?
Using ProcessExplorer, we also noticed that when the software is launched as a service, there is no GDI Handle created, nor is a User Handle. But when the software is launched with a user account, some of these handles are created. With Windows XP and Windows Server 2003, either the software is launched as a service or with a simple user account, these handles are always created.
Can this observation be linked with our problem?
If you already noticed these behaviour, how did you fix the problem?
Because of the many places where we relied on Windows API CompareString function we could not replace it by non Windows versions.
But, we found that instead of using LOCAL_USER_DEFAULT by using LOCALE_INVARIANT($07) the API works fine.
So, we decided to hack the constant value as defined in Windows and over write it everywhere where it was used for comparison purposes with a conditional compilation like this:
{$IFDEF OVERLOAD_LUD}
const
LOCALE_INVARIANT = $7;
LOCALE_USER_DEFAULT = LOCALE_INVARIANT;
{$ENDIF}
That solved the problem.
I think we found the source of our problems. So for those that are looking for a solution, here's what we’ve done:
Delays are due to the use of Win32 API functions using locals. Using a Locale Identifier functions are now being deprecated in favor of using the Locale Name functions (see http://msdn.microsoft.com/en-us/library/windows/desktop/dd319091%28v=vs.85%29.aspx).
Our developments use significantly “CompareString” (http://msdn.microsoft.com/en-us/library/windows/desktop/dd317759%28v=vs.85%29.aspx), including the use of the indexOf method of the TStringList .The execution of this method (CompareStringA of kernell32) is slowed while running in the user context System (in Session 0).
To get around this problem, we overloaded TStringList with CompareStr instead of CompareString. This workaround suits in our context but CompareStr makes comparisons bit to bit and isn't case sensitive unlike CompareString. (Not to mention the fact that this method is about 10 times faster ... http://www.gefvert.org/blog/archives/651)
Another solution would be to switch to a newer version of the IDE, but we all know that this is another story...
Related
I use CreateDXGIFactory to create a IDXGIFactory(the oldest version), and then use this IDXGIFactory to query IDXGIFactory6, it succeed.(My system version is Win10 1803).
1.So, is this fuction CreateDXGIFactory always create the newest version of IDXGIFactory which the system support?
The similar thing, D3D11CreateDevice create the base version of ID3D11Device, and I can query the ID3D11Device3 successfully?
2.The second question, is fuction D3D11CreateDevice create the newest version of ID3D11Device which the system support?
D3D11CreateDevice is simpler because it is a single entry point. The documentation does not operate with terms "older version" and "newer version". Instead it suggests that API creates an object with requested interface, and which is adequate to the system you are on and to requested creation arguments (feature level and such). Following that you can obtain access to newer features, when available, by querying newer interfaces, which documentation suggests as well:
To create a Direct3D 11.1 device (ID3D11Device1), which is available on Windows 8, Windows Server 2012, and Windows 7 and Windows Server 2008 R2 with the Platform Update for Windows 7 installed, you first create a ID3D11Device with this function, and then call the QueryInterface method on the ID3D11Device object to obtain the ID3D11Device1 interface.
To create a Direct3D 11.2 device (ID3D11Device2), which is available on Windows 8.1 and Windows Server 2012 R2, you first create a ID3D11Device with this function, and then call the QueryInterface method on the ID3D11Device object to obtain the ID3D11Device2 interface.
That is, you start creating device the same way and then you query new interfaces. Implementation may or may not respond by stepping up to "newer implementation" depending on whether you ever queried those new interfaces. Either way it remains implementation specific, including that such behavior can technically be changed as long as it transparent to applications consuming the API in this documented way.
With DXGI there are two API entry points CreateDXGIFactory and CreateDXGIFactory1. The documentation suggests that you don't mix API consumption via 1.0 and 1.1 interfaces.
Do not mix the use of DXGI 1.0 (IDXGIFactory) and DXGI 1.1 (IDXGIFactory1) in an application. Use IDXGIFactory or IDXGIFactory1, but not both in an application.
This does not necessarily mean that the two functions are creating different factories. Microsoft reserves the right to adjust the behavior as long as you abide by documented guidelines.
If you are not going to do anything that goes beyond DGXI 1.0 you can use CreateDXGIFactory on older and newer systems. If you need features of 1.1 and above you are supposed to start with CreateDXGIFactory1. Also note that the two functions have different availability across environments and this is one of the reasons they two exist in first place.
I am developing Delphi application on Delphi 2010 XE RAD Studio under Windows 7. My application talks on the serial port non-stop. I am using AsyncPro for Delphi 2010. Serial communication and everything else on the computer I develop with works great without any problem. However, when my release version of my application is run on another Windows 7 system, serial communication completely fails. We probed the serial communication itself for an answer and found out that Request to Send (RTS) line is not dropped right after sending all the bytes, whereas on my development computer RTS line is dropped correctly.
Even when I explicitly drop the RTS line to low or false state, RTS line doesn't drop right away but after good 15 milliseconds. Thus, serial communication on my release version is failing.
Am I missing important information about Windows 7 and serial communication issues?
UPDATE: I just found the bug with my Aysncpro 5.0 for Delphi XE. It is weird. When my Delphi XE IDE is open or running, my program is communicating flawlessly. When I shutdown or close my Delphi XE IDE while my program is running, the same program doesn't communicate very well or it times out.
Chime in if you have any idea why it is happening.
Any help will be appreciated.
Thank you,
Sounds like a timer resolution problem to me. I had the same problem trying to write to a USB FTDI driver using an event based timer with timeSetEvent()... When Delphi loads, it changes the timer resolution to less than 20ms, which made my app work fine. When the IDE wasn't running I couldn't get things to work below 20ms +/- 5ms (the default Windows resolution I believe).
To fix the problem, I call timeBeginPeriod(1) in the thread to set the minimum system wide timer resolution.
I believe this affects the resolution of other time based events, because I get better than +/-5ms accuracy on other (non-multimedia timer) wait events in my app when I use timeBeginPeriod().
So, what I'm suggesting is that somewhere in the AsyncPro code it's using some time based event or call back... That would be affected by Delphi's change to the timer resolution when it is loaded. Try calling timeBeginPeriod(1) somewhere in your app when it starts and see if there is a change.
Oh, and don't forget to call timeEndPeriod(1) when your app shuts down.
N#
Last few times I saw random inexplicable crap like I tried everything, and was unable to solve it for months.
I found two different common causes:
ASYNC Professional has some weird glitches that I was unable to solve, so I dropped it, and moved to TComPort.
I found all kinds of strange flow control bugs in USB drivers. I found FTDI chipset USB-to-serial more reliable than others.
The Debug build not having the problem could be two things:
Certain timing changes cause the USB device driver that was failing, not to fail.
You actually have some kind of a thread problem, like a race condition, leading to your ASync Pro components messing up in a way that looks like something's happening to your port, but really it's ASYNC pro.
The easiest thing to do is to try it with a different USB to serial adapter, and if that doesn't solve your problem, I would be tempted to pull out AsyncPro which I have also had many random problems with, and either write your own serial port class, or use TComPort. I have some long experience using a TThread that uses a com port "reader/writer" class and have found this the most reliable way to go, because you can tweak low level elements of the Win32 overlapped-IO calls, directly to meet your needs, and also be sure that you don't have some extra complexity/overhead getting in your way. (AsyncPro's complexity and overhead, are a significant potential source of bugs.)
This has to be a driver problem on the other machine, surely? Hardware flow control works fine on my W7 test box as well, (and Vista development machine). If your Apro has set the DCB correctly, and it sounds like it does because of your 'manual' tests, the driver should work...
15ms for a 'manual' RTS change from user mode is sad, but not at all unusual on Windows - that's why the driver should do it.
Rgds,
Martin
I have developed a simple win 32 service in delphi 7 which performs some print operations. All works fine on our XP machines, but fails on the target Windows 2008 standard server. When I put a try except block around the print statement, it results in the "Printer Selected is not valid" error.
When I check the Printer object for count of printers and event write out all the printers available in the Printer object to a file, it works fine. Only when I try to perform a print (on any printer local and network), it fails.
Based on lot of research using google, I found quite a few suggestions to use local acct, network acct, specific acct, LogonAsUser, ImpersonateUser, LoadUserProfile, etc, etc. but nothing is working. I have also set up security on the installed printers to be accessible to everyone.
This thing is really driving me crazy. Any help is greately appreciated.
Thanks
This is likely due to Session 0 Isolation, which was introduced in Vista. Services always run in Session 0, but in XP and earlier, the first user to log in also runs in Session 0, thus allowing services to access that user's desktop (thus allowing for "Interactive" services) and resources (like shares and printers). In Vista onwards, users never run in Session 0 anymore, so services do not have access to user-specific resources anymore. A service has to impersonate the user account it wants to access.
Always hard to answer an "it doesn't work" question. But I can speculate. Microsoft has warned about printing from a service in the past. I think the problem is that printer drivers are rarely designed to run in the kind of service environment that Windows 2008 provides. Services run in an isolated session, they cannot interact with the desktop anymore. Printer drivers tend to be too chatty, doing stuff like prompting the user that there's a paper jam. Or that it is time to buy a new factory approved toner cartridge. That doesn't work well in session 0, nobody can hear it scream. Quite undiagnosable, you just can't tell why the service seized-up.
Maybe they nailed this down in 2008 and blocked it completely. No idea, you'll find the people that know this at serverfault.com
I get the same kind of error, much google work done an came on http://www.codenewsfast.com/cnf/article//permalink.art-ng1612q9464
It seems that the delphi 2007 printer unit:Printer.pas is not designed for Vista and up.
The referenced entry give the option to change the source of Printer.pas.
On vista it solved my problem.
I'm looking at porting an Interbase 6 / Delphi 7 application to embedded Firebird in Delphi 2007. One of the problems we have is getting our users (often quite an unskilled bunch, really - though I love them to bits, naturally) to unblock our applications in their firewall. Windows firewall itself is fairly straightforward but often they are running McAfee or similar (they tend to buy cheap Dells with this stuff pre-installed) and it seems that each and every variation of this stuff has a slightly different user interface. sigh
Still, I'm digressing, sorry. Straight to the point; If my Delphi app connects to an embedded Firebird database, will I still need to all/open something in the user's firewall (as I currently do when installing stuff that makes a connection to 'normal' IB6)?
And if you've read this far (thanks) - can embedded Firebird be used concurrently on a machine? Let's say we have 2 applications, both of which want to use DIFFERENT databases - could the user run both of these apps simultaneously on the same machine or is there some kind of port binding that goes on under the hood, which we'd have to work around?
I have never had a problem with firewalls or McAfee with embedded firebird. (I assume this is because embedded is not really a 'server' and does not require a port to operate)
Yes you can have two apps concurrently, just keep the executables & databases in two different folders.
Even using Firebird in a non-embeded install on the local machine we have never bumped into any firewall issues in hundreds of installations. You don't even have to use TCP/IP to connect to the database. We do use TCP/IP, but using the local shared memory protocol would avoid the issue entirely.
Firebird makes an excellent embedded or semi-embedded database. We just install it in it's normal mode and it runs in the background without any user intervention 24x7 for years at a time.
As the embedded version of Firebird doesn't use TCP/IP to talk to the database, you'll be fine on single user machines. Bear in mind that Firebird Embedded is single-user and you won't be able to get two apps talking concurrently to the same database. To do that you'd need to install the Firebird server on the machine and in the connection string use localhost:C:\Data\MyDB.FDB on both apps.
I use UIB to talk to Firebird (I wrote a persistence layer for the OPF I use using it), it's thread-safe (unlike IBX) and I've found it to be appreciably faster than IBX. There's a version that comes with JVCL and a slightly later version at http://www.progdigy.com
The situation is simple. I've created a complex Delphi application which uses several different techniques. The main application is a WIN32 module but a few parts are developed as .NET assemblies. It also communicates with a web service or retrieves data from a specific website. It keeps most of it's user-data inside an MS Access database with some additional settings inside the Registry. In-memory, all data is converted inside an XML document, which is occasionally saved to disk as backup in case the system crashes. (Thus allowing the user to recover his data.) There's also some data in XML files for read-only purposes. The application also executes other applications and wants for those to finish. All in al, it's a pretty complex application.
We don't support Citrix with this application, although a few users do use this application on a Citrix server. (Basically, it allows those users to be more mobile.) But even though we keep telling them that we don't support Citrix, those customers are trying to push us to help them with some occasional problems that they tend to have.
The main problem seems to be an occasional random exception that seems to pop up on Citrix systems. Never at the same location and often it looks related to some memory problems. We've p[lenty of error reports already and there are just too many different errors. So I know solving all those will be complex.
So I would like to go a bit more generic and just want to know about the possible issues a Delphi (2007) can have when it's run on a Citrix system. Especially when this application is not designed to be Citrix-aware in any way. We don't want to support Citrix officially but it would be nice if we can help those customers. Not that they're going to pay us more, but still...
So does anyone know some common issues a Delphi application can have on a Citrix system?
Does anyone know about common issues with Citrix in general?
Is there some Silver Bullet or Golden Hammer solution somewhere for Citrix problems?
Btw. My knowledge about Citrix is limited to this Wikipedia entry and this website... And a bit I've Googled...
There were some issues in the past with Published Delphi Applications on Citrix having no icon in the taskbar. I think this was resolved by the MainFormOnTaskbar (available in D2007 and higher). Apart from that there's not much difference between Terminal Server and Citrix (from the Application's perspective), the most important things you need to account for are:
Users are NEVER administrator on a Terminal or Citrix Server, so they no rights in the Local Machine part of the registry, the C drive, Program Folder and so on.
It must be possible for multiple users on the same system to start your application concurrently.
Certain folders such as the Windows folder are redirected to prevent possible application issues, this is also means that API's like GetWindowsFolder do not return the real windows folder but the redirected one. Note that this behaviour can be disabled by setting a particular flag in the PE header (see delphi-and-terminal-server-aware).
Sometimes multiple servers are used in a farm which means your application can run on any of these servers, the user is redirected to the least busy server at login (load balancing). Thefore do not use any local database to store things.
If you use an external database or middleware or application server note that multiple users will connect with the same computername and ip address (certain Citrix versions can use Virtual IP addresses to address this).
Many of our customers use our Delphi applications on Citrix. Generally speaking, it works fine. We had printing problems with older versions of Delphi, but this was fixed in a more recent version of Delphi (certainly more recent than Delphi 2007). However, because you are now running under terminal services, there are certain things which will not work, with or without Citrix. For example, you cannot make a local connection to older versions of InterBase, which use a named pipe without the GLOBAL modifier. Using DoubleBuffered would also be a really bad idea. And so on. My suggestion is to look for advice concerning Win32 apps and Terminal Services, rather than looking for advice on Delphi and Citrix in particular. The one issue which is particular to Citrix that I'm aware of is that you can't count on having a C drive available. Hopefully you haven't hard-coded any drive letters into your code, but if you have you can get in trouble.
Generally speaking, your application needs to be compatible with MS Terminal Services in order to work with XenApp. My understanding is that .NET applications are Terminal Services-compatible, and so by extension should also work in a Citrix environment. Obviously, as you're suffering some problems, it's not quite that simple, however.
There's a testing and verification kit available from http://community.citrix.com/citrixready that you may find helpful. I would imagine the Test Kit and Virtual Lab tools will be of most use to you. The kit is free to use, but requires sign-up.
Security can be an issue. If sensitive folders are not "sandboxed" (See Remko's discussion about redirection), the user can break out of your app and run things that they shouldn't. You should probe your app to see what happens when they "shell out" of your app. Common attack points are CHM Help, any content that uses IE to display HTML, and File Open/Save dialogs.
ex: If you show .chm help, the user can right-click within a help topic, View Source. That typically opens Notepad. From there, they can navigate the directory structure. If they are not properly contained, they may be able to do some mischief.
ex: If they normally don't have a way to run Internet Explorer, and your app has a clickable URL in the about box or a "visit our web site" in the Help menu, voila! they have access to the web browser. If unrestrained, they can open a command shell by navigating to the windows directory.