Tapi3Lib Adding a new line at runtime - c#

I am having some trouble with the interop.tapi3lib.dll (which can be DL here:dllLink)
For a reporting program i'm writing, i want to monitor all of the devices available by the tapi for their calls. Now this is working nicely when i fire up the program, although i suspect the dll is written with the purpose of modifying calls on a single extension, with very little code i can see all of the activity perfectly.
The problem arrises when a user logs out (or in) a phone (I'm using this for a cisco Callmanager). At that time i am able to capture the tapi_object which in turn can be used to determine which line is removed and added (old number and new number) but i can't register the new address for sending events.
The exception when i try:
Value does not fall within the expected range.
because the tapiclass was created before this address was available i suspect.
At the moment i have done a test which creates a single tapiclass for each line individual and 1 tapiclass for monitoring the tapiobject event, but this is eating 10 times the memory for our company's configuration (20 phones) so i dont even want to test this at the target site (+300 phones). The other option (for i can think of) is to dispose the 'old' tapiclass and create a new one after, however i'm a bit concerned with either loosing events between, getting double events between and pingpong when multiple users log in/out (creating the class takes a couple of seconds with my program)
So, what i would really like is the option to
tapi.RegisterCallNotifications(ad, true, true, TAPI3Lib.TapiConstants.TAPIMEDIATYPE_AUDIO, 2);
for newly available lines.
Bit of background for answers :)
-I am fairly new to C#, completly new to COM-interop and i know the principles of C++, but ive never written anything in it.
Any help would greatly be appriciated. (also any comments about interop and such)

Hmm, turns out I was wrong. Adding the line for notification is possible and does not throw the exception. I think i didn't remove the old line before adding the new in my old sample.

Related

text exchange between two processes on a box using Memory Mapped File

Requirement is to be able to achieve 'chat' like communication between two console apps on the same windows box. I implemented this using named pipes, by implementing both a sender and receiver functionality in each app.
I want to try the same functionality but using Memory Mapped files (though I think it is not ideal for 'chat' type communication).
For simplicity sake, say chat messages are just strings of short length.
Here is what I have in mind:
One app will take care of creating a mutex and the memory mapped file.
Call it master.
In each app, we maintain two threads, one responsible for taking user
input and writing to the file, the other responsible for periodically
checking if it has something to read.
So four threads in all, each governed by a mutex for access to the
file.
Within the file, I think both should have their own 'section'. say
first half of the file size is for master app and the other half for
the second app.
So when user inputs a line of text in master app, the thread accesses
its half of the file and tries to append new text after the last new
line.
When app reads its section of the file for text, if there is any, app
reads it and blanks out its section.
Is this approach correct? Other approach would be to some how mark the message with the source id, so that the reader knows to ignore messages that are written by itself. But I feel that is unnecessary string parsing.
Also, other than each reader thread periodically trying to read their section of the file to see if there is new data, can you suggest any kind of notification mechanism? Sort of event handling? Reader thread will only go look for new messages if it gets some kind of event notification.
Any thoughts?
I agree with Hans for the most part, memory mapped files would not nessecarily be ideal here, if you go down this road though consider using a named event (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx) instead of polling.
You may need to p/invoke to get at this functionality from c#.
On the rest give each app its own region of the file, with a control section managed by the master to coordinate who gets what.

My System.IO.File.WriteAllText coding doesn't create a file after it has once been deleted in Windows Explorer

CONCLUSION AT BOTTOM OF POST
I'm a novice with C# and have only just begun using System.IO, but haven't been able to find information on my issue so wanted to ask the guys here:
I have a program that when run, creates a directory, then writes to a .txt file what the most recent value of a certain variable was, so that if the program is interrupted or the computer loses power, restarting the program will retrieve that stored number from the .txt file.
I've simply done this:
string INSTATR = LastValue.ToString();
System.IO.File.WriteAllText(#"C:\\DotTempFiles\\"+Instrument.Name+"ATR.txt", INSTATR);
My first time running this program, the file was created, and I found that on every cycle the number in the file was being overwritten to the last valid number just as I wanted.
However, once I went to the DotTempFiles directory and deleted the .txt file using Shift+Del, the file has never returned upon running the program as I thought it would. If I delete the entire directory and run the program, the directory is recreated but still not the file.
If I run the program using a different Instrument.Name, that new file is created as expected, but the original one that I once manually deleted is still not showing, even after computer restarts.
I can't find any information leads online, so does anyone have an idea? Thank you!
EDIT (more info): People asked a few questions so I'm adding more information (thank you)
There are no errors being reported. It compiles fine, and when running, there is an output window that usually alerts me to errors like if I reference an object that is null, or try to read from an empty file, etc. No errors like this are occurring.
More background on what the program is. There is a stock trading program called NinjaTrader that has their own API based on C#. They wouldn't support the questions I have because it's outside the normal scope of the script development they intended people to use, and that's ok with me. The program itself is a trading strategy that is run within NinjaTrader, and it exposes default programmer access to these two main methods:
Initialize()
protected override void OnBarUpdate() //this is the main part of the program that gets called every time a change has occurred to one of the bars on the stock chart.
In the variable declaration section I have this:
System.IO.DirectoryInfo di = Directory.CreateDirectory(#"C:\\DotTempFiles");
And in OnStartUp() I have this:
//Set up ReadMe file in the temp directory in case people wonder why it keeps appearing
string README = "This DotTempFiles directory is created by the strategy every time it is run, and temporary text files with the name [instrumentsymbol]ATR.txt are written into it containing the last highest ATRStopValue for the strategy, which if it is stopped and restarted with an open position, it will read from that file to get back the best value instead of recalculating it with possibility of a lower unwanted value.";
System.IO.File.WriteAllText(#"C:\\DotTempFiles\\README.txt", README);
Every time OnBarUpdate() is called, which can be up to a few times per second, it first calculates a double called LastValue which is a number related to the stock price, then it converts it to a string INSTATR, then writes it to a .txt file.
string INSTATR = LastValue.ToString();
System.IO.File.WriteAllText(#"C:\\DotTempFiles\\"+Instrument.Name+"ATR.txt", INSTATR);
And this is every single piece of code I have connected to this issue. As I mentioned above, it created the file the first time, but since I've deleted the file in windows explorer, it isn't able to recreate it. However, deleting the directory and restarting the strategy program does recreate that directory.
OnTermination() is not being used to close or delete the file in any way (just in case people wanted to ask) -- I am not using any other code to interact with the file than the ones already shown. Thanks!
EDIT 2 (Update after reading comments): Thank you guys for your comments and help. What I'll do when I get back to my home is try recreating the minimal version of this with an empty program containing just these lines of code and see what the outcome is, and I'll post updates in either way.
EDIT 3: Thank you Steve, that is a very good idea that I should use from now on for these kinds of things.
EDIT 4 (Conclusion): Well, I found out that I overlooked something simple about my own code logic. I was setting the File.WriteAllText to trigger any time the Double variable increased in value, not on every call of the OnBarUpdate method. Because of this, the file would not be written except once every few hours or so and now I see that everything is working properly. I am sorry that I made all these people read this post since it was based on another issue of my own fault. However, I am very thankful to everyone for their comments that helped me get to this point, and to Steve and Mark Lakata for their tips that I learned some new good things from.
I found out there is nothing wrong with the file creation, it was the fact that my coding logic was just calling for it far less frequently than I assumed it was (once every few hours vs several times per second)

Getting unique hardware ID changes everytime C#

I want to make a program and sell it, so I was thinking to make some kind of licensing system. What I've found on google is this:
http://www.codeproject.com/Articles/28678/Generating-Unique-Key-Finger-Print-for-a-Computer
I am running Windows 7 (32 bit) in VirtualBox from Ubuntu. I get the same UID, but when I restart my Windows, I get a new UID. I am just thinking that some people will buy my program and they may run it from VirtualBox, so it would be a problem.
Do you guys have any suggestions?
Even if it's an easier way, but something that won't change even if I restart my VBox.
You need to not get so bogged down in the whole DRM process, there are always smarter people out there and someone will work out how to circumvent it.
If you're really concerned:
Set up an online license server to hold your users licenses
Prevent the application from doing anything until the user enters a valid license
This licence would be validated over the internet by your service
You could restrict the number of "active" applications using your service that way
Think along the lines of how iTunes allows you to authorise up to 5 computers to access your media library.
Even if a lot of time has passed, I want to add a possible solution to this question, pointing out something that happened to me trying to generate a fingerprint with exactly that code and facing the same problem.
The identifier function retrieves only the first not-empty value of wmiProperty for each wmiClass. The first important thing you should be aware of is this: what is returned for every wmiClass might not belong to the same ManagementObject. Hence, if something changes to "not the first object", this might affect also your fingerprint.
Be advised that using Win32_DiskDrive as wmiClass is dangerous since plugging in a USB device often results in this device being recognized as the first one (instead of your hard drive), changing the fingerprint as you plug-in or out your device. Even if this doesn't happen, still one of the wmiProperty could be taken from your USB device if your main drive has it empty (e.g. the disk signature, which happened to me).
A possible solution to that would be excluding all USB devices by checking InterfaceType and excluding all those who match "USB", or at least that's what I did.

How to Show the Content of a Variable Which is in a Class Library In A Form Or Console?

I have a C# solution which contains a project and a class library written by somebody else. The class library gets GPS data via wifi. The project shows the processed data on a map. Now, I want to see the contents of some variables in the class library in real time for the sake of debugging.
I tried to use
System.Diagnostics.Debug.Write(value)
without success. It seems it does not do anything.
Also I tried "MessageBox.Show(value.ToString())" which was good but it stopped the wifi reading and interrupted the program as I needed to press OK button each time that it showed up.
Moreover, I added a windows form (which contained a textBox) to the class library to print the data in the textBox, however, when I wrote:
Form1.textBox1.Text = value.ToString()
It gives me this error:
Error 3 'MapNMEA.Form1.textBox1' is inaccessible due to its protection level C:\Users\john\Documents\Visual Studio 2010\Projects\new ver of map purecom\MapExplorer\MapExplorer\MapNMEA\MapNMEA\SerialPort.cs 184 27 MapNMEA
"MapNMEA" is the name of the class library. Also "MapExplorer" is the name of both solution and the project. "SerialPort.cs" is a file inside the class library in which I wrote the above code.
My question is how to show the content of those variable (they are 3,4 variables) in real time and this act should not stop the wifi reading. I need to do this as an electrician who does not know much about programming wants to check whether a GPS device sends the data to my computer correctly or not.
UPDATE 1: Actually I noticed that System.Diagnostics.Debug.Write(value) is working but as there was too many warning messages showing up in the debug window, I did not noticed it. Now, if somehow I could remove (or hide) other (warning) messages, I would see only my desired output. Do you know?
Debug.Write should be fine if you attach a listener first (Debug.Listeners.Add( new _a_listener_type() )).
Also, you should probably be aware of the AutoFlush property on the Debug class which determines whether or not Flush is automatically called.
Debug.Write should work - by default it will write to the 'Debug' window in Visual Studio if you have the debugger attached. Are you sure you're looking in the right place?
If you want to use the form approach, you need to keep track of the instance of the form which is open, and give it a public method. For example:
public void WriteDebug(string message) {
TextBox1.Text += message + Environment.NewLine;
}
Then you can call formInstance.WriteDebug(message);.
Do you run debug build? Also your code with textbox does not work, because textBox1 is non-public
I think you may not be searching the right location: Is there something preventing you from debugging on a PC first before going to a target? If not, the you should probably use the traditional way: put spies on variables, use your IDE (Visual Studio) to watch them and so on.
If you actually NEED to run on target without advanced debug tools, then you might want to take a look at some easier solutions:
log them to a text file (append or replace, whatever you need), then have a viewer opened at hand
make another non-modal form with a textbox, and call a form2.writeDbgTextBox(String) every time you need to refresh
Be sure to remove this code on release (eg. by putting them in a #if DEBUG section)
And whatever happens, DO NOT try to write to an existing Message box! they are made to pop up and close, not to interact with your code.

Windows clipboard CRLF/LF passing wrong for one user

We have a pair of applications. One is written in C# and uses something like:
string s = "alpha\r\nbeta\r\ngamma\r\ndelta";
// Actually there's wrapper code here to make sure this works.
System.Windows.Forms.Clipboard.SetDataObject(s, true);
To put a list of items onto the clipboard. Another application (in WinBatch) then picks up the list using a ClipGet() function. (We use the clipboard functions to give people the option of editing the list in notepad or something, without having to actually cut-and-paste every time.)
In this particular environment, we have many users on one system via Citrix. Many using these pairs of programs.
Just one user is having the problem where the line delimiters in the text are getting switched from CRLF to LF somewhere between the SetDataObject() and the CLipGet(). I could explain this in a mixed Unix/Windows environment, but there is no Unix here. No unix-y utilities anywhere near this system either. Other users on the same server, no problems at all. It's like something in Windows/Citrix is being "helpful" when we really don't want it, but just for this one guy.
Ideas?
Have you tried clearing their profile on Citrix? That seems to be the solution to many many user specific Citrix problems.
Does Environment.NewLine behave differently on Citrix environments? If so, it may give you a good option that works for all users instead of \r\n.

Categories

Resources