How to use QuickFix to read secdef.dat file - c#

I'm trying to read the static securities definition file from the CME, located at:
ftp://ftp.cmegroup.com/fix/Production/secdef.dat.gz
Since they seem to be standard fix messages, I thought I could use QuickFix to help me read them into C# rather than parsing the file myself. I created a test app that basically does what I want, but I'm having 2 issues:
1) I'm getting a QuickFix exception "Invalid message: Header fields out of order" when forming the message from the string. If I set the "validate" boolean to false, this message disappears and the constructor succeeds, but may be an indicator for the next issue.
2) Upon calling p.Crack, I'm getting the QuickFix exception "QuickFix.UnsupportedMessageType", but there doesn't seem to be any indication of what the message type is that is supposedly unsupported.
Anyway, maybe QuickFix wasn't intended to be used in this way, but any ideas on how to get this to work?
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using QuickFix;
namespace TestQuickFix
{
class Program : QuickFix.MessageCracker
{
static void Main(string[] args)
{
int count = 0;
string line;
Program p = new Program();
StreamReader file = new StreamReader(#"C:\secdef.dat");
while (((line = file.ReadLine()) != null && count < 10))
{
// ISSUE #1 REQUIRES false 2ND ARG WHEN CREATING THE MESSAGE
Message m = new Message(line, false);
// ISSUE #2 Exception of type 'QuickFix.UnsupportedMessageType' was thrown.
p.Crack(m, new SessionID("beginString", "senderCompID", "targetCompID"));
}
file.Close();
}
public void OnMessage(QuickFix.FIX50.SecurityDefinition secDef, SessionID sessionID)
{
Console.WriteLine(secDef.ToString());
}
}
}

The messages seems to be in FIX50sp2 format, supported by QuickFIX. (Please take a look at the tag 1128=9).
http://www.onixs.biz/fix-dictionary/5.0.SP2/tagNum_1128.html
BUT every single message seems to be not-well formatted. In the header are missed tag 8 (should be the BeginString), and also the tag 56 (TargetCompID), that are mandatory.
Therefore in order to load a single line in a message you must put the "false" parameter to avoid validation.
I suppose the second error is related to the not-well formatted messages.

After emailing the QuickFix listserv with this question, I was able to get enough information to get this to work. Although each line still seems to be malformed for some reason, if I keep validation off, I can get the parser to do exactly what I need it to with the following simplified code:
using System;
using System.IO;
using QuickFix;
using QuickFix.DataDictionary;
namespace TestQuickFix
{
class Program
{
private const int MAX_LINES = 10;
static void Main(string[] args)
{
DataDictionary dd = new QuickFix.DataDictionary.DataDictionary("fix\\FIX50SP2.xml");
StreamReader file = new StreamReader(#"C:\secdef.dat");
int count = 0; string line;
while (((line = file.ReadLine()) != null && count++ < MAX_LINES))
{
QuickFix.FIX50.SecurityDefinition secDef = new QuickFix.FIX50.SecurityDefinition();
secDef.FromString(line, false, dd, dd);
Console.WriteLine(secDef.SecurityDesc);
}
file.Close();
}
}
}

Related

inserting into index location of a text file if a string does exist inside the line, if the string doesn't exist, still write line as it was

The program is supposed to look for a string in a line, and if it finds the string, it will make the inserts after meeting the condition inside the textfile. Currently, when I run this program it is now simply giving me a blank console. Previously, I had it just reading all the lines properly and could make inserts only if I remove them first but it messed the indexing up and ultimately did not give me the result I wanted. The logic is fairly straightforward, if you see any problems please share your thoughts. Please and thanks. I am very confused why this is having problems and not working.
using System.IO;
using System.Globalization;
using System.Diagnostics;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
namespace Masker
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine();
string path = #"\file1.txt";
ReadLines(path)
}
public static void ReadLines(string path)
{
int counter = 0;
var text = new StringBuilder();
foreach (string s in File.ReadAllLines(path))
{
counter += 1;
if (s.Contains("000INDEX"))
{
text.AppendLine(s.Insert(60, "#"));
}
else if (s.Contains("001PRTBNR"))
{
text.AppendLine(s.Insert(60, "#").Insert(119,"#").Insert(120,"#").Insert(121, "#"));
};
text.AppendLine(s);
//Console.Write(text.ToString());
}
Console.Write(text.ToString());
}
}
}
The last two blocks of your if/else statement will never be executed.
If the execution reaches the third check
else if (s.Contains("000INDEX"))
that will always be true. Because if it wasn't, then the first check
if (!s.Contains("000INDEX"))
would have already been true.
But the biggest problem is that if the line contains "000INDEX", your while loop becomes and infinite loop. You never leave it. That is probably the reason why you end up with a blank console.

Title: C# File.Exist returning false when file can be read from/written to

Development Environment: .Net Framework 4.7.2 using VS 2022 on Win 10 Pro x64
Preface: I've reviewed the two similar questions I found at SO; the first deals with permissions and the second with restrictions on using the root directory. Neither contained info that enabled me to resolve my issue.
I'm working on a C# winforms app which uses a SQLite database. I recently discovered "PRAGMA integrity_check" will create an empty DB and return “ok” if the target DB file is missing so I need to ensure the file’s not gone missing before executing the PRAGMA. My simple solution is to wrap integrity_check in an IF (File.Exist) ELSE but the Exist method is returning ”false”.
In MSDN documentation there 7 stated reasons why a false might be returned in addition to the file actually not existing (listed to avoid the need to follow a link):
path is null
path is invalid
path exceeds maximum length (260)
path is a zero-length string
path has invalid characters
storage media is failing/missing
caller has insufficient permissions to read the specified file
My operating assumption is none of those are the root cause since I can read from and write to the DB programmatically in the app.
Code building the path:
namespace BURS_Library
{
public class MISC
{
public const string DBName = "BURS.db";
}
}
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
namespace BURS_Library
{
public class BURS_Path
{
public static string AppData()
{
string userAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
userAppDataDir = userAppDataDir.Replace("Roaming", "LocalLow");
if ( ! Directory.Exists(Path.Combine(userAppDataDir, "BURS_Data_tst")))
{
// display error MessageBox
Environment.Exit(1);
}
return Path.Combine(userAppDataDir, "BURS_Data_tst");
}
public static string DB()
{
return Path.Combine(AppData(), MISC.DBName);
}
{
}
Resultant path: C:\Users\Art\AppData\LocalLow\BURS_Data_tst\BURS.db
Code with File.Exist
using _Library;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace BURS_UI
{
public static class Program
{
[STAThread]
public static void Main(string[] tsArgs)
{
if (File.Exists(BURS_Path.DB()))
{
// perform db Integrity Check
}
else
{
// display error MessageBox
Environment.Exit(2);
}
BURS_Connections.SetConnection(BURS_Path.DB());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Discover());
}
}
}
If my operating assumption is valid why is File.Exist returning false?
Thank you for your time & expertise.
Following #BentTranberg's suggestion a test was run using the following code (in case its useful to somebody):
if (Directory.Exists(#"C:\Users"))
Save2Log(#"FOUND: C:\Users", true);
if (Directory.Exists(#"C:\Users\Art"))
Save2Log(#"FOUND: C:\Users\Art", true);
if (Directory.Exists(#"C:\Users\Art\AppData"))
Save2Log(#"FOUND: C:\Users\Art\AppData", true);
if (Directory.Exists(#"C:\Users\Art\AppData\LocalLow"))
Save2Log(#"FOUND: C:\Users\Art\AppData\LocalLow", true);
if (Directory.Exists(#"C:\Users\Art\AppData\LocalLow\BURS_Data_tst"))
Save2Log(#"FOUND: C:\Users\Art\AppData\LocalLow\BURS_Data_tst", true);
if (File.Exists(#"C:\Users\Art\AppData\LocalLow\BURS_Data_tst\BURS.db"))
Save2Log(#"FOUND: C:\Users\Art\AppData\LocalLow\BURS_Data_tst\BURS.db", true);
Save2Log($"METHOD: {BURS_Path.DB()}", true);
Which produced the following result:
FOUND: C:\Users
FOUND: C:\Users\Art
FOUND: C:\Users\Art\AppData
FOUND: C:\Users\Art\AppData\LocalLow
FOUND: C:\Users\Art\AppData\LocalLow\BURS_Data_tst
FOUND: C:\Users\Art\AppData\LocalLow\BURS_Data_tst\BURS.db
METHOD: C:\Users\Art\AppData\LocalLow\BURS_Data_tst\BURS.db
Next I reran my original code which surprisingly now worked as expected. To validate that result I ran more test:
int existFail = 0;
for (int i = 0; i < 10000; i++)
{
if ( ! File.Exists(BURS_Path.DB())) existFail++;
}
Save2Log($"number of exist fail in 10,000 = {existFail}", true);
I did that 5 times and in 50,000 iterations there were zero incorrect returns. At this point the error has not been reproduced.
My computer was shut down over night which may have impacted the findings. I will rerun this each morning for the next 3 days and post the results as an edit.

Revit IExternal Application Error- doesn't seems to run at all

Should we have something with the External application to properly register the event?
I also tried putting two breakpoints one inside the start module and other inside the Export module.
the first responded and waited for me to continue and the next didn't respond(hope did not run the line)
Also,I had manually tried coping the addin file to the addin location to avoid any post build event error but still doesnt seem to work.
could you tell me what I am I doing wrong here.
Here is the code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.DB.Events;
using System.IO;
namespace UserDataSheet
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class UserDataSheetclass : IExternalApplication
{
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
public Result OnStartup(UIControlledApplication application)
{
try
{
// Register event.
application.ControlledApplication.DocumentOpened += new EventHandler<Autodesk.Revit.DB.Events.DocumentOpenedEventArgs>(ExportLog);
return Result.Succeeded;
}
catch (Exception)
{
return Result.Failed;
}
}
public void ExportLog(object sender, DocumentOpenedEventArgs args)
{
var doc = sender as Document;
var isFamilyDoc = doc.IsFamilyDocument;
// variables to use
string RevitUserName = "";
DateTime OpenTime = new DateTime();
string localUserName = "";
string filename = "";
string filepath = "";
string content = "";
if (isFamilyDoc == false)
{
var IsloggedIn = Autodesk.Revit.ApplicationServices.Application.IsLoggedIn;
if (IsloggedIn == true )//&& doc.IsModelInCloud == true)
{
// use variables
filepath = doc.PathName;
filename = doc.Title;
RevitUserName = doc.Application.Username;
OpenTime = DateTime.Now;
localUserName = System.Environment.MachineName;
}
content = string.Format("Date and time : {0} \n Revit UserName : {1} \n Local PC UserName : {2} \n FileName : {3} \n FilePath : {4} "
, OpenTime.ToString(), RevitUserName, localUserName, filename, filepath);
TaskDialog.Show("Model Open Writer info", "user and file details : \n " + content);
}
var writefilepath = Path.GetTempPath();
var Writefile = writefilepath + "//records.txt";
FileStream fs = new FileStream(Writefile, FileMode.Append);
StreamWriter writer = new StreamWriter(fs);
writer.Write(content);
writer.Close();
File.OpenRead(Writefile);
}
}
}
First of all, you can completely remove the TransactionMode and RegenerationOption. The latter is completely obsolete and does nothing at all anywhere whatsoever. The former is only useful when declaring an external command. It is useless and ignored in the context of an external application.
Secondly, to address your question: you can set a breakpoint in the beginning of OnStartup. If the breakpoint is not hit, your add-in is not being loaded at all. Probably something is wrong with your add-in registration, e.g., in the add-in manifest *.addin file.
Go back to square one, i.e., work through the getting started material and the developer guide instructions on registering and loading a Revit add-in.
If the breakpoint in OnStartup is hit, then your add-in is loading correctly, which means that the add-in manifest *addin file is OK. So, you do not need to worry about that. The VisibilityMode tag is not used for external applications, by the way.
Thanks, Jeremy It worked
Firstly I apologies for adding this as answer( I don't know how to add codes in comment)
It worked when I deleted my Addin file and recreated it may be I had made some mistake in it.
meanwhile I have copied the following code from examples and used it,honestly I did't understand this line of the code.
"public void ExportLog(object sender, DocumentOpenedEventArgs args)"
can you point to a right source that explains this part. I have three questions here :
what object type is sender and args are they of type application?
How do I add a 3rd parameter to this method say I want the user to input a string to name the file the data is copied to.
Can I do this
var newEvent = new EventHandler<Autodesk.Revit.DB.Events.DocumentOpenedEventArgs>(ExportLog);
instead of
application.ControlledApplication.DocumentOpened += new EventHandler<Autodesk.Revit.DB.Events.DocumentOpenedEventArgs>(ExportLog);
why does all example use += is this to register the event every time a new instance of Revit is opened?
Thanks for your help.
You can see the class of sender yourself by setting a breakpoint at the beginning of ExportLog and looking in the debugger.
No, you cannot modify the signature of the event handler. It is predetermined by the Revit API.
Yes.
It sounds to me as if you might save some time and effort for yourself by learning a bit more about the basics of C# and .NET programming in general before continuing to tackle this task.

how to get the current item being written by an XMLWriter

I have a series of settings being written out by an XMLWriter in C#. Here's some code:
try
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
using (writer = XmlWriter.Create("PCOB2NET.XML", settings))
{
// Write XML data.
writer.WriteStartElement("PowerCOBOL2NETMigration");
writer.WriteStartElement("config");
writer.WriteElementString("VSVersion", selectedVSver);
writer.WriteElementString("path2SelectedVSVerProjects", path2SelectedVSVerProjects);
if (path2VSoverridden)
writer.WriteElementString("path2VSoverridden", "true");
else
writer.WriteElementString("path2VSoverridden", "false");
writer.WriteElementString("path2PRCfile", path2PRCfile);
writer.WriteElementString("path2XMLfile", path2XMLfile);
writer.WriteElementString("path2VSProject", path2VSProject);
... and so on.
My problem is that if there is an Exception (like a null field, for instance) it goes to the catch block and reports the exception as we would expect, but I don't know WHICH field it was writing at the time.
My question:
Is there any way I can get the current string being written, when an Exception occurs? I searched the web without success and I looked through every property and method of XMLWriter but I can't find a way to do it. Is there maybe a certain type of Exception trap that will give it to me? Any help or thoughts appreciated.
Try xml linq which is a new Net Library for reading and writing xml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string selectedVSver = "";
string path2SelectedVSVerProjects = "";
Boolean path2VSoverridden = true;
string path2PRCfile = "";
string path2XMLfile = "";
string path2VSProject = "";
XDocument doc = new XDocument();
XElement powerCOBOL2NETMigration = new XElement("PowerCOBOL2NETMigration", new object[] {
new XElement("config", new object[] {
new XElement("VSVersion", selectedVSver),
new XElement("path2SelectedVSVerProjects", path2SelectedVSVerProjects),
new XElement("path2VSoverridden", path2VSoverridden),
new XElement("path2PRCfile", path2PRCfile),
new XElement("path2XMLfile", path2XMLfile),
new XElement("path2VSProject", path2VSProject)
})
});
doc.Add(powerCOBOL2NETMigration);
doc.Save(FILENAME);
}
}
}
The simplest approach is to wrap small helper methods around XmlWriter.WriteStartElement etc. and catch your exceptions there.
It turns out I was looking for a solution at the wrong end of the problem. Instead of puzzling over XMLWriter, what I SHOULD have done was investigate the EXCEPTION.
(I did do this but only for the Exception Class, I needed to look further.) The problem looked like it could be easily solved by nesting some exception catch blocks, so:
catch (ArgumentNullException anEx)
{
// retrieve the offending field name from anEX...
badField = anEx.ParamName;
...
}
catch (ArgumentException aEx)
{
// retrieve the offending field name from aEX...
badField = aEx.ParamName;
...
}
catch (Exception ex)
{
...
However, I was misled by the "ParamName" which does not mean what I thought it did... This always returned null and I was no better off.
After spending a number of hours reading everything I could about Exception handling in C#, I am much better informed, but no wiser. I can't find a solution with the Framework so I have little recourse but to push all the settings through a method which will do the actual write and trap any exception at that moment, with the offending field available as it will have been passed into that method.
I think this inelegant, but I can't spend more time on it. Many thanks to all who responded and those who thought about responding... :-) I'll leave this open in case somebody really has a solution, for a few days.

C# Windows Service - this keyword error

I have the following code which works fine when I use it within a Windows Forms application, however the application I'm writing needs to run as a Windows service, and when I moved my code into the Windows Service template in Visual Studio 2015 Community Edition, I get the following error.
Cannot implicitly convert type "MyWindowsService.Main" to "System.ComponentModel.ISynchronizeVoke". An explicit conversion exists (are you missing a cast?)
Could anyone shed some light on why I am getting this error, and what I need to do to resolve it?
The code which throws the error is the line below, and it is located within the OnStart method of my main class (named Main.cs). The code is used to create an instance of the DataSubscriber class (AdvancedHMI library).
dataSubscribers[dataSubscriberIndex].SynchronizingObject = this;
It has to have something to do with the fact that the code is in a Windows service template, because using this works perfectly in my forms application running the same code.
UPDATE
Correction, I've attempted to cast this to the required type, and now get the following error on run.
Additional information: Unable to cast object of type 'MyWindowsService.Main' to type 'System.ComponentModel.ISynchronizeInvoke'.
Code:
dataSubscribers[dataSubscriberIndex].SynchronizingObject = (System.ComponentModel.ISynchronizeInvoke)this;
UPDATE
I've included the entire contents of the Main.cs file from my Windows Service application.
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using AdvancedHMIDrivers;
using AdvancedHMIControls;
using MfgControl.AdvancedHMI.Drivers;
using MfgControl.AdvancedHMI.Controls;
using System.Collections.ObjectModel;
namespace PLCHistoricDataHarvester {
public partial class Main : ServiceBase {
private EthernetIPforCLXCom commObject = new EthernetIPforCLXCom();
private globals globals = new globals();
private Dictionary<String, String> operationLines = new Dictionary<String, String>();
private Dictionary<String, String> tags = new Dictionary<String, String>();
private Collection<DataSubscriber> dataSubscribers = new Collection<DataSubscriber>();
private int harvesterQueueCount = 0;
private string harvesterInsertValues = String.Empty;
public Main() {
InitializeComponent();
}
protected override void OnStart(string[] args) {
// Initialize our harvester program
initializeHarvester();
Console.WriteLine("The program has started");
}
protected override void OnStop() {
// Call code when the service is stopped
Console.WriteLine("Program has stopped");
Console.ReadLine();
}
public void initializeHarvester() {
// First, we connect to the database using our global connection object
globals.dbConn.DatabaseName = "operations";
if (!globals.dbConn.IsConnect()) {
// TODO: Unable to connect to database. What do we do?
}
// Second, we connect to the database and pull data from the settings table
globals.initializeSettingsMain();
// Set IP address of PLC
commObject.IPAddress = globals.getSettingsMain("Processor_IP");
// Pull distinct count of our parent tags (Machines ex: Line 1, etc)
operationLines = globals.getOperationLines();
// If we have at least 1 operation line defined...we continue
if (operationLines.Keys.Count > 0) {
//Now we loop over the operation lines, and pull back the data points
int dataSubscriberIndex = 0;
foreach (KeyValuePair<String, String> lines in operationLines) {
int line_id = int.Parse(lines.Key);
string name = lines.Value;
tags = globals.getTags(line_id);
// If we have at least 1 tag for this operation line, we continue...
if (tags.Keys.Count > 0 && tags["tags"].ToString().IndexOf(",") != -1) {
// Create our dataSubscriber object
dataSubscribers.Add(new DataSubscriber());
dataSubscribers[dataSubscriberIndex].SynchronizingObject = (ISynchronizeInvoke)this;
dataSubscribers[dataSubscriberIndex].CommComponent = commObject;
dataSubscribers[dataSubscriberIndex].PollRate = 1000;
dataSubscribers[dataSubscriberIndex].PLCAddressValue = tags["tags"];
dataSubscribers[dataSubscriberIndex].DataChanged += new EventHandler<MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs>(subscribeCallback);
// Increment our dataSubscriberIndex
dataSubscriberIndex++;
}
}
}
}
private void subscribeCallback(object sender, MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs e) {
// code removed as it is irrelevant
}
}
}
The error message says this:
An explicit conversion exists (are you missing a cast?)
So add a cast like this:
dataSubscribers[dataSubscriberIndex].SynchronizingObject = (ISynchronizeInvoke)this;
^^^^^^^^^^^^^^^^^^^^
//Add this
If you've got a console app, the easiest way to convert it to a windows service is by using Topshelf, a nuget package which lets you run in either console mode or nt service mode.
Here's the quickstart guide.
We use it to write services all the time and it helps you avoid this kind of fragile shenanigans.

Categories

Resources