Jump to content

Mark Williams

Members
  • Content Count

    274
  • Joined

  • Last visited

Everything posted by Mark Williams

  1. Mark Williams

    Reset Printer

    I'm using PDevMode to change printer settings. Printer.GetPrinter(Device, Driver, Port, hDMode); if (hDMode<>0) then begin pDMode := GlobalLock(hDMode); if pDMode <> nil then begin with pdMode^ do begin dmFields := DM_DEFAULTSOURCE; dmDefaultSource := ToBin; dmFields := dmFields or DM_PAPERSIZE; dmPaperSize := DMPAPER_A4; // Letter, 8-1/2 by 11 inches dmFields := dmFields or DM_PRINTQUALITY or DM_YRESOLUTION; if BestQuality then begin dmPrintQuality := LoWord(High_Quality); dmYResolution:=HiWord(High_Quality); end else begin dmPrintQuality := LoWord(Med_Quality); dmYResolution:=HiWord(Med_Quality); end; dmFields := dmFields or DM_DUPLEX; dmDuplex := DMDUP_VERTICAL; dmFields := dmFields or DM_COPIES; dmCopies := Copies; end; GlobalunLock(hDMode); This works fine if you only want to print one document or many documents with the exact same settings. But I am printing various documents in a loop and different document get printed at different qualities, with different nos of copies and to different bins. The problem is that once set the settings are saved and calling the above function does not change the settings for the new document. One code example I found suggests the following: Printer.GetPrinter(Device, Driver, Port, hDevmode); {force reset of devmode} Printer.SetPrinter(Device, Driver, Port, 0); Printer.GetPrinter(Device, Driver, Port, hDevmode); However, I then get a "Printer selected is not valid" error immediately I call Printer.BeginDoc. I'm not sure what else to do. Have tried Printer.Refresh which is no help. I've come up with a clunky temporary solution which is to change the PrinterIndex immediately after Printer.EndDoc and then set it back to the desired printer. It works in clearing the settings, but I'm sure it is not the best way to do this!
  2. I create/open a TFileStream in non-exclusive mode with the following code: if not FileExists(FileName) then //have to create it first and close it otherwise the share mode does not work!! begin Result := TFileStream.Create(FileName, fmCreate, fmShareExclusive); Result.free; end; Result := TFileStream.Create(FileName, fmOpenReadWrite, fmShareDenyNone); By my reckoning I should be able to open the file in read only mode: fs := TFileStream.Create(FileName, fmOpenRead, fmShareDenyNone); But it throws up an EFOpenError ie file in use by another process. I have looked online and found old posts which suggest that the share modes do not function for fmCreate mode ie always created exclusively and that is why I create, then close and then open. There was a post around 2010 which suggested the issue had been reported to Embarcadero and that it had been closed as fixed. Couldnt find anything much later than this. However as you can see , my problem is not with fmCreate, it is with fmOpenReadWrite. is there a bug with TFileStream or am I handling this in the wrong way? If there is a bug, does anyone know a work around?
  3. Mark Williams

    TFileStream fmShare modes

    Thanks. I didn't read the help file properly!
  4. Within an ISAPI dll I create a pooled connection: Params := TStringList.Create; try Params.Add('DriverID=PG'); Params.Add('User_Name=*****'); Params.Add('UnknownFormat=BYTEA'); Params.Add('Pooled=True'); FDManager := TFDManager.Create(Nil); with FDManager do begin ResourceOptions.SilentMode:=True; ResourceOptions.AutoReconnect:=True; AddConnectionDef(FD_POOLED_CONN, 'PG', Params); Active := true; end; finally Params.Free; end; The server is left as the default ie localhost. The server is a machine on my local network (ip 192.168.0.12). It is also a web server with an external id (say 52.132.222.67) It hosts a number of databases and to change the referenced database I call the following: var Def : IFDStanConnectionDef; begin try Def : =FDManager.ConnectionDefs.FindConnectionDef(FD_POOLED_CONN); if Def.Params.Values['Database'] <> dbName then Def.Params.Values['Database'] := dbName; if assigned(Query) then Query.Close; if assigned(Query) then Query.ConnectionName := FD_POOLED_CONN; except on E: Exception do AddToLog('Error SetDatabase: '+e.Message, leMajorError); end; If I call the dll via the external ip address then my function to change the referenced database works just fine. If I use local ip it fails with the following error: Why do I get this error if I use the local ip, but not if I call the dll with the external ip and is there any way around it?
  5. Mark Williams

    Problems changing database with pooled connection

    It has taken me an age to get back around to this, but I have finally uncovered the problem. It was not with FireDAC but my code.
  6. Using a Postgre database. If I run an insert query with the following code: # With FDQuery Do begin SQL.Text:='INSERT INTO temptab(email, name) ' +'VALUES (''email1'', ''name1''), ' +'(''email2'', ''name2'') ' +'returning id'; Open; end; The query returns two records containing the id for the newly inserted records. However, for larger inserts I want to use Array DML, but I also want to be get the returned data. Example code: With FDQuery Do begin SQL.Text:='INSERT INTO temptab(email, name) ' +'VALUES (:EMAIL, :NAME) returning id'; Params.BindMode:=pbByNumber; Params[0].DataType:=ftString; Params[0].DataType:=ftString; Params.ArraySize:=2; Params[0].AsStrings[0]:='Email1'; Params[1].AsStrings[0]:='Name1'; Params[0].AsStrings[1]:='Email2'; Params[1].AsStrings[1]:='Name2'; Execute(params.ArraySize); end; This returns no records. Not unsurprisingly as I am using the Execute command. If I change the Execute command to Open, it inserts just the first record from the array and returns the id for that new record. The Open function does not allow you to specify the ArraySize. I have tried to find some other procedure/property that will achieve this, but have drawn a blank. Does anyone know whether it is possible to return data from all inserted records using Array DML? If it is not possible can anyone suggest an efficient way for returning the inserted data? There seems to be two alternatives to me, neither of which is particularly attractive: Run a query to return all records that match the email and name and then extract the relevant ids. In large tables this would doubtless result in a significant overhead. Add an integer field to the table eg "temp_id". When inserting the data set this field to a unique value for all records inserted for the DML Array transaction and then retrieve the newly inserted data using "temp_id". Again, this doesn't appear to me to be an attractive solution. @Dmitry Arefiev If this is not currently possible with Array DML would you please consider including it for later versions?
  7. Mark Williams

    FireDAC Array DML returning values from inserted records

    Good to know thanks, but would be a bit of a major shift for me from FireDac to Zeos
  8. Mark Williams

    FireDAC Array DML returning values from inserted records

    Sorry, I though I had posted the SO link. It is FireDAC Array DML and Returning clauses - Stack Overflow
  9. Mark Williams

    FireDAC Array DML returning values from inserted records

    Sorry I misunderstood. What is SA?
  10. Mark Williams

    Embarcadero.com

    It seems to me that the Embarcadero web site(s) are a complete mess. I manage to find a resource one day and it's gone the next. As examples, I was advised to use https://idera.secure.force.com/CG/ to get to Quality Portal. I managed to get in to the Portal earlier this year and make a feature request, I returned to view it today and when I click on the Quality Portal link, it wants my username and password again, but not the same one. It wants the username and password for the Registered Product Page. Incidentally, this page also has a link for Registered Product, which takes a lifetime to load and is out of date! I use this link https://members.embarcadero.com/Login.aspx?returnurl=http%3a%2f%2fcc.embarcadero.com%2fmyreg to access Registered Product, which works. However, the username and password I use to access Registered Product does not work for Quality Portal because it won't accept an email as a username it wants your "real" username and I have no idea what that is. Tried a couple of options and none of them work. Is it just me or is this a complete mess? And is it beyond the wit of man to put links for all resources we need on one consistent web page with one username and password?
  11. Mark Williams

    Embarcadero.com

    Well I've not seen that site before today! Yes, it is annoying and pointless. I have made a note of the site for future reference. Of course, by the time I get around to looking at it, it will probably have moved somewhere else with n forwarding link.
  12. Mark Williams

    FireDAC Array DML returning values from inserted records

    http://FireDAC Array DML and Returning clauses - Stack Overflow
  13. Mark Williams

    Embarcadero.com

    I'll probably be dead by then!
  14. Mark Williams

    Embarcadero.com

    It's the same page as I get to via https://idera.secure.force.com/CG/. Still doesn't accept my credentials. But why all the different domains and different log ins required? It doesn't make any sense to me.
  15. Mark Williams

    FireDAC Array DML returning values from inserted records

    It's a bit frustrating and I have also posted on Stackoverflow, but nothing has come back. I have logged a feature request at Quality Portal. I would give you the link, but for some reason my log in details no longer work. If you could comment on that to lend support that would be great. That's assuming you know how to get in to it. I tried today, but my details no longer work!
  16. Mark Williams

    Email Tampering

    Apologies in advance as this isn't really an Indy question, but not sure where else to ask it. I have written functions to batch parse information from emails. I would also like to be able to flag up possible suspicious activity such as date tampering. One of the things I am looking at is the difference between the date time in the Date header and the date time of the first Received header. If there is a significant difference between the two then I will flag the item as suspicious. However, I am not sure what would be a significant time difference to warrant flagging. Anything more than a few minutes strikes me as too long and my initial view is to opt for about 30 minutes. Views as to whether that sounds sensible would be appreciated.
  17. Mark Williams

    Email Tampering

    It's not for filtering purposes. It is for a system that will store documents/resources including emails. When users are examining email threads I simply want to highlight that there may be something suspicious about one of the emails in the thread not exclude it from the thread. So if in 99% of the cases a Date header later than the Received header is suspicious that works for me. Perhaps my original question was unclear and answers have been given on the basis that I was looking to exclude such emails. Far from it, I am looking to highlight them. With that in mind perhaps I can ask my original question again. What sort of time difference by which the Date header is greater than the first Received header would you consider suspicious? I have opted for 30 minutes, but presumably there is an argument to say any difference is suspicious as I would expect most users' computers' and servers' clocks are automatically set.
  18. Mark Williams

    Email Tampering

    Thanks for the responses. Hadn't though of delayed sends. What I'm trying to catch is someone setting the date on their computer to a date in the past and sending an email to make it appear as though it was sent earlier than it in fact was. I haven't come across this, but surely if the Date header is later than the Received header someone's clock someone is showing the wrong time?
  19. Mark Williams

    FireDac PostgreSQL and TBatchMove

    Has anyone been able to get the BatchMove component to work correctly with PostgreSQL in AppendUpdate mode where there is an auto inc key field? My BatchMove component creation code is below. In addition, either the FDConnectionPG ExtendedMetaData param is set to true or the FDQueryPG updateOptions.AutoIncFields is set. Either way produces the same result, although I understand there is an efficiency hit with use of ExtendedMetaData. The problem is that whilst new rows get added to the table and my auto inc key field value gets set, it is running backwards ie -1, -2, -3 etc. Am I missing something or is this a bug? var FBatchMove: TFDBatchMove; FReader: TFDBatchMoveDataSetReader; FWriter: TFDBatchMoveSQLWriter; F:TField; begin FBatchMove := TFDBatchMove.Create(nil); FReader := TFDBatchMoveDataSetReader.Create(FBatchMove); FWriter := TFDBatchMoveSQLWriter.Create(FBatchMove); try FReader.DataSet:=FDQueryPG; FWriter.Connection:=FDConnectionPG; FWriter.TableName:='dummy'; FBatchMove.CommitCount:=1000; FBatchMove.Mode := dmAppendUpdate; FBatchMove.options:=FBatchmove.Options+[poIdentityInsert]; FBatchMove.Execute; finally FWriter.Free; FReader.Free; FBatchMove.Free; end;
  20. FireDAC Array DML doesn't seem to be usable in any practical sense with Returning clauses FireDAC Array DML returning values from inserted records. That being so, I am trying to work out whether there is an efficient way I can retrieve data from inserted records using Array DML. The following seems a possibility and is lightening fast, but I am concerned that I may be missing something critical: Insert required no of new records using Array DML within a StartTransaction/Commit section. Check the number of affected rows to make sure that all required records have been inserted. If not, then rollback. Obtain the last insert id for the target table for the current session. Work backwards through the array of inserted data in my app and assign the id by decrementing the last id. My initial testing suggests that this works. But it depends on the following assumptions being correct (which I believe they are): The RowsAffected property of TFDQuery is wholly reliable. My DB (in this case PostgreSQL) will always reliably return the correct last insert id for my table in my current session. My DB will insert all my records in the same order as they are added to the TFDQuery params list. My DB will insert the records in an unbroken sequence of IDs. So my questions Are my assumptions sound? Am I missing something else?
  21. Mark Williams

    Returning ids for records inserted with Array DML

    OK. I'm a little confused, but thanks for the help.
  22. Mark Williams

    Returning ids for records inserted with Array DML

    OK. As mentioned in original post if RowsAffected is less than the number of inserted rows I would expect I rollback the transaction (and handle it as an error). It is only if the RowsAffected = the number of inserted rows expected that I would use the approach in my original post. Taking that into account, do you think it is safe to do so?
  23. Mark Williams

    Returning ids for records inserted with Array DML

    But for an insert procedure would not the number of successful executions be the number of new rows inserted? That certainly seems to to be the case from the testing I have carried out so far.
  24. Mark Williams

    Returning ids for records inserted with Array DML

    Thanks for the suggestions. Just to clarify By that, do you mean that you consider the method I proposed in my original post would be reliable? If so, that would be the quickest and easiest route to go.
  25. Mark Williams

    IsElevated

    Is there a simple way to check if my app is running elevated? I can see a few oldish posts on this on Google, but nothing recent. I was just wondering if newer Delphi has introduced a simple function for it, although I couldn't find anything in help or likely units. Or perhaps there is a new Windows API procedure?
×