Converting doc to pdf using Interop.Word C# - c#

I'm using C# to convert the .doc to .pdf. The .doc is on the vendor's site. To get the .doc, we have to click on a button which presents us with option to Open, Save, or Cancel. When the user clicks on Save button, it prompts for the location. The user chooses the location in mapped drive, say, S:\Some Folder\abc.doc, and the actual folder location is \\server\\folder\Some Folder. This is where my program comes in to play. I'm using FileSystemWatcher class in c# with Filter set for .doc files. I can see in debug that the file is found. The folder location is hardcoded and saved as the actual folder location mentioned above. The user and the application has full permission to the folder. However, I'm getting FileNotFoundException when I run the program.
This is what I have
WriteToFile("Starting Word application");
Application word = new Application();
object missing = Type.Missing;
var sourcefile = new FileInfo(path);
// check if the created file ends with .doc.
System.Diagnostics.Debug.WriteLine(path);
if (!path.ToLower().EndsWith(".doc"))
{
return "";
}
word.Visible = false;
WriteToFile("Opening doc as read only");
// open readonly
System.Diagnostics.Debug.WriteLine(sourcefile.FullName);
var doc = word.Documents.Open(FileName: sourcefile.FullName, ReadOnly: true);
The strange thing is sourcefile.FullName doesn't show the hard coded server address that path is set to. It shows the file path as S:\Some Folder\abc.doc, which makes no sense to me. What's going on here, and why can't it find the file?

The OnCreate event can fire when the underlying file is still in use/being written to which can cause problems if you immediately try to access it.
The simple solution is to introduce either an arbitrary delay to allow for the file to be closed by the process creating it, or better a loop with a short delay that attempts to access the file, catches the relevant exception should it occur and retries.

My guess is that you use the wrong FileInfo object. Try to generate an new one or use
System.IO.Path.Combine(#"\\server\folder\Some Folder", "sourcefile.Name")
which you could also use to generate your new FileInfo Object. The object which you are using is probably the one of the user dialogue box which is using the mapped drive. You do also have a typo in your location. \\SERVERNAME\\ isn't an UNC path. There should be only two backslashes on the beginning of the string. It should be
#"\\server\folder\Some Folder"
WriteToFile("Starting Word application");
Application word = new Word.Application();
object missing = Type.Missing;
var sourcefile = new System.IO.FileInfo(path);
string SomeShare = #"\\SomeServer\Someshare\Somepath";
System.IO.FileInfo WorkFile = new System.IO.FileInfo(System.IO.Path.Combine(SomeShare, sourcefile.Name));
// check if the created file ends with .doc.
System.Diagnostics.Debug.WriteLine(path);
if (!path.ToLower().EndsWith(".doc"))
{
return "";
}
word.Visible = false;
WriteToFile("Opening doc as read only");
// open readonly
System.Diagnostics.Debug.WriteLine(sourcefile.FullName);
var doc = word.Documents.Open(FileName: WorkFile.FullName, ReadOnly: true);
}
This works just fine for me, it updates the path to the correct UNC pattern. If the file still isn't accesible you should check if you can open it on the workstation using the UNC path you have generated.

Related

How Read File Path From a .dat file then open the program When Pressing The Launch Button?

I have a problem Where I cant make my program automatically read the given file path inside the .dat and be ready to launch the program when pressing launch file without opening openFileDialog and choosing the program every time.
the code im using here is for the user to enter the file path for the first time then create a file path .dat file and it works with now issues.
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string path = Path.Combine(desktop, "LS\\Fail-SafePath.dat");
openFileDialog.InitialDirectory = filePath;
openFileDialog.Filter = " PlayGTAV (*.exe)|PlayGTAV.exe";
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog.FileName;
var fileStream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(fileStream))
{
fileContent = reader.ReadToEnd();
}
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(filePath);
}
After that that i have a start button for it
private void panel21_MouseClick(object sender, MouseEventArgs e)
{
Process.Start(filePath);
}
This works well when the user does it for the first time but now I want it to read that .dat file path automatically without having to ask the user for the file path every single time which I don't know how to do and need help with please.
I was thinking to do it like that: When Pressing the Launch button (After the first time) The Program Checks if the Fail-SafePath.dat Exists if Yes it reads the lines from it and starts the program from the given path without opening OpenFileDialog.
I'm Using Visual Studio, Windows Form.
If it's a file that the application will always need, then something like you mentioned:
I was thinking to do it like that: When Pressing the Launch button (After the first time) The Program Checks if the Fail-SafePath.dat Exists if Yes it reads the lines from it and starts the program from the given path without opening OpenFileDialog.
Could work easily enough. You could have your application look for it in the default location, and if not there, have your user select it.
Another solution could be using something like Application Settings or User Settings, which are values persisted between executions of .NET projects.
Depending on your full application design, you could also have the file path and other settings stored in some database or other data storage. There are a lot of ways to accomplish this.
EDIT: To elaborate further on the Application Settings
The application settings are very easy to read and write to.
You just need to create the ones you want, before trying to use them.
They can be created by:
Open Visual Studio.
In Solution Explorer, expand the Properties node of your project.
Double-click the .settings file in which you want to add a new setting. The default name for this file is Settings.settings.
In the Settings designer, set the Name, Value, Type, and Scope for your setting. Each row represents a single setting.
To read from your settings:
this.FilePath= Properties.Settings.Default.FilePath;
To write to and save the setting:
Properties.Settings.Default.FilePath= Path.GetFullPath("importantFilePath");
Properties.Settings.Default.Save();

C# program open Word Application but not specific Word Document

The code below is supposed to open a .docx file in my windows directory but instead of opening the file it opens only the Word Application. There is no active word document inside, not even a new document. I notice that under the file tab options like "save, save as, print, Share, Export, and Close" are all grayed out and inactive.
using Microsoft.Office;
using Word = Microsoft.Office.Interop.Word;
class Program
{
static void openFile()
{
string myText = #"‪C:\CSharp\WordDocs\MyDoc.docx";
var wordApp = new Word.Application();
wordApp.Visible = true;
wordApp.Activate();
Word.Documents book = wordApp.Documents;
Word.Document docOpens = book.Open(myText);
}
static void Main(string[] args)
{
//Console.WriteLine("Hello World\n");
openFile();
}
}
Running your code but with a path that doesn't exist does indeed opens Word Application with no document inside. But it does throw a very informative exception as follows:
System.Runtime.InteropServices.COMException: 'Sorry, we couldn't find
your file. Was it moved, renamed, or deleted?
(C:\Users\nonexistantuser...\Test.docx)'
You failed to mention this in your question, but you must get an exception.
So my guess is your path is incorrect.
If the path is correct, i.e. the file exists, another possible scenario is not having appropriate read permissions. In that case again it would open an empty Word Application, but that too should throw an exception albeit a different one:
System.Runtime.InteropServices.COMException: 'Word cannot open the document: user does not have access privileges
(C:\Users\NS799\Desktop\Test.docx)'
So please check if the path exists and if it does, if you have appropriate permissions.

Detect when OpenFileDialog returns a downloaded URL/URI

I'm using OpenFileDialog (.Net Framework 4, Windows 10) and I've noticed that it will allow the user to specify a URL as the file name (e.g., http://somewebsite/picture.jpg). This is very useful for my application, so I don't intend to disable it. The way it works is downloading the file into the user's temp directory and returning the temporary file name in the dialog's Filename property. This is nice, except for the fact that the user starts to build up garbage in his/her temp directory.
I would like to tell when a file was downloaded by the OpenFileDialog class (as opposed to a previously existing file), so I can clean up by deleting the file after use. I could check if the file's directory is the temp directory, but that's not very good since the user might have downloaded the file him/herself.
I've tried intercepting the FileOK event and inspect the Filename property to see if it is an HTTP/FTP URI, but despite what the documentation says ("Occurs when the user selects a file name by either clicking the Open button of the OpenFileDialog") it is fired after the file is downloaded, so I don't get access to the URL: the Filename property already has the temporary file name.
EDIT: This is an example of what I'like to do:
Dim dlgOpenFile As New System.Windows.Forms.OpenFileDialog
If dlgOpenFile.ShowDialog(Me) <> Windows.Forms.DialogResult.OK Then Return
''//do some stuff with dlgOpenFile.Filename
If dlgOpenFile.WasAWebResource Then
Dim finfo = New IO.FileInfo(dlgOpenFile.Filename)
finfo.Delete()
End If
In this example, I've imagined a property to dlgOpenFile "WasAWebResource" that would tell me if the file was downloaded or originally local. If it's the first case, I'll delete it.
There's no obvious way to do this, but as a workaround, how about checking where the file lives? It looks like by default this dialog downloads files to the users Temporary Internet Files directory, so you could introduce some code that looks something like this:
FileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
string temporaryInternetFilesDir = Environment.GetFolderPath(System.Environment.SpecialFolder.InternetCache);
if (!string.IsNullOrEmpty(temporaryInternetFilesDir) &&
dialog.FileName.StartsWith(temporaryInternetFilesDir, StringComparison.InvariantCultureIgnoreCase))
{
// the file is in the Temporary Internet Files directory, very good chance it has been downloaded...
}
}

Deploy an application's xml file with installer or create it on the fly if it does not exist

I am having an xml file like:
<CurrentProject>
// Elements like
// last opened project file to reopen it when app starts
// and more global project independend settings
</CurrentProject>
Now I asked myself wether I should deliver this xml file with above empty elements with the installer for my app or should I create this file on the fly on application start if it does not exist else read the values from it.
Consider also that the user could delete this file and that should my application not prevent from working anymore.
What is better and why?
UPDATE:
What I did felt ok for me so I post my code here :) It just creates the xml + structure on the fly with some security checks...
public ProjectService(IProjectDataProvider provider)
{
_provider = provider;
string applicationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
_projectPath = Path.Combine(applicationPath,#"TBM\Settings.XML");
if (!File.Exists(_projectPath))
{
string dirPath = Path.Combine(applicationPath, #"TBM");
if (!Directory.Exists(dirPath))
Directory.CreateDirectory(dirPath);
using (var stream = File.Create(_projectPath))
{
XElement projectElement = new XElement("Project");
projectElement.Add(new XElement("DatabasePath"));
projectElement.Save(stream, SaveOptions.DisableFormatting);
}
}
}
In a similar scenario, I recently went for creating the initial file on the fly. The main reason I chose this was the fact that I wasn't depending on this file being there and being valid. As this was a file that's often read from/written to, there's a chance that it could get corrupted (e.g. if the power is lost while the file is being written).
In my code I attempted to open this file for reading and then read the data. If anywhere during these steps I encountered an error, I simply recreated the file with default values and displayed a corresponding message to the user.

User Permissions issue

I am using Visual Studio C# to parse an XML document for a file location from a local search tool I am using. Specifically I am using c# to query if the user has access to certain files and hide those to which it does not have access. I seem to have files that should return access is true however because not all files are local (IE some are web files without proper names) it is not showing access to files it should be showing access to. The error right now is caused by a url using .aspx?i=573, is there a work around or am I going to have to just remove all of these files... =/
Edit: More info...
I am using right now....
foreach (XmlNode xn in nodeList)
{
string url = xn.InnerText;
//Label1.Text = url;
try
{ using (FileStream fs = File.OpenRead(url)) { }
}
catch { i++; Label2.Text = i.ToString(); Label1.Text = url; }
}
The issue is, when it attempts to open files like the ....aspx?i=573 it puts them in the catch stack. If I attempt to open the file however the file opens just fine. (IE I have read access but because of either the file type or the append of the '?=' in the file name it tosses it into the unreadable stack.
I want everything that is readable either via url or local access to display else it will catch the error files for me.
I'm not sure exactly what you are trying to do, but if you only want the path of a URI, you can easily drop the query string portion like this:
Uri baseUri = new Uri("http://www.domain.com/");
Uri myUri = new Uri(baseUri, "home/default.aspx?i=573");
Console.WriteLine(myUri.AbsolutePath); // ie "home/default.aspx"
You cannot have ? in file names in Windows, but they are valid in URIs (that is why IE can open it, but Windows cannot).
Alternatively, you could just replace the '?' with some other character if you are converting a URL to a filename.
In fact thinking about it now, you could just check to see if your "document" was a URI or not, and if it isn't then try to open the file on the file system. Sounds like you are trying to open any and everything that is supplied, but it wouldn't hurt to performs some checks on the data.
private static bool IsLocalPath(string p)
{
return new Uri(p).IsFile;
}
This is from Check if the path input is URL or Local File it looks like exactly what you are looking for.
FileStream reads and writes local files. "?" is not valid character for local file name.
It looks like you want to open local and remote files. If it is what you are trying to do you should use approapriate metod of downloading for each type - i.e. for HTTP you WebRequest or related classes.
Note: it would be much easier to answer if you'd say: when url is "..." File.OpenRead(url) failes with exception, mesasge "...".

Categories