I am trying to fetch events from the TaiPan Realtime COM server. I am able to extract other data from there. Accessing keys is working correctly.
But when i try to fetch events, the function is not fired somehow. Hopefully this is a small mistake. For better readability i made a small test code, which is easyer to read for you. After adding those ids to the Stream the Visual Basic debugger is working and it show cpu activity for com_test.
So i gues events are there but i made mistake in eventhandling somehow.
Thanks for help.
using System;
using System.Collections.Generic;
using TaiPanRTLib;
namespace com_test
{
class Program
{
static void Main(string[] args)
{
var handle = new handle();
handle.start();
Console.ReadLine();
}
}
public class handle
{
public int counter;
// this is a list contains the internal numbers of the taipan Software
public static List<int> numbercodes = new List<int>(new int[] { 78379670, 78379685, 78379692, 78379669, 78379729, 78379672, 78379674, 78379698, 78379682, 78379681, 78379704, 78379689, 78379694, 78379673, 78379697, 78379687, 78379702, 78379690, 78379668, 78379671, 78379715, 78379666, 78379706, 78379727, 78379679, 127289939, 78379677, 78379693, 78379676, 78379678, 78379680, 78379688, 78379726, 78379686, 78379696, 78379675, 78379667, 78379703, 78379691, 78379684, 78379700, 78379699, 78379705, 78379695, 78379701, 78379664, 78379716, 78379982, 78379665, 78379707, 78379728, 78379717, 78379719, 7837971 });
void TPRTDataStream_Bezahlt(int SymbolNr, float Kurs, float Volume, DateTime Zeit)
{
Console.WriteLine("peng"); // never see this in window - so not fired?
counter += 1;
}
public void start()
{
TaiPanRealtime TPRTObject = new TaiPanRealtime(); // connects to launches Application
DataStream TPRTDataStream = (DataStream)TPRTObject.DataStream; // attach to the DataStream Object.
foreach (int db_num in numbercodes)
{
TPRTDataStream.Add(db_num, 0); // This adds the internal dbnumber to the Stream
}
TPRTDataStream.Bezahlt+=new _IDataStreamEvents_BezahltEventHandler(TPRTDataStream_Bezahlt);
while (true)
{
Console.WriteLine(counter); // counter stays 0 all the time
System.Threading.Thread.Sleep(1000);
};
}
}
}
I want to post the solution TaiPan service found out. To handle the events correctly you need to set "Embed Interop Types" to false in the reference properties of visual basic. here is a screenshot:
screenshot properties
hope this helps others.
Related
I am working on a .NET Application which is rendering data from a source (say TCP) to excel using the Excel-DNA Library.
I have given example of LtpObserver which I have created by implementing IExcelObservable. I am creating the Observer using a Excel Function Call (Refer Code) --> "GetLtp".
'Data' referred here is containing a List of LtpObservers and Ltp value.
THE PROBLEM -
When I call the formula in Excel using a symbol say 'X', it creates the Observer (verified via Logging), and the data starts updating. Constructor of observer is called, as well as, callback is received on Subscribe() Method. But, when I call the same formula for 'X in another cell, no new Observer is created, neither a call on subscribe is received.
And upon deletion, of formula from just Cell#1, the Dispose is not called. But upon deleting from both Cell#1 and Cell#2 Dispose is called.
So is there just one observer for every unique symbol in the Excel Workbook? In that case does keeping a list of Observers and updating each of them on OnNext() makes sense? And what about the case when 2 or more formulas are used together in a single cell? How does this work Internally
CODE
class LtpObserver : IExcelObservable
{
private List<IExcelObserver> _observerList;
private string _symbol;
private Timer _timer;
public LtpObserver(string symbol)
{
Trace.TraceInformation("Constructor Called. New Ltp Observer Loaded for Symbol : " + symbol);
_symbol = symbol;
_observerList = new List<IExcelObserver>();
_timer = new Timer();
_timer.AutoReset = true;
_timer.Interval = FeedTimerConstant.ltpFrequency;
_timer.Elapsed += _timer_Elapsed;
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (Data != null))
{
_timer.Stop();
Data.LtpObserver = _observerList;
timer_tick(Data.Ltp);
}
else
{
timer_tick(0);
}
}
public IDisposable Subscribe(IExcelObserver observer)
{
Trace.TraceInformation("LTP Subscription for : " + observer.ToString() + " Symbol : " + _symbol);
_observerList.Add(observer);
if (Data != null)
{
Data.LtpObserver = _observerList;
timer_tick(Data.Ltp);
}
else
{
timer_tick(0);
_timer.Start();
}
return new ActionDisposable(() => {
Trace.TraceInformation("Un Subscribed for LTP Price :" + _symbol);
_observerList.Remove(observer);
});
}
void timer_tick(object _now)
{
foreach (var obs in _observerList)
obs.OnNext(_now);
}
}
-----------------------------------------------------------------------------------------------------------
[ExcelFunction(Name = "GetLtp", IsVolatile = true)]
public static object GetLtp(string symbol)
{
if (String.IsNullOrEmpty(symbol))
{
return INVALID_SYMBOL;
}
return ExcelAsyncUtil.Observe("GetLtp", symbol, () => new LtpObserver(symbol)
);
}
-------------------------------------------------------------------------------------------------------------
public class Data {
public decimal Ltp { get; set; }
public List<IExcelObserver> LtpObserver { get; set; }
}
The behaviour you describe is by design. The first two parameters passed to ExcelAsyncUtil.Observe are normally a string with the function name and an object or array of objects that provide a unique identifier for the IObservable stream.
So the part you describe in "THE PROBLEM" is exactly how it is intended to work. For every unique symbol you have a stream of values, and you can use the same values in multiple places on the sheet without a problem - they will be listening to the same underlying stream. If you have multiple different symbols active, you have multiple streams that you update with whatever mechanism, using the OnNext() calls.
In your code you need not make provision for multiple IObservers that Subscribe to your IObservable. But this detail is specific to the way Excel-DNA will call your IObservable. Excel-DNA will only ever Subscribe once to your IObservable. However, if you wanted to use the same IObservable class in other contexts or in another application, this might not hold an you might get multiple Subscribe calls.
(It would also make more sense to rename LtpObserver to LtpObservable.)
You could add extra information to that list to create separate topics according to the calling cell. This code might be something like this:
(I've removed the IsVolatile=true as that doesn't make sense for a streaming function wrapper like this)
[ExcelFunction(Name = "GetLtp")]
public static object GetLtp(string symbol)
{
if (String.IsNullOrEmpty(symbol))
{
return INVALID_SYMBOL;
}
var callerReference = XlCall.Excel(XlCall.xlfCaller);
var identifiers = new object[] { symbol, callerReference };
return ExcelAsyncUtil.Observe("GetLtp", identifiers, () => new LtpObserver(symbol, callerReference)
);
}
But now again you have a unique LtpObserver for the combination of symbol and calling cell. And again each such IObservable will only be subscribed to once by Excel-DNA.
Internally this is implemented using Excel's RTD mechanism. Excel can associate one or more RTD topics with a cell. When the topic value changes, Excel will invalidate the relevant cells, and recalculate them. There is some optimisation inside Excel so that this scales well.
I have a console program, not that complicated but at the same time's not a hello world one. I have just two projects, first one has several classes. It is not multithreaded, and is all about calling restful APIs etc.
The thing is this: I am trying to make my application check if it runs twice (it is very important). I thought that it would be somehow feasible, but turns out to be extremely complicated.
Unfortunately, the only example I found, doesn't shed any light on how to use this technology. Below the code, which, is quite complicated for me, and I don't know how to plug it in my Main. Hence, the question.
Below the code (is not mine, I found it here: https://www.codeproject.com/Articles/3014/Single-Process-Instance-Object)
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
namespace SpecialServices
{
//SingleProgamInstance uses a mutex synchronization
//object to ensure that only one copy of process is running
//at a particular time. It also allows for UI identification
// of the intial process by bringing that window to the foreground.
public class SingleProgramInstance : IDisposable
{
//Win32 API calls necesary to raise an unowned processs main window
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd,int nCmdShow);
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
private const int SW_RESTORE = 9;
//private members
private Mutex _processSync;
private bool _owned = false;
public SingleProgramInstance()
{
//Initialize a named mutex and attempt to
// get ownership immediately
_processSync = new Mutex(
true, // desire intial ownership
Assembly.GetExecutingAssembly().GetName().Name,
out _owned);
}
public SingleProgramInstance(string identifier)
{
//Initialize a named mutex and attempt to
// get ownership immediately.
//Use an addtional identifier to lower
// our chances of another process creating
// a mutex with the same name.
_processSync = new Mutex(
true, // desire intial ownership
Assembly.GetExecutingAssembly().GetName().Name + identifier,
out _owned);
}
~SingleProgramInstance()
{
//Release mutex (if necessary)
//This should have been accomplished using Dispose()
Release();
}
public bool IsSingleInstance
{
//If we don't own the mutex than
// we are not the first instance.
get {return _owned;}
}
public void RaiseOtherProcess()
{
Process proc = Process.GetCurrentProcess();
// Using Process.ProcessName does not function properly when
// the actual name exceeds 15 characters. Using the assembly
// name takes care of this quirk and is more accruate than
// other work arounds.
string assemblyName =
Assembly.GetExecutingAssembly().GetName().Name;
foreach (Process otherProc in
Process.GetProcessesByName(assemblyName))
{
//ignore "this" process
if (proc.Id != otherProc.Id)
{
// Found a "same named process".
// Assume it is the one we want brought to the foreground.
// Use the Win32 API to bring it to the foreground.
IntPtr hWnd = otherProc.MainWindowHandle;
if (IsIconic(hWnd))
{
ShowWindowAsync(hWnd,SW_RESTORE);
}
SetForegroundWindow(hWnd);
break;
}
}
}
private void Release()
{
if (_owned)
{
//If we own the mutex than release it so that
// other "same" processes can now start.
_processSync.ReleaseMutex();
_owned = false;
}
}
#region Implementation of IDisposable
public void Dispose()
{
//release mutex (if necessary) and notify
// the garbage collector to ignore the destructor
Release();
GC.SuppressFinalize(this);
}
#endregion
}
}
Any help using the above would be GREATLY appreciated; thank you so much.
how to use the sample code.
take the sample code (its one file) and add it to your project (as a separate .cs file)
now at the startup of your program main add
using(var spi = new SpecialServices.SingleProgramInstance("x5k6yz"))
{
if (!spi.IsSingleInstance){
Console.WriteLine("another copy is running");
return;
}
}
caveat, I have not tried the code from the sample, I assume it works.
EDIT. Ok tested, it works fine
Try this:
private void CloseDuplicateApplications()
{
string ProgramTitle = System.Diagnostics.Process.GetCurrentProcess().MainWindowTitle;
System.Diagnostics.Process[] Processes = System.Diagnostics.Process.GetProcesses();
for (int i = 0; i < Processes.Length; i++)
{
if (Processes[i].MainWindowTitle == ProgramTitle)
{
Processes[i].CloseMainWindow();
}
}
}
Currently the procedure simply closes any duplicate programs, however if you need to kill the duplicate program, replace this line:
Processes[i].CloseMainWindow();
With:
Processes[i].Kill();
Rookie here so please be nice!! I have had so much fun learning to program and gotten some great help along the way when google failed me. But alas, I'm stuck again.
I have a C# program that looks like this (It's MWS if anyone is familiar)
I've tried so many different ways to get this to effectively loop through a list of values in a text file. The problem I'm having is that the Main function is where I have to set the loop, but the BuildClass is where I need to cycle through the values in the text file (sentinel). I've included some stuff that probably isn't necessary just in case it is messing my code up and I don't realize it.
Here's what I've tried:
setting the loop inside the BuildClass - didn't expect it to work but it threw an exception before getting to the sentinel.
Reference the sentinel within the main function by changing the "using" or "var" in the main function sentinel to public - turned EVERYTHING red in visual studio
moving the string sentinel outside the main function so that the function and the BuildClass would recognize it - main function did not recognize it anymore.
I've tried so many other things unsuccessfully. I've gotten it to loop with the same sentinel value passed from BuildClass to the function over and over again but that's about it.
What I think I need:
A destructive version of streamReader that will remove the value from the text file when reading it. I'll put this inside the BuildClass, so that the next loop of the main function, the next value will be read and passed into the main function until the file is empty, terminating the loop.
an understanding of why changing sentinel to public destroys the code so badly. I have a decent understanding of why the other attempts wouldn't work.
namespace MainSpace
{
public class MainClass
{
int i;
public static void Main(string[] args)
{
ClientClass client = new ClientInterface(appName, appVersion, password, config);
MainClass sample = new MainClass(client);
string sentinel;
using (var streamReader = new StreamReader(#"sample.txt", true))
while((sentinel = streamReader.ReadLine()) != null)
{
try
{
//stuff
response = sample.InvokeBuild();
Console.WriteLine("Response Stuff");
string responseXml = response.ToXML();
Console.WriteLine(responseXml);
StreamWriter FileWrite = new StreamWriter("FileTest.xml", true);
FileWrite.WriteLine(responseXml);
FileWrite.Close();
}
catch (ExceptionsClass)
{
// Exception stuff
throw ex;
}
}
}
private readonly ClientInterface client;
public MainClass(ClientInterface client)
{
this.client = client;
}
public BuildClass InvokeBuild()
{
{
using (var streamReader = new StreamReader("sample.txt", true))
{
string sentinel = streamReader.ReadLine();
Thread.Sleep(6000);
i++;
Console.WriteLine("attempt " + i);
// Create a request.
RequestClass request = new RequestClass();
//Password Stuff
request.IdType = idType;
IdListType idList = new IdListType();
idList.Id.Add(sentinel);
request.IdList = idList;
return this.client.RequestClass(request);
}
}
}
}
I'm trying to write some tests for testing GUI interface. I decided to choose NUnit.Forms. But the tests fall with the following error:
TearDown : System.ComponentModel.Win32Exception : The requested resource is in use
I have two versions of the source code tests.
First:
using System.Windows.Forms;
using NUnit.Extensions.Forms;
using NUnit.Framework;
using YAMP;
namespace Tests.GUITests
{
[TestFixture]
public class GuiTest : NUnitFormTest
{
private FrmMain _frm;
//[SetUp] // or it is still needed
public override void Setup()
{
base.Setup();
_frm = new FrmMain();
_frm.Show();
}
[Test]
public void TestData()
{
var txtInput = new TextBoxTester("txtInput") {["Text"] = "2+2"};
var txtOutput = new TextBoxTester("txtOutput");
Assert.AreEqual("2+2", txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.AreEqual("4", txtOutput.Text);
}
}
}
Second:
using System.Windows.Forms;
using NUnit.Extensions.Forms;
using NUnit.Framework;
using YAMP;
namespace Tests.GUITests
{
[TestFixture]
public class GuiTest : NUnitFormTest
{
private FrmMain _frm;
//[SetUp] // or it is still needed
public override void Setup()
{
base.Setup();
_frm = new FrmMain();
_frm.Show();
}
[TearDown]
public override void TearDown()
{
_frm.Close();
_frm.Dispose();
}
[Test]
public void TestData()
{
var txtInput = new TextBoxTester("txtInput") {["Text"] = "2+2"};
var txtOutput = new TextBoxTester("txtOutput");
Assert.AreEqual("2+2", txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.AreEqual("4", txtOutput.Text);
}
}
}
And there are two different versions of the method TestNoData:
public void TestFormNoDataHandler()
{
var messageBoxTester = new MessageBoxTester("Message");
messageBoxTester.ClickOk();
}
[Test]
public void TestNoData()
{
ExpectModal("Message", TestFormNoDataHandler);
var txtInput = new TextBoxTester("txtInput") {["Text"] = string.Empty};
Assert.AreEqual(string.Empty, txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.IsFalse(_frm.DialogResult == DialogResult.OK);
}
[Test]
public void TestNoData()
{
var txtInput = new TextBoxTester("txtInput") {["Text"] = string.Empty };
Assert.AreEqual(string.Empty, txtInput.Text);
var btnRes = new ButtonTester("btnRes");
btnRes.Click();
Assert.IsFalse(_frm.Enable);
}
Testable form is very simple. There are two TextBox - "txtInput", "txtOutput" and button - "btnRes". In "txtInput" introduced a mathematical expression, and "txtOutput" output response. The decision of expression occurs when you press "btnRes". If the field "txtInput" empty, the button is disabled and you can not click on it.
When searching for solutions to this problem came on the following links:
AutomaticChainsaw: WinForms testing using NUnitForms
c# - I need to create a windows form from within a NUnit test - Stack Overflow
Unfortunately I can attach only 2 links. But the information I learned is very different. Especially the part of writing methods Setup and TearDown.
In any case, I specify the version I use:
Visual Studio 2015 Community
NUnit - 2.6.4.14350
NUnitForms - 1.3.1771.29165
Because it seems to me that the problem might be too recent versions of frameworks, as article I learned quite old.
Thank you for any suggestion.
UseHidden Property: Tests are run on a separate hidden desktop. This makes them much faster and it works for any tests that are not using the keyboard or mouse controllers. They are less disruptive and input tests cannot interfere with other applications.
UseHidden property controls whether a separate desktop is used at all.
Though tests on the separate desktop are faster and safer (There is no danger of keyboard or mouse input going to separate running applications.), however for some operating systems or environments the separate desktop does not work. And the tests throw up errors like:
System.ComponentModel.Win32Exception : The requested resource is in use
--TearDown
at NUnit.Extensions.Forms.Desktop.Destroy()
at NUnit.Extensions.Forms.Desktop.Dispose()
at NUnit.Extensions.Forms.NUnitFormTest.Verify()
In that case you can override UseHidden property from test class and set it to return false. This will cause the tests to run on original, standard desktop.
I am currently using the Change Notifications in Active Directory Domain Services in .NET as described in this blog. This will return all events that happen on an selected object (or in the subtree of that object). I now want to filter the list of events for creation and deletion (and maybe undeletion) events.
I would like to tell the ChangeNotifier class to only observe create-/delete-/undelete-events. The other solution is to receive all events and filter them on my side. I know that in case of the deletion of an object, the atribute list that is returned will contain the attribute isDeleted with the value True. But is there a way to see if the event represents the creation of an object? In my tests the value for usnchanged is always usncreated+1 in case of userobjects and both are equal for OUs, but can this be assured in high-frequency ADs? It is also possible to compare the changed and modified timestamp. And how can I tell if an object has been undeleted?
Just for the record, here is the main part of the code from the blog:
public class ChangeNotifier : IDisposable
{
static void Main(string[] args)
{
using (LdapConnection connect = CreateConnection("localhost"))
{
using (ChangeNotifier notifier = new ChangeNotifier(connect))
{
//register some objects for notifications (limit 5)
notifier.Register("dc=dunnry,dc=net", SearchScope.OneLevel);
notifier.Register("cn=testuser1,ou=users,dc=dunnry,dc=net", SearchScope.Base);
notifier.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(notifier_ObjectChanged);
Console.WriteLine("Waiting for changes...");
Console.WriteLine();
Console.ReadLine();
}
}
}
static void notifier_ObjectChanged(object sender, ObjectChangedEventArgs e)
{
Console.WriteLine(e.Result.DistinguishedName);
foreach (string attrib in e.Result.Attributes.AttributeNames)
{
foreach (var item in e.Result.Attributes[attrib].GetValues(typeof(string)))
{
Console.WriteLine("\t{0}: {1}", attrib, item);
}
}
Console.WriteLine();
Console.WriteLine("====================");
Console.WriteLine();
}
LdapConnection _connection;
HashSet<IAsyncResult> _results = new HashSet<IAsyncResult>();
public ChangeNotifier(LdapConnection connection)
{
_connection = connection;
_connection.AutoBind = true;
}
public void Register(string dn, SearchScope scope)
{
SearchRequest request = new SearchRequest(
dn, //root the search here
"(objectClass=*)", //very inclusive
scope, //any scope works
null //we are interested in all attributes
);
//register our search
request.Controls.Add(new DirectoryNotificationControl());
//we will send this async and register our callback
//note how we would like to have partial results
IAsyncResult result = _connection.BeginSendRequest(
request,
TimeSpan.FromDays(1), //set timeout to a day...
PartialResultProcessing.ReturnPartialResultsAndNotifyCallback,
Notify,
request
);
//store the hash for disposal later
_results.Add(result);
}
private void Notify(IAsyncResult result)
{
//since our search is long running, we don't want to use EndSendRequest
PartialResultsCollection prc = _connection.GetPartialResults(result);
foreach (SearchResultEntry entry in prc)
{
OnObjectChanged(new ObjectChangedEventArgs(entry));
}
}
private void OnObjectChanged(ObjectChangedEventArgs args)
{
if (ObjectChanged != null)
{
ObjectChanged(this, args);
}
}
public event EventHandler<ObjectChangedEventArgs> ObjectChanged;
#region IDisposable Members
public void Dispose()
{
foreach (var result in _results)
{
//end each async search
_connection.Abort(result);
}
}
#endregion
}
public class ObjectChangedEventArgs : EventArgs
{
public ObjectChangedEventArgs(SearchResultEntry entry)
{
Result = entry;
}
public SearchResultEntry Result { get; set; }
}
I participated in a design review about five years back on a project that started out using AD change notification. Very similar questions to yours were asked. I can share what I remember, and don't think things have change much since then. We ended up switching to DirSync.
It didn't seem possible to get just creates & deletes from AD change notifications. We found change notification resulted enough events monitoring a large directory that notification processing could bottleneck and fall behind. This API is not designed for scale, but as I recall the performance/latency were not the primary reason we switched.
Yes, the usn relationship for new objects generally holds, although I think there are multi-dc scenarios where you can get usncreated == usnchanged for a new user, but we didn't test that extensively, because...
The important thing for us was that change notification only gives you reliable object creation detection under the unrealistic assumption that your machine is up 100% of the time! In production systems there are always some case where you need to reboot and catch up or re-synchronize, and we switched to DirSync because it has a robust way to handle those scenarios.
In our case it could block email to a new user for an indeterminate time if an object create were missed. That obviously wouldn't be good, we needed to be sure. For AD change notifications, getting that resync right that would have some more work and hard to test. But for DirSync, its more natural, and there's a fast-path resume mechanism that usually avoids resync. For safety I think we triggered a full re-synchronize every day.
DirSync is not as real-time as change notification, but its possible to get ~30-second average latency by issuing the DirSync query once a minute.