|
Hi,
I haven't done these things myself, however I remember reading about it. Here are some thoughts:
1.
different versions of Office need different libraries ("Primary Interop Adapters"), so you would have to rebuild your app, and you can make it work reliably with only one Office version at a time. I suggest you google for details.
2.
Most articles don't discuss handling multiple Word documents; and most do close both the document and the Word application (your shortened example did not show that).
3.
Here is one CodeProject article on Office automation out of many: Word Automation using VB.NET - Part I[^]
Hope this helps.
|
|
|
|
|
Hey Luc
Thank you very much for your quick answer.
Ok so I downloaded the project from step 3.
I hit the open-doc Button: Document gets opened in MS Word
I hit the read word button: Msgbox appears with document content
I hit the read word button again: Again the msgbox appears with document content
I hit the read word button for the 3rd time: Msgbox appears with document content
I hit the open-doc Button: unhandled Exception System.Runtime.InteropServices.COMException (0x800A1066): command failed
Now the buttons don't work anymore. no open or read...
I closed the app. opened it again. first time opening the word doc works, 2nd and 3rd try no more...
I closed the app again. reopened it. again the first time was ok, any further clicks on open-doc will result in the same Exception above
There is something wrong, but I don't have a clue what...
|
|
|
|
|
That sounds weird. Some more thoughts:
1. you could try on another machine, maybe something is wrong with your Office.
2. if still no luck, you could post on that article's forum too.
3. are you doing anything special within Word? macro's? VBA code?
|
|
|
|
|
Yes it is really weird indeed.
Tried already different machines. On one i'm doing a clean reinstall right now and then i'm going to check again.
No we do not use features like macros or vba.
|
|
|
|
|
Office 2010 does not support automation from unattended client application or components. Maybe this link[^] can help you.
|
|
|
|
|
Hmm thanks for the link.
So with office 2010 the "remote controll" for word via interop-services is gone?
Its weird, because why should it work the first time i do an export and then it doesn't go any further. and our vendor has other customers working with office 2010 and they don't have the problem.
Has anybody for example tested this project demo here with office 2010:
Word Automation using VB.NET - Part I[^]
|
|
|
|
|
Well, not exactly that, I think. What Microsoft says is that it is gone for unattended client applications. What I understand here is that an Office Application might, for example, show a MessageBox, which requires user interaction, and thus an unattended client application would not be able to handle it and any further request to the Office application will unavoidably lead to a COMException.
|
|
|
|
|
Hmm ok. So all my Programms should actually work, because they're alle installed locally, operated by the local user und also use the local word application.
|
|
|
|
|
Errrr, you know, it's hard to say... In my own experience, when Microsoft says something like "this will not work in these conditions" it really means "this will not work in some conditions".
Maybe in this case the problem is that you are trying to open the same file more than once at the same time, so it is locked as readonly from the second time unless you close the first one before.
Really, I would like to help you, but I'm afraid that the best advise I can give you is that you do what I usually do in these cases: if you know exactly when it fails and when it works, try a work-around to avoid the problem.
|
|
|
|
|
I am trying to read serial data from a microchip.
Using the simple serial c# project I am able to read the characters being sent, but I am not able to delineate carriage returns and so the correct data will stream across the screen until the programs input box end and then it will wrap around to the next line and continue to stream, an example would be
seveneightnineteneleventwelvethirteen
fourteenfifteensixteenseventeeneighteen
instead of
seven
eight
nine
ten
eleven
twelve
thirteen
fourteen
fifteen
sixteen
seventeen
eighteen
Does anyone know how I can recognize the carriage returns? They should come through as an ascii character "13" and the serial data protocol is 8 databits no paraty one stopbit (8N1) at a baudrate between 9600 and 115200 baud.
Thanks!
|
|
|
|
|
What have you tried? Are you checking each character as it arrives, or just passing the stream onto the input box?
Are you handling them as characters or bytes?
Post the relevant code fragments so we can tell what you are doing - that should help us to help you!
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
Hi,
Here is the guts of it
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen) serialPort1.Close();
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if(!serialPort1.IsOpen) return;
char[] buff = new char[1];
buff[0] = e.KeyChar;
serialPort1.Write(buff, 0, 1);
e.Handled = true;
}
private void DisplayText(object sender, EventArgs e)
{
textBox1.AppendText(RxString);
}
private void serialPort1_DataReceived
(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadExisting();
this.Invoke(new EventHandler(DisplayText));
}
|
|
|
|
|
The first thing which springs to mind is:
Don't read the text into a string and invoke a routine to handle it. The only logical reason for doing that is to get the execution onto the GUI thread - which may not execute it immediately. If a single other character arrives in the mean time, it will discard your existing data. Better to get the data in the invoked method instead, or add it to a queue (my preference).
Regarding your problem with new lines: Are you sure you are receiving them? Remember that ReadExisting translates according tgo the encoding (Strings are generally Unicode, serial ports are generally ASCII). I would be tempted to either try using ReadLine instead of ReadExisting, or ReadAllBytes and display the data as Hex, at least in the early stages.
I also wouldn't want to use a TextBox - a ListBox might be better as it doesn't slow down lots when the strings start to get large.
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
Hi OG,
What do you think about using a rich text box? That would be ideal for me. I do have to preface this that I am new to c# and o.o and changing parameters around sometimes FUBARs everything because I'm new.
I am sure I am receiving the (13) because I have a barebones serial reader application that can read them correctly.
With this statement
"Don't read the text into a string and invoke a routine to handle it. The only logical reason for doing that is to get the execution onto the GUI thread - which may not execute it immediately."
How would I add it to a queue, I'm hoping that the data will stream up to the data rate speed without issue. When it is going across the screen it does not appear to be missing bits in the string I am sending.
|
|
|
|
|
Luc seems to have covered it all pretty well in his answer - good luck!
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
I suspect your problem is with how ReadExisting() handles the carriage returns; it may well be expecting a carriage return line feed pair of characters, to indicate a new line.
If I am using Serial port for text data, I get the data as a byte array; and then convert it to a string, either using Encoding - Encoding.ASCII.GetString(myByteArrray) or manually processing each character if I need to handle specific bytes individually.
Off the top of my head, I can't remember if GetString will convert a striaght carriage return to a new line; but if not you can process each byue of the array in turn, detecting the carriage return and adding Environment.NewLine in it's place to the string.
Hope this helps.
|
|
|
|
|
Hi Colin,
Maybe I can send it different characters for a line feed ... do you happen to know what pair of characters is it expecting?
With the byte array, are you just filling it up with 8 bits, and then at the stop bit converting it to a string?
|
|
|
|
|
I expect it wants a carriage return followed by a line feed - 0x0d 0x0a
Reading a byte array is not that low a level; the SerialPort class gives you a method to read byte data - SerialPort.Read Method (Byte[], Int32, Int32).
You can use the BytesToRead property to see how many bytes there are in the buffer.
|
|
|
|
|
In .NET a new line is triggered by a LF (0x10) or "\n", a preceeding CR (0x13) is optional. Most other systems react on CR and tolerate an optional LF. If your microprocessor isn't sending any LF then all data will be on a continuous line by default.
There are many ways to remedy that, here is one you may like:
1. tell your serial port you want LF as NewLine indicator, by setting mySerialPort.NewLine="\r";
2. now read text lines using mySerialPort.ReadLine()
Furthermore, I would avoid the DataReceived event in this case; I'd rather have an explicit thread performing ReadLine() in a loop, and invoking the Control that is going to process it right away.
I agree with Griff a ListBox is more suited for long, line-oriented texts; I must add going from a TextBox to a RichTextBox is a step backward, performance wise. It too holds all text in one big string internally (even when you use the AppendText method, which is better than Text=Text+newText).
|
|
|
|
|
Thanks for the reply Luc
I will try to get this up and running tonight per your instructions, I thought rich text would be good because of the ability to color format things, but maybe not. Speed would be up to 20 mips per second max, slower than that in reality, probably more like 1 mips in reality. I will setup the newline/readline and if I can get that working, setup the listbox. Thanks
|
|
|
|
|
If all you need is homogeneous line coloring (say lots of black lines, a few green or red), then that isn't very hard to do with a ListBox. I have an example here[^].
|
|
|
|
|
Hi Luc,
I tried what you suggested and it still isn't working, its behavior remains unchanged. I also tried sending the serial data as a "(10)" instead of a "(13)" and that did not work either, it actually wouldn't read anything with the 10. Should I try and send a different ascii character or stick with the 13?
|
|
|
|
|
I suggest you validate the incoming bytes somehow. I see basically two ways to do that:
1.
use a terminal emulator (such as good old HyperTerminal) and see what comes in.
2.
better, use SerialPort class in binary mode, basically something along these lines:
SerialPort port=new SerialPort();
...
...
Thread.Sleep(5000);
int DIM=300;
byte[] bytes=new byte[DIM];
int n=port.Read(bytes,0,DIM);
for(int i=0; i<n; i++) {
byte b=bytes[i];
char c=b;
log("bytes["+i+"]=0x"+b.ToString("X2")+"="+c);
}
where log is a simple logging method, could be:
public static void log(string s) {
Console.WriteLine(s);
}
|
|
|
|
|
Hi Luc,
Here is what it looks like with the OE program, so it is working correctly. There has to be something I'm missing here?
<
>
http://img221.imageshack.us/img221/4316/serialterminal.png[^]
Here is my code after all kinds of tweaks or attempts to get this to work, if you'd like anything else just let me know. Thanks!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace SimpleSerial
{
public partial class Form1 : Form
{
string RxString;
public Form1()
{
InitializeComponent();
string[] theSerialPortNames = System.IO.Ports.SerialPort.GetPortNames();
}
private void buttonStart_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM7";
serialPort1.BaudRate = 115200;
serialPort1.Handshake = Handshake.None;
serialPort1.Open();
if (serialPort1.IsOpen)
{
buttonStart.Enabled = false;
buttonStop.Enabled = true;
textBox1.ReadOnly = false;
}
}
private void buttonStop_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
buttonStart.Enabled = true;
buttonStop.Enabled = false;
textBox1.ReadOnly = true;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen) serialPort1.Close();
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if(!serialPort1.IsOpen) return;
char[] buff = new char[1];
buff[0] = e.KeyChar;
serialPort1.Write(buff, 0, 1);
e.Handled = true;
}
private void DisplayText(object sender, EventArgs e)
{
textBox1.AppendText(RxString);
}
private void serialPort1_DataReceived
(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadExisting();
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
serialPort1.DataBits = 8;
serialPort1.NewLine = "(13)";
this.Invoke(new EventHandler(DisplayText));
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void comboBox1_Click(object sender, EventArgs e)
{
}
}
}
|
|
|
|
|
Hi,
some comments:
1.
as your terminal emulator is working, it would be time to try the binary mode I have shown earlier. It has the advantage of (a) showing the exact bytes you're getting, and (b) you're using your own code (as opposed to the terminal emulator).
2.
you should set the port's properties right when you open it, and not in its DataReceived handler, i.e. after having gotten some data already.
3.
turbosupramk3 wrote: serialPort1.NewLine = "(13)";
that is non-sense. You need a CR character, which is represented by \r in C-like languages. cfr my first reply.
4.
I wouldn't use a single TextBox for both input and output, at least until everything works well. I also wouldn't spend all that effort in the GUI stuff until such moment that the serial comm is working fine.
I think you're getting closer to the solution!
|
|
|
|