Opening a document from Imanage in Word 2016 - c#

I am attempting to open an Imanage document, in MS Word, within a temporary test application (for debugging) to later copy over into an ActiveX control project. The error that is popping up is:
Exception thrown at 0x7618851A (msvcrt.dll) in w3wp.exe: 0xC0000005: Access >violation reading location 0x09801000.
If there is a handler for this exception, the program may be safely continued.
The error occurs when running the cmd.Execute line and I am unsure as to why I am getting the error.
using IManage;
using IMANEXTLib;
using System;
namespace WebApplication3
{
public partial class WebForm2 : System.Web.UI.Page
{
IManDatabase imanagedatabase;
IManDMS myDMS = new ManDMSClass();
protected void Page_Load(object sender, EventArgs e)
{
openImanageDoc("docNumber", "versionNumber", "server", "database", ReadOnly);
}
public void imanageLogin(string server, string database)
{
try
{
IManSession session = myDMS.Sessions.Add(server);
IManWorkArea oWorkArea = session.WorkArea;
session.TrustedLogin();
foreach (IManDatabase dbase in session.Databases)
{
if (dbase.Name == database)
{
imanagedatabase = dbase;
}
}
}
catch (Exception ex)
{
throw ex;
}
}
public void openImanageDoc(string docNo, string versionNo, string server, string database, bool isReadOnly = true)
{
IManDocument doc;
try
{
imanageLogin(server, database);
int iDocNo = int.Parse(docNo);
int iVersion = int.Parse(versionNo);
doc = imanagedatabase.GetDocument(iDocNo, iVersion);
openNRTDocument(ref doc, isReadOnly);
imanagedatabase.Session.Logout();
myDMS.Close();
}
catch (Exception Ex)
{
imanagedatabase.Session.Logout();
throw Ex;
}
finally
{
imanagedatabase = null;
myDMS = null;
}
}
public void openNRTDocument(ref IManDocument nrtDocument, Boolean isReadonly)
{
OpenCmd cmd = new OpenCmd();
ContextItems objContextItems = new ContextItems();
objContextItems.Add("NRTDMS", myDMS);
objContextItems.Add("SelectedNRTDocuments", new[] { (NRTDocument)nrtDocument.LatestVersion });
objContextItems.Add("IManExt.OpenCmd.Integration", false);
objContextItems.Add("IManExt.OpenCmd.NoCmdUI", true);
cmd.Initialize(objContextItems);
cmd.Update();
cmd.Execute();
}
}
}
Due to the nature of the error, I am presuming it is a configuration issue rather than a code error although I could be completely wrong as I am very new to programming.
I have found out that w3wp.exe is an IIS worker process created by the app pool but other than that I have no idea what the numeric code represents. Any help or advice is greatly appreciated.

The error is being raised by the OpenCmd instance because it is most likely trying to access resources such as local registry settings. It's not possible to do that in a web application, unless you host your code in a proprietary technology like ActiveX (which is specific to Internet Explorer)
Actually, it is not appropriate for you to use OpenCmd here. Those type of commands (iManage "ICommand" implementations) are intended to be used in regular Windows applications that have either the iManage FileSite or DeskSite client installed. These commands are all part of the so-called Extensibility COM libraries (iManExt.dll, iManExt2.dll, etc) and should not be used in web applications, or at least used with caution as they may inappropriately attempt to access the registry, as you've discovered, or perhaps even display input Win32 dialogs.
For a web app you should instead just limit yourself to the low-level iManage COM library (IManage.dll). This is in fact what iManage themselves do with their own WorkSite Web application
Probably what you should do is replace your openNRTDocument method with something like this:
// create a temporary file on your web server..
var filePath = Path.GetTempFileName();
// fetch a copy of the iManage document and save to the temporary file location
doc.GetCopy(filePath, imGetCopyOptions.imNativeFormat);
In an MVC web application you would then just return a FileContentResult, something like this:
// read entire document as a byte array
var docContent = File.ReadAllBytes(filePath);
// delete temporary copy of file
File.Delete(filePath);
// return byte stream to web client
return File(stream, MediaTypeNames.Application.Octet, fileName);
In a Web Forms application you could do something like this:
// set content disposition as appropriate - here example is for Word DOCX files
Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
// write file to HTTP content output stream
Response.WriteFile(filePath);
Response.End();

Related

How to handle System.Runtime.InteropServices.COMException (0x800706BA): The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

I am developing a Windows application where I manipulate Word Application. More specific, I am opening a Word Document but when I quit it and try to open another Word Document this Error comes out.
How to handle
System.Runtime.InteropServices.COMException (0x800706BA): The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) at Microsoft.Office,Word.ApplicationClass.set_Visible(Boolean Prop)**
If I don't quit the Word Application this error does not come out.
Below I show you the functions that I open and quit the Word Application.
//function to open word Document located in a specific path
public static void openWordDocument(string fileName)
{
try
{
wordApplication.Visible = true;
string filePath = myPath + fileName;
WordApi.Document docx = wordApplication.Documents.Open(filePath);
}
catch (Exception ex)
{
MyLogger.Error(ex.ToString());
}
}
//function to quit wordApplication
public static void CloseWordApp() {
try {
Object wordAppObject = Marshal.GetActiveObject("Word.Application");
WordApi.Application wordApp = (WordApi.Application)wordAppObject; //cast Object to its actual type
wordApp.Quit();
}
catch (Exception ex) {
MyLogger.Error(ex.ToString());
}
I finally figured it out what is the problem.
The main problem was that when I quit it and try to open another Word Document,which opening another Word Document means get/create an Object of Word Application. In my case wordApp != null, after finalizing the application, so I had to create another Word Application Object and return it for the case.
//open word Document located in a specific path
public static void openWordDocument(string fileName)
{
try
{
wordApplication = createWordApplicationObject(wordApplication);
wordApplication.Visible = true;
string filePath = myPath + fileName;
WordApi.Document docx = wordApplication.Documents.Open(filePath);
}
catch (Exception ex)
{
MyLogger.Error(ex.ToString());
}
}
private static WordApi.Application createWordApplicationObject(WordApi.Application wordApp)
{
WordApi.Application wordAppFirstTime;
WordApi.Application wordApp1;
if (wordApp == null)
{
wordAppFirstTime = new WordApi.Application();
return wordAppFirstTime;
}
else
{
wordApp1 = new WordApi.Application();
return wordApp1;
}
}
With CloseWordApp() remain the same.
Most probably the exception is fired by the following line of code:
wordApplication.Visible = true;
You need to make sure the COM server is alive. Because after quitting the object becomes unavailable. I'd suggest setting such object references to null, so later we could check whether the application object is still alive. For example:
try
{
if (wordApplication == null)
{
wordApplication = new Word.Application();
}
wordApplication.Visible = true;
string filePath = myPath + fileName;
WordApi.Document docx = wordApplication.Documents.Open(filePath);
}
catch (Exception ex)
{
MyLogger.Error(ex.ToString());
}
I wanted to add a solution that works for me. We had this issue in a .net web service, along with other errors, like "the remote procedure call failed" on Word.Documents.Open(). i'll list all the things we tried, and finish with the solution.
we tried:
Make sure RPC service is up. Word is not corrupted, opens properly,
including the file we were opening.
restart server and service hosting the web application.
Rollback a windows update that occured the same day it stopped working.
Uninstalled the antivirus software.
We isolated the code to a third party app to validate it was the open()
method that caused the problem, and using different files as well. We
created a win form app, and consol app. We ran that small app as win
admin, a regular account as well as the account that runs the web
app.
We ran procMon.
we did a repair on word.
we installed Office all over, we tried 32 and 64bits version
Finale solution:
we deleted the user profile that runs the web app.
4 days to find that out. I'd thought i'd share my paine with the world. lol
while posting these lines, we are not sure why the local profile created this issue.

The process cannot access the file 'C:\file.txt' because it is being used by another process

I am trying to log each method on my program, I have the application deployed on IIS Server and the user just called me and said the email functionality is not working so I need to basically run the application but log each step into a txt file.
I am declaring the below as a global value:
StreamWriter writer = new StreamWriter("C:\\file.txt");
Then I use it like below in my code:
Method 1
{
if (file1.HasFile)
{
writer.WriteLine("Has File");
}
}
Method 2
private Boolean InsertUpdateData(SqlCommand cmd)
{
writer.WriteLine("Insert Started" + DateTime.Now.ToString());
}
So in my case method one runs fine and it writes Has File but when it goes into the second method I get the file is already open which is correct how can I work around this?
Thanks
Global Value - declared at top
namespace WorkOrderManagement
{
public partial class CreateWorkOrder : System.Web.UI.Page
{
bool successfull;
string path;
string name;
string content;
string datas;
string ext;
bool affectedrows;
string seasonalsupervisor;
private string sLogFormat;
private string sErrorTime;
StreamWriter writer = new StreamWriter("C:\\file.txt");
I really suggest you to discard the idea to have a global variable to represent a stream and then try to use it in different methods. This is simple in a desktop application, but a lot more complex in an ASP.NET application.
There are simple alternatives that could atomically write your log text and leave the file unlocked.
For example you could have a method like this
public static class Log
{
public static string _file = "log.txt";
public static object _locked = new object();
public static void AppendToLog(string text)
{
lock(_locked)
{
string path = Server.MapPath("~/APP_DATA");
File.AppendAllText(Path.Combine(path, _file), text + Environment.NewLine);
}
}
}
Now you can call the log write with
Log.AppendToLog("My message");
I want to underline two important things here. First I don't write in the root drive of the server. This is a bad practice and always a source of problems when you deploy your ASP.NET application in a server where you have not permissions to use anything outside your site root. Thus the ASP.NET system defines a particular folder called APP_DATA under your site root where your application should have read/write permissions.
Second point to notice is the use of the lock keyword. This is necessary in an environment like ASP.NET where two users could reach a point of the code where you need to write to the common log file. As MSDN explains it
The lock keyword ensures that one thread does not enter a critical
section of code while another thread is in the critical section. If
another thread tries to enter a locked code, it will wait, block,
until the object is released.
you can also do this to close the file stream
using (StreamWriter writer = new StreamWriter("C:\\file.txt"))
{
//your code here
}
//this automatically closes the stream, and it is more recommended.
Close the stream after writing the file
Method 1
{
if (file1.HasFile)
{
writer.WriteLine("Has File");
writer.Close();
}
}

Webclient causing an invalid operation exception

I'm trying to download a simple xml file and save it to the users local profile. When trying to download (i don't think this has anything to do with the saving location but i'm not 100% sure) i get the following exception on the webclient.
System.InvalidOperationException
My code is as follows;
public void downloadProxy() {
string url = Properties.Settings.Default.url;
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "/netsettings/proxies.xml");
try
{
WebClient GrabFile = new WebClient();
GrabFile.DownloadFile(url, path);
}
catch (WebException webEx)
{
if (webEx.Status == WebExceptionStatus.ConnectFailure)
{
Console.WriteLine("Are you behind a firewall? If so, go through the proxy server.");
}
}
}
If you are on a Windows operating system, use a backslash (not a slash) as folder separator:
\netsettings\proxies.xml

How to send a local file through a REST service?

I am developing a REST web service using WCF and C# (VS 2010). I want to develop an operation like this:
doSomethingWithAFile(String filePath)
so it would be invoked like this:
GET http://my.web.service/endpoint?filePath={filePath}
filePath is a file path in the client (not in the server). So, when invoked, that operation has to send the file pointed by the path to the server so that the server can do some operations with the data contained in the file.
How can I achieve this?
EDIT: As stated in the comment I made, I would set a shared folder in the client, so I send the path and the server reads the file in the folder.
On your server, you will have to have a service with a method that accepts a string input, which you call with the file path from the client application.
You then read/copy/whichever the file from that location, on your server via normal file IO methods.
An example of how to do this you can find below.
The definition of ServerPleaseFetchThisFile naturally depends on what kind of webservice this would be, WCF or IIS web service or self made web service.
public bool ServerPleaseFetchThisFile(string targetPath)
{
// targetPath should enter from the client in format of \\Hostname\Path\to\the\file.txt
return DoSomethingWithAFile(targetPath);
}
private bool DoSomethingWithAFile(string targetFile)
{
bool success = false;
if (string.IsNullOrWhiteSpace(targetFile))
{
throw new ArgumentNullException("targetFile", "The supplied target file is not a valid input.");
}
if (!File.Exists(targetFile))
{
throw new ArgumentNullException("targetFile", "The supplied target file is not a valid file location.");
}
try
{
using (FileStream targetStream = new FileStream(targetFile, FileMode.Open, FileAccess.Read))
{
// Do something with targetStream
success = true;
}
}
catch (SecurityException se)
{
throw new Exception("Security Exception!", se);
// Do something due to indicate Security Exception to the file
// success = false;
}
catch (UnauthorizedAccessException uae)
{
throw new Exception("Unathorized Access!", uae);
// Do something due to indicate Unauthorized Access to the file
// success = false;
}
return success;
}

Copy a file in a new folder

I have a problem coping a file. I need to copy a .db file and put it in a new folder (called "directory",selected previously with FolderPicker).
The code that i have is: (this is for a store app for Windows 8.1)
try{
StorageFile newDB = await StorageFile.GetFileFromPathAsync(directory);
StorageFile originalDB = await StorageFile.GetFileFromPathAsync(Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "AFBIT.db"));
await newDB.CopyAndReplaceAsync(originalDB);
}
catch(Exception ex){
}
I have a exception in neDB, and said "Value does not fall within the expected range."
I dont know another way to copy a file in xaml, if u know what is the problem or another way to do this i llbe very grateful.
I have something similar that I currently use when copying a file CopyFileAsync method I have created see if this can help you in regards to refactoring your code to a working model
public static async Task CopyFileAsync(string sourcePath, string destinationPath)
{
try
{
using (Stream source = File.Open(sourcePath, FileMode.Open))
{
using (Stream destination = File.Create(destinationPath))
{
await source.CopyToAsync(destination);
}
}
}
catch (IOException io)
{
HttpContext.Current.Response.Write(io.Message); //I use this within a web app change to work for your windows app
}
}
I'm not sure what your truly inquiring but I believe your attempting is:
public static bool CopyFile(string source, string destination)
{
if(!File.Exist(source))
return false;
if(string.IsNullOrEmpty(destination))
return false;
try
{
using(var reader = File.Open(source))
using(var writer = File.Create(destination))
reader.CopyTo(writer);
return true;
}
catch(IOException ex) { return false; }
}
Bare in mind this will eat your exception, then return false if it fails at any point for any reason.
That would essentially copy the file, I noticed that your trying to read your local application folder. Be careful, as it often requires Administrator Privileges when it resides in several locations within the Operating System.

Categories