I have a program written in C# that creates a Word doc by collating a bunch of text (extracted from objects). This application has worked fine for the past 4 years on many different machines, but right now it is breaking for one new client with the following error:
System.Runtime.InteropServices.COMException (0x80010108): The object
invoked has disconnected from its clients. (Exception from HRESULT:
0x80010108 (RPC_E_DISCONNECTED)) at
Microsoft.Office.Interop.Word.DocumentClass.get_Content() at
MyCompany.MyApp.Main.btnPrint_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e) at
System.Windows.Forms.Button.OnClick(EventArgs e) at
System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at
System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons
button, Int32 clicks) at
System.Windows.Forms.Control.WndProc(Message& m) at
System.Windows.Forms.ButtonBase.WndProc(Message& m) at
System.Windows.Forms.Button.WndProc(Message& m) at
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&
m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32
msg, IntPtr wparam, IntPtr lparam)
Here's the code snippet (it won't compile as-is because this is just an excerpt, but it should make sense):
// This will be the collated doc
object missing = System.Type.Missing;
Document combinedDoc = null;
// Temp doc holders
string tempWordFilePath;
object tempWordFilePathObj;
// Loop thru records and add their content to Word doc
foreach (RecordWrapper rec in records)
{
// Decode base64 attachment to byte-array
byte[] b = decodeToBase64(rec.body);
if (combinedDoc == null) combinedDoc = app.Documents.Add(ref missing, ref missing, ref missing, ref missing);
tempWordFilePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + (string)o.Item("Name").Value;
tempWordFilePathObj = tempWordFilePath;
if (File.Exists(tempWordFilePath))
{
File.Delete(tempWordFilePath);
}
// Write bytes into a temp Word doc
FileStream fs = new FileStream(tempWordFilePath, FileMode.CreateNew);
fs.Write(b, 0, b.Length);
fs.Close();
// Load the temp file as a Document
Document doc = app.Documents.Open(ref tempWordFilePathObj, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
// Insert page break
object collStart = combinedDoc.Content.Start;
object collEnd = combinedDoc.Content.End;
Range rng2 = combinedDoc.Range(ref collStart, ref collEnd);
object collapseEnd = Microsoft.Office.Interop.Word.WdCollapseDirection.wdCollapseEnd;
rng2.Collapse(ref collapseEnd);
// Paste range into resulting doc
rng2.InsertFile(tempWordFilePath, ref missing, ref missing, ref missing, ref missing);
object pageBrk = Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak;
rng2.InsertBreak(ref pageBrk);
doc.Close(ref missing, ref missing, ref missing);
File.Delete(tempWordFilePath);
}
I have read on an MSDN forum that this may be due to a missing library called SHDocVw.dll. I have repackaged my application with said library included but it's the same result. Others have said that it may be a Service Pack issue, but there haven't been any recommended solutions. Another person has recommended to ignore "80010108" errors but the idea was quickly dismissed by the OP. I have also read on here that this could be due to incorrect instantiation/referencing of certain Interop classes, but I don't see that happening in my code (or am I not seeing it?)
I had the same issue on a Windows 2008 server with Microsoft Office 2013.
Try to repair your Microsoft Office installation.
On control panel choose the repair option and reset your PC.
It worked for me!
Related
I am an OPC-UA newbie integrating a non-OPC-UA system to an OPC-UA server using the Milo stack. Part of this includes writing values to Nodes in the OPC-UA server. One of my problems is that values from the other system comes in the form of a Java String and thus needs to be converted to the Node's proper data type. My first brute force proof-of-concept uses the below code in order to create a Variant that I can use to write to the Node (as in the WriteExample.java). The variable value is the Java String containing the data to write, e.g. "123" for an Integer or "32.3" for a Double. The solution now includes hard-coding the "types" from the Identifiers class (org.eclipse.milo.opcua.stack.core, see the switch statement) which is not pretty and I am sure there is a better way to do this?
Also, how do I proceed if I want to convert and write "123" to a node that is, for example,
UInt64?
try {
VariableNode node = client.getAddressSpace().createVariableNode(nodeId);
Object val = new Object();
Object identifier = node.getDataType().get().getIdentifier();
UInteger id = UInteger.valueOf(0);
if(identifier instanceof UInteger) {
id = (UInteger) identifier;
}
System.out.println("getIdentifier: " + node.getDataType().get().getIdentifier());
switch (id.intValue()) {
// Based on the Identifiers class in org.eclipse.milo.opcua.stack.core;
case 11: // Double
val = Double.valueOf(value);
break;
case 6: //Int32
val = Integer.valueOf(value);
break;
}
DataValue data = new DataValue(new Variant(val),StatusCode.GOOD, null);
StatusCode status = client.writeValue(nodeId, data).get();
System.out.println("Wrote DataValue: " + data + " status: " + status);
returnString = status.toString();
} catch (Exception e) {
System.out.println("ERROR: " + e.toString());
}
I've looked at Kevin's response to this thread: How do I reliably write to a OPC UA server? But I'm still a bit lost... Some small code example would really be helpful.
You're not that far off. Every sizable codebase eventually has one or more "TypeUtilities" classes, and you're going to need one here.
There's no getting around that fact that you need to be able to map types in your system to OPC UA types and vice versa.
For unsigned types you'll use the UShort, UInteger, and ULong classes from the org.eclipse.milo.opcua.stack.core.types.builtin.unsigned package. There are convenient static factory methods that make their use a little less verbose:
UShort us = ushort(foo);
UInteger ui = uint(foo);
ULong ul = ulong(foo);
I'll explore that idea of including some kind of type conversion utility for an upcoming release, but even with that, the way OPC UA works you have to know the DataType of a Node to write to it, and in most cases you want to know the ValueRank and ArrayDimensions as well.
You either know these attribute values a priori, obtain them via some other out of band mechanism, or you read them from the server.
I got the following exception in itextsharp 5.0.6 library when I am trying to parse one PDF file
here is the link of that PDF File
https://backup.filesanywhere.com/fs/v.aspx?v=8c726b8f5a6673b56b6d
try
{
string s = null;
MessageBox.Show("Not-Protected");
PdfReader read = new PdfReader(openFileDialog1.FileName);
//MessageBox.Show(read.NumberOfPages.ToString());
for (int i = 1; i <= read.NumberOfPages; i++)
{
s = PdfTextExtractor.GetTextFromPage(read, i, new SimpleTextExtractionStrategy());
MessageBox.Show(s);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
System.NullReferenceException: Object reference not set to an instance of an object.
at iTextSharp.text.pdf.PdfContentParser.ReadArray()
at iTextSharp.text.pdf.PdfContentParser.ReadPRObject()
at iTextSharp.text.pdf.PdfContentParser.Parse(List`1 ls)
at iTextSharp.text.pdf.parser.PdfContentStreamProcessor.ProcessContent(Byte[] contentBytes, PdfDictionary resources)
at iTextSharp.text.pdf.parser.PdfReaderContentParser.ProcessContent[E](Int32 pageNumber, E renderListener)
at iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(PdfReader reader, Int32 pageNumber, ITextExtractionStrategy strategy)
The content stream of the first page of the PDF contains an array start bracket '[' inside the array operand of a TJ operator. This is not allowed as the array operand of a TJ operator may only contain strings and numbers.
Furthermore there is no matching array end bracket ']' inside that array operand, so the end bracket of the array operand itself closes this (illegal) inner array and the array operand does not have a closing bracket anymore. Thus, iText parses all the remaining content stream into the array and at the end of the content stream runs into the exception.
Adobe Reader is well known to ignore certain errors and try to fix others on the run. Knowing that there are no nested arrays allowed in page content descriptions, it seems to simply ignore the illegal opening bracket. This behavior of Adobe Reader is quite a nuisance because it allows defect PDF creation software to flourish.
PS: The line in question:
[(&)110($,"#'#"0'#.\(1\(2'0',#+345467839':'#.\(1;<"'0',#;345467839':'#.\(1!=.0',#\(345467839':'+.\(1\(2'0',#+7)(5)35(5467834':'+.\(1;<"0',#;7)(5)35(5467834)[(&)110($,"#'#"0'#.\(1\(2'0',#+345467839':'#.\(1;<"'0',#;345467839':'#.\(1!=.0',#\(345467839':'+.\(1\(2'0',#+7)(5)35(5467834':'+.\(1;<"0',#;7)(5)35(5467834)(':'*!>1;<"0',#;385467837)] TJ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>^
I have an email messge on an Exchange server (2010 SP1) with a Subject header that is 272 characters long. Both Outlook and OWA show it truncated to the first 252 characters followed by "...". EWSEditor shows it the same way. I know, however, that the full Subject is stored somewhere, because when I look at the headers in Message Options dialog Outlook or in the Message Details in OWA, all 272 characters are there.
My code is only gettting the truncated Subject, and I need a way to get the full string.
My code is using SyncFolderItems to get a ChangeCollection of ItemChange objects. I have two code branches for this. One retrieves FirstClassProperties, and one retrieves IdOnly. I have a function called getItemStringProp(), and depending on the branch, I either call it directly with the Item that I get from the ItemChange, or with the Item that I get by binding to the ItemChange.Item.Id. In both cases, my getItemStringProp() uses Item.TryGetProperty() and returns a max of 255 characters for the Subject. If the actual subject is longer, then I get 252 chars followed by "...".
Here's my code from the branch doing SyncFolderItems with FirstClassProperties:
useIdOnly = false;
icc = exchange.SyncFolderItems(folderId, PropertySet.FirstClassProperties, null, syncFolderItemsBatchSize, SyncFolderItemsScope.NormalItems, result.getSyncState());
and from the other branch:
useIdOnly = true;
icc = exchange.SyncFolderItems(folderId, PropertySet.IdOnly, null, syncFolderItemsBatchSize, SyncFolderItemsScope.NormalItems, result.getSyncState());
Following this, I drill down to get the Subject:
foreach (ItemChange ic in icc)
{
if (!useIdOnly)
{
icSubject = getItemStringProp(ic.Item, EmailMessageSchema.Subject,"Subject", folderName,"");
}
else
{
PropertySet itemProps = new PropertySet(BasePropertySet.IdOnly);
itemProps.Add(EmailMessageSchema.Subject);
itemProps.Add(EmailMessageSchema.DateTimeSent);
itemProps.Add(EmailMessageSchema.ItemClass);
Item item = Item.Bind(exchange, ic.Item.Id, itemProps);
icSubject = getItemStringProp(item, EmailMessageSchema.Subject, "Subject", folderName, "");
}
}
And here's the function that gets the Subject:
private String getItemStringProp(Item item, PropertyDefinition propDef, String propName, String fName, String defaultValue)
{
// some debug logging code and error checks omitted
object prop = null;
String value = "";
try
{
if (item.TryGetProperty(propDef, out prop) && prop != null)
{
value = prop.ToString();
}
if (prop == null || value == null)
{
value = defaultValue;
}
}
return value;
}
By the way, I'm aware that neither Outlook (at least the 2007 version) nor OWA allows creation of a message with a Subject longer than 255 characters. The message in question came into Exchange via SMTP, and a Subject far longer than 255 characters is legal according to the RFCs.
Don't rely on Item.Bind(), sync, search, or any other operation in EWS to load up all of the properties you're looking for. Have you tried getting the item, then doing a .load(PropertySet) or ExchangeService.loadPropertiesForItems()? Some properties won't come through in various retrieval actions even if you specifically request them. Some may come through, but get truncated. What makes it more fun is that I don't think there's any documentation telling you exactly which operations will return which properties, so you get to guess and check. You have to load the property set after you retrieve the Item(s), so it's usually best to get the Item with the ID only, then load the property set.
I want to read the <param> values of custom plugin
I could not find answer on the internet, what I found was:
https://github.com/firebreath/FireBreath/blob/master/src/NpapiCore/NpapiPlugin.cpp#L76
I see params are stored in pluginMain->setParams(paramList);
Can you point how can I access this paramList later? or pluginMain
Is there pluginMain->getParams()? I could not find reference
Nor I could locate the source for setParams().
The question is, how do I get that parameters from PluginWindowXXX or FB::NpapiPluginXXX ?
I exported m_npHost to PluginWindowXXX, set breakpoint in it with gdb but still no success.
All I can think of was:
(gdb) p ((FB::Npapi::NpapiBrowserHost)this->m_npHost)->GetValue
$17 = {NPError (const FB::Npapi::NpapiBrowserHost * const, NPNVariable, void *)} 0x7fe435adeff8 <FB::Npapi::NpapiBrowserHost::GetValue(NPNVariable, void*) const>
Obviously what I do is wrong but I am stuck,
I am passing this host from NpapiPluginX11.cpp
pluginWin->setHost(m_npHost);
taxilian's answer is the most correct one as always but I'll give a try. I'm reading params in my MyPluginAPI constructor.
MyPluginAPI::MyPluginAPI(const MyPluginPtr& plugin, const FB::BrowserHostPtr& host) : m_plugin(plugin), m_host(host)
{
string settings; //<param name="settings" value="{'foo':'bar'}">
settings = plugin->getParam("settings");
}
Inside your PluginCore-derived class, you can use either the getParam method or the getParamVariant method.
From the FireBreath Source:
boost::optional<std::string> PluginCore::getParam(const std::string& key) {
boost::optional<std::string> rval;
FB::VariantMap::const_iterator fnd = m_params.find(key.c_str());
if (fnd != m_params.end())
rval.reset(fnd->second.convert_cast<std::string>());
return rval;
}
FB::variant FB::PluginCore::getParamVariant( const std::string& key )
{
FB::VariantMap::const_iterator fnd = m_params.find(key.c_str());
if (fnd != m_params.end())
return fnd->second;
return FB::variant();
}
So if it's for sure a string (which it pretty much is, unless it starts with on, in which case it might have been converted to a referenced function), you can use:
boost::optional<std::string> mystr = getParam("mystr");
if (mystr) {
call_fn_with_string(*mystr);
}
Alternately, you can get it as a variant and convert it:
FB::variant mystrVal = getParamVariant("mystr");
try {
call_fn_with_string(mystrVal.convert_cast<std::string>());
} catch (FB::bad_variant_cast &err) {
// What to do if the cast to string fails
}
I am working on a web project where client needs a functionality to first upload some MS Word document & then he can compare any two of the uploaded documents.
The idea I came up with is to first make the documents available using WEBDAV & then open both documents using command line with "Compare side by side" option. In this way he will be able to compare & modify two documents.
The problem is, I am not able to find any command which can be run from command prompt to open two documents in compare mode.
Also, if you know any other way to achieve this functionality then please share it with me.
There is a project to do this using a PowerShell script, ExtDiff: https://github.com/ForNeVeR/ExtDiff
This may be an approach (for Visual Studio 2010)
I mixed together the two following links
http://social.msdn.microsoft.com/Forums/en-US/b7f4b480-ca1c-49a1-a2ea-b1d1cf5ad56b/how-do-you-compare-two-word-documents-in-c
http://msdn.microsoft.com/en-us/library/vstudio/ee342218%28v=vs.100%29.aspx
to a C# Console Project to which I added added the Reference:
.NET --> Microsoft.Office.Interop.Word Version 14.0.0.0
here the source:
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Word = Microsoft.Office.Interop.Word;
//using Office = Microsoft.Office.Core;
//using Microsoft.Office.Tools.Word;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Word.Application wordApp = new Word.Application();
wordApp.Visible = false;
object wordTrue = (object)true;
object wordFalse = (object)false;
object fileToOpen = #"C:\Temp\1.docx";
object missing = Type.Missing;
Word.Document doc1 = wordApp.Documents.Open(ref fileToOpen,
ref missing, ref wordFalse, ref wordFalse, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref wordTrue, ref missing,
ref missing, ref missing, ref missing);
object fileToOpen1 = #"C:\Temp\2.docx";
Word.Document doc2 = wordApp.Documents.Open(ref fileToOpen1,
ref missing, ref wordFalse, ref wordFalse, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing);
Word.Document doc = wordApp.CompareDocuments(doc1, doc2, Word.WdCompareDestination.wdCompareDestinationNew, Word.WdGranularity.wdGranularityWordLevel,
true, true, true, true, true, true, true, true, true, true, "", true);
doc1.Close(ref missing,ref missing,ref missing);
doc2.Close(ref missing,ref missing,ref missing);
wordApp.Visible = true;
}
}
}
TODO:
Replace 1.docx and 2.docx with strings from command line
maybe some Exception handling
I've looked at the list of command line switches and I didn't see anything relevant.
You could create a console application in .net that opens Word, loads in the 2 documents and switches Word to the compare documents viewmode. Instead of launching Word directly from the command line you launch your application.