"Illegal characters in path" error opening service config file - c#

I am trying to read a section of a Windows service configuration file and extract a value (port number). Following code works fine on my local machine but not in any server I tested even though the service is installed in exact same folder structure.
On servers, I get "illegal character in path" error (I added a couple of try-catch to see where it dies and what the message was).
public static string GetCurrentTCPPort()
{
string sTCPPort = "7899";
string ServiceName = "IDC - Tcp Interface Service";
using (ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + ServiceName + "'"))
{
try
{
wmiService.Get();
}
catch (Exception ex)
{
throw new Exception("Died in GetCurrentTCPPort - wmiService.Get()");
}
string ServiceExePath = wmiService["PathName"].ToString();
System.Configuration.Configuration config;
try
{
config = ConfigurationManager.OpenExeConfiguration(ServiceExePath); // FilePath = "C:\\IDC\\APP\\IDC - Tcp Interface Service\\IDC.Service.TcpInterface.exe.config"
string[] saLiteningIPs = config.AppSettings.Settings["TcpServerListenIpAddrsAndPortNos"].Value.Split(','); // "1.2.3.4:7899,1.2.3.5:7899"
if (saLiteningIPs.Length > 0)
{
sTCPPort = saLiteningIPs[0].Split(':')[1];
}
}
catch (Exception ex)
{ // This exception is thrown
string sExcep = string.Format("Died in GetCurrentTCPPort - OpenExeConfiguration(); ServiceExePath: {0}{1}Exception: {2}", ServiceExePath, Environment.NewLine, ex.Message);
throw new Exception(sExcep);
}
}
return sTCPPort;
}
When I run it, I get:
Died in GetCurrentTCPPort - OpenExeConfiguration(); currentserviceExePath: "C:\IDC\APP\IDC - Tcp Interface Service\IDC.Service.TcpInterface.exe"
Exception: An error occurred loading a configuration file: Illegal characters in path.
Screen shot of config file location:
Update - With the fix
public static string GetCurrentTCPPort()
{
string sTCPPort = "7899";
string ServiceName = "IDC - Tcp Interface Service";
using (ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + ServiceName + "'"))
{
try
{
wmiService.Get();
}
catch (Exception ex)
{
throw new Exception("Died in GetCurrentTCPPort - wmiService.Get()");
}
string ServiceExePath = wmiService["PathName"].ToString();
// Added below two lines to fix the issue
List<char> invalidPathChars = Path.GetInvalidPathChars().ToList();
invalidPathChars.ForEach(c => ServiceExePath = ServiceExePath.Replace(c.ToString(), String.Empty));
System.Configuration.Configuration config;
try
{
config = ConfigurationManager.OpenExeConfiguration(ServiceExePath);
string[] saLiteningIPs = config.AppSettings.Settings["TcpServerListenIpAddrsAndPortNos"].Value.Split(',');
if (saLiteningIPs.Length > 0)
{
sTCPPort = saLiteningIPs[0].Split(':')[1];
}
}
catch (Exception ex)
{ // This exception is thrown
string sExcep = string.Format("Died in GetCurrentTCPPort - OpenExeConfiguration(); ServiceExePath: {0}{1}Exception: {2}", ServiceExePath, Environment.NewLine, ex.Message);
throw new Exception(sExcep);
}
}
return sTCPPort;
}

I am not sure why this happens when application is deployed to server and not when I run it locally, even though folder structure and files are exactly same on both; maybe there are invisible characters that are caught on the server but not locally.
Nonetheless, it seems the following modification fixed the issue, in case anyone else runs into this problem.
Right below the line getting the exe path, added these two lines:
string ServiceExePath = wmiService["PathName"].ToString();
List<char> invalidPathChars = Path.GetInvalidPathChars().ToList();
invalidPathChars.ForEach(c => ServiceExePath = ServiceExePath.Replace(c.ToString(), String.Empty));
I have also updated the the question.

Related

Try Catch finally in C# - can I somehow say if exception is thrown go to end, or to start otherwise continue? IWould like to stop and start new file?

sorry if its noob question but I am System Administrator, not developer, but willing to learn more :)
I am writing small console application in C# to verify backup files with MD5 hash. I Actually wrote and it works fine, except it counts error files as good because application works after try-catch even if exception is catch. I will paste part of the code with try catch finally block, my question is can I by any chance in "finally" say "if exception is thrown log filename and exception and go to beginning (start calculating next file) else if stream !=null ....continue Computing hash?
Thank you very much
Ervin
Here is my code in try-catch-finally block
try
{
myHash = null;
myFileMd5 = null;
stream = new FileStream(myFilename, FileMode.Open);
}
catch (FileNotFoundException)
{
File.AppendAllTextAsync(hashList, "The file " + myFilename + " or directory cannot be found." + "\n");
badcounter++;
}
catch (DirectoryNotFoundException)
{
File.AppendAllTextAsync(hashList,"The file " + myFilename + "or directory cannot be found." + "\n");
badcounter++;
}
catch (DriveNotFoundException)
{
File.AppendAllTextAsync(hashList, "The drive specified in 'path' is invalid." + "\n");
badcounter++;
}
catch (PathTooLongException)
{
File.AppendAllTextAsync(hashList, "'path' exceeds the maximum supported path length." + "\n");
badcounter++;
}
catch (UnauthorizedAccessException)
{
File.AppendAllTextAsync(hashList, "You do not have permission to access this file: " + myFilename + "\n");
badcounter++;
}
catch (IOException e) when ((e.HResult & 0x0000FFFF) == 32)
{
File.AppendAllTextAsync(hashList, myFilename + " " + "Sharing violation." + "\n");
badcounter++;
}
catch (IOException e) when ((e.HResult & 0x0000FFFF) == 80)
{
File.AppendAllTextAsync(hashList, myFilename + " " + "The file already exists." + "\n");
badcounter++;
}
catch (IOException e)
{
File.AppendAllTextAsync(hashList, $"An exception occurred:\nError code: " + $"{e.HResult & 0x0000FFFF}\nMessage: {e.Message}" + myFilename + "\n");
badcounter++;
}
finally
{
if (stream != null)
{
myFileMd5 = md5.ComputeHash(stream);
stream.Close();
}
}
return (myFileMd5);
}
Usually it is not a good practice to use the finally block to continue your processing logic. The finally block is executed in any case even if there is an exception catched or not. So your logic inside the finally block needs to be protected by the stream open failure and, not probable, but what if the same ComputeHash throws an exception?
So, I would move the logic inside the try block. If there is an exception the ComputeHash is not executed anyway and with the using statement you don't need to close the stream.
// This class will be used to comunicate back to the caller the result of the hash
// Try to avoid using too many global variables if possible. They make your code very
// unmaintenable.
public class ComputeStatus
{
public string errorText {get;set;} = "";
public byte[] hash {get;set;}
}
public ComputeStatus MyComputeHash(string filename)
{
ComputeStatus status = new ComputeStatus();
try
{
using var stream = new FileStream(myFilename, FileMode.Open);
status.hash = md5.ComputeHash(stream);
return status;
}
catch (FileNotFoundException)
{
string error = $"The file {myFilename} or directory cannot be found.";
// This can now be moved outside the method as well and done just one
// time by the caller in case of error text.
// File.AppendAllTextAsync(hashList, error);
status.errorText = error;
}
..... all the other catch blocks follow
return status;
}
Now the calling code just need to check if the ComputeStatus instance returned contains an error message or not. Let the error counting be handled at that level.
Something like this should work:
private void button1_Click(object sender, EventArgs e)
{
List<string> files = new List<string>();
files.Add(#"C:\file1.txt");
files.Add(#"C:\file2.txt");
files.Add(#"C:\file3.txt");
foreach(string myFilename in files)
{
//... your existing code...
}
}

Process Cannot Access the File Attachment

I have the following code (or the equivalent thereof):
var provider = new System.Net.Http.MultipartFormDataStreamProvider([...]);
try
{
if (provider.FileData.Count != 0)
{
foreach (System.Net.Http.MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
AddAttachment(file.LocalFileName, file.Headers.ContentDisposition.FileName.Replace("\"", ""));
if (attachmentPaths.Length != 0)
{
attachmentPaths += ";";
}
attachmentPaths += file.Headers.ContentDisposition.Name.Replace("\"", "");
}
}
}
catch (Exception ex)
{ ... }
...
public void AddAttachment(string attachmentFileName, string attachmentName)
{
var AttachmentList = new List<System.Net.Mail.Attachment>();
System.Net.Mail.Attachment newAttachment = new System.Net.Mail.Attachment(attachmentFileName);
newAttachment.Name = attachmentName;
AttachmentList.Add(newAttachment);
}
And I'm getting the "Process cannot access the file ... because it is being used by another process" error. I'd just like to know where my application could be getting the error. I can't tell where in here it is actually trying to access the file. My best guess is in the Attachment constructor, but I'm really not sure.
I was able to figure out a way to test it in a debugger. And the answer was yes, the System.Net.Mail.Attachment constructor is what was trying to access the file.

C# try and catch

I've just signed up to the website so I have probably put this wrong. Anyways, I am trying to use the try and catch in C# to catch my file if it not found. Here is my code for it at the moment. To repeat myself, I want the program to read the file in, as it does- but then if the file is not found, I would like it to give an error saying "cannot find the file" or something along those lines, not simply just crash. (I've just started learning C#)
Thanks for the help!
string file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
try
{
file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
}
catch
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
//ARRAY for string lines
string[] Line = new string[6];
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
You should read the file inside the try catch and catch FileNotFoundException, like this:
var file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
string[] lines;
try
{
lines = File.ReadAllLines(file);
}
catch (FileNotFoundException exnotfound)
{
// file not found exception
}
catch (Exception ex)
{
// handle other exceptions
}
You need to put the code that is error prone inside of try block.
try
{
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
}
catch(Exception ex)
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
BTW, you can handle this situation by checking if file exists first using File.Exists method.There is no need to catch exception for that.
Try catch just doesn't work like this.
You are trying to catch a line of code that changes a string and doesn't change a file, so the file doesn't need to exist, so it will never throw an exception (in your case), and it will never catch it.
You should surround code that can go wrong: File.ReadLines
Your code will become like this:
string file = #"C:\Users\Henry\Desktop\Assessments\Programming and data structures\grades_multiple.txt";
//can go wrong
try
{
//ARRAY for string lines
string[] Line = new string[6];
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
}
//File.ReadLines is null
catch
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
I also think it is even better practice to check it with an if statement, instead of catching it when it goes wrong:
//if file exists
if(File.Exists(file))
{
//ARRAY for string lines
string[] Line = new string[6];
Line[0] = File.ReadLines(file).Skip(1).Take(1).First();
}
//File does not exist
else
{
Console.WriteLine("Could not find the file - grades_multiple.txt");
}
When ever possible you should try to avoid throwing exceptions just to display a message to the user or for conditions that can be easily tested. This is primarily a performance consideration as throwing an exception is expensive. Additionally performance can be impacted by loading the entire file into memory unless you know that the file is relatively small..
Here is a quick and raw example on how you may test for the condition and handle it.
void Main()
{
var filePath ="C:\\TEST.DAT";
if(!File.Exists(filePath)){ DisplayFileNotFoundError(filePath); }
try
{
var lines = GetFileLines(filePath);
if(lines == null) { DisplayFileNotFoundError(filePath);}
// do work with lines;
}
catch (Exception ex)
{
DisplayFileReadException(ex);
}
}
void DisplayErrorMessageToUser(string filePath)
{
Console.WriteLine("The file does not exist");
}
void DisplayFileReadException(Exception ex){
Console.WriteLine(ex.Message);
}
string[] GetFileLines(string filePath){
if(!File.Exists(filePath)){ return null; }
string[] lines;
try
{
lines = File.ReadLines(filePath);
return lines;
}
catch (FileNotFoundException fnf){
Trace.WriteLine(fnf.Message);
return null;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw ex;
}
}
Performance Test, FileNotFoundException vs File.Exists
void Main()
{
int max = 100000;
long[] feSampling = new long[max];
long[] exSampling = new long[max];
String pathRoot ="C:\\MISSINGFILE.TXT";
String path = null;
Stopwatch sw = new Stopwatch();
for (int i = 0; i < max; i++)
{
path = pathRoot + i.ToString();
sw.Start();
File.Exists(pathRoot);
sw.Stop();
feSampling[i] = sw.ElapsedTicks;
sw.Reset();
}
StreamReader sr = null;
sw.Reset();
for (int i = 0; i < max; i++)
{
path = pathRoot + i.ToString();
try
{
sw.Start();
sr = File.OpenText(path);
}
catch (FileNotFoundException)
{
sw.Stop();
exSampling[i] = sw.ElapsedTicks;
sw.Reset();
if(sr != null) { sr.Dispose();}
}
}
Console.WriteLine("Total Samplings Per Case: {0}", max);
Console.WriteLine("File.Exists (Ticsk) - Min: {0}, Max: {1}, Mean: {2}", feSampling.Min(), feSampling.Max(), feSampling.Average ());
Console.WriteLine("FileNotFoundException (Ticks) - Min: {0}, Max: {1}, Mean: {2}", exSampling.Min(), exSampling.Max(), exSampling.Average ());
}

Unauthoriezed Access Exception

i have a cloud database server like application on my computer that i'm hosting my game on. However, every time an user tries to save data i get an UnauthorizedAccessException.
Im running it by admin and i dont have any specias right in my folder so i have no idea what's the problem.
Here's my code:
public const string root = "D:/DATABASE/";
public static void WriteData(string playername, string type, string data)
{
if (!Directory.Exists("D:/DATABASE/" + playername))
{
Directory.CreateDirectory("D:/DATABASE/" + playername);
Directory.CreateDirectory("D:/DATABASE/" + playername + "/weapons");
}
if (type != "Weapon")
{
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/" + type + ".sav"))
{
sw.WriteLine(data);
}
}
else
{
string[] dat = data.Split('%');
using (StreamWriter sw = new StreamWriter("D:/DATABASE/" + playername + "/weapons/" + dat[0] + ".gfa"))
{
string[] lines = dat[1].Split('#');
foreach (string cline in lines)
{
sw.WriteLine(cline);
}
}
}
}
public static string ReadLoadout(string playername)
{
string output = "";
string[] items = new string[2];
using (StreamReader sr = new StreamReader(root + playername + "/loadout.gfl"))
{
items[0] = sr.ReadLine();
items[1] = sr.ReadLine();
}
int c = 0;
foreach (string citem in items)
{
if (c > 0) output += "$";
output += citem + "%" + GetCompressedWeaponFile(playername, citem);
c++;
}
return output;
}
public static string GetCompressedWeaponFile(string playerName, string weaponName)
{
string output = "";
using (StreamReader sr = new StreamReader(root + playerName + "/weapons/" + weaponName))
{
string line = " ";
int c = 0;
while (line != null)
{
line = sr.ReadLine();
if (line != null)
{
if (c > 0) output += "#";
output += line;
}
c++;
}
}
return output;
}
public static void RegisterNewUser(string username, string password, string email)
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
public static void EditLoadout(string username, string items)
{
File.WriteAllLines(root + username + "/loadout.gfl",items.Split('#'));
}
It is difficult to provide specific help without more information. Here are a few of troubleshooting suggestions:
1) Try running your code on a different machine. Specifically your development computer. Do you still have the same error? If not, then there is indeed a permission problem.
2) Have you tried checking the stack trace of the exception?
When you run the application on your own computer, try using the IDE to display the exception. Yes, the problem may ultimately be in a low-level class, but you should be able to break on the error and go back in the call stack to see which method in your code is actually throwing the error.
3) Check the actual exception, even for a system-level exception.
Chances are, if you are able to debug this in the IDE, that you will see property information that will give you a hint. Is it in a directory method or a file write method? Check additional properties. Somewhere it might give you the text of the path (assuming it's a file issue) that it failed on that that could help narrow things down too.
4) Add Exception handling to your code
This is a good rule of thumb, and you should really do this anyway to make a stronger program. Regardless of who's method you are calling (yours, someone else's, or a system method) you need to determine where it should be handled.
For example, in your code, in the RegisterNewUser() method, consider something like:
public static void RegisterNewUser(string username, string password, string email)
{
try
{
string udir = root + username;
Directory.CreateDirectory(udir);
Directory.CreateDirectory(udir + "/weapons");
Directory.CreateDirectory(udir + "/loadouts");
File.WriteAllText(udir + "/password.sav", password);
File.WriteAllText(udir + "/level.sav", "1");
File.WriteAllText(udir + "/money.sav", "1000");
File.WriteAllText(udir + "/email.sav", email);
File.WriteAllText(udir + "/loadout.gfl", "");
using (StreamWriter sw = new StreamWriter(root + "emails.txt", true))
{
sw.WriteLine(email);
}
Email.Send(email, "New Account Registration", string.Format(mailTemplate, username, password));
}
catch (Exception ex)
{
// Create a method to display or log the exception, with it's own error handler
LogAndDisplayExceptions(ex);
// Send the user a message that we failed to add them. Put this in it's own try-catch block
// ideally, for readability, in it's own method.
try
{
Email.Send(email, "Failed to register", "An error occurred while trying to add your account.");
}
catch (Exception exNested)
{
LogAndDisplayExceptions(exNested);
}
}
}
5) Add a "crash-and-burn" exception handler to "main"
In the method that is your "top method" (it's hard to tell in the snippet you provided since there are few methods that would attempt to write to the disk) you could wrap your code in a try - catch block and print the exception or write it to disk.
If you have having trouble writing the exception to disk, I would suggest creating an error file first, make sure that the user account that is running the program can write to it, and then in the catch block open the file for APPEND. This should make it easier to get to the error text.
6) When all else fails, use the Debug class or Console class to write the traditional "I made it to line x."
While this will not solve your problem, it should help you get more information that will provide more insight into where your code is causing an error.

Outlook returns error: The messaging interface has returned an unknown error

I am having some problems with a piece of code, I am trying to import data from a source (at this time an access database) into a custom form but i keep getting the above error.
When i use a VBscript inside the source database all contacts import correctly.
When i repair the PST it still gives this error.
When i add a delay of 450 ms. the error also occurs but later on in the process.
Having Outlook opened or closed does not matter.
I am using the following method
string[] arrFolders = strFolders.Split('\\');
Outlook.Application app = null;
Outlook.MAPIFolder folder = null;
try {
app = new Outlook.Application();
folder = app.GetNamespace("MAPI").Folders[arrFolders[0]];
} catch (Exception ex) {
writeLogLine("Error creating Outlook instance: " + ex.Message);
MessageBox.Show("Error creating Outlook instance\r\n" + ex.Message);
intErrorCount++;
blnHasErrors = true;
blnAbort = true;
}
try {
for (int i = 1; i < arrFolders.Length; i++) {
folder = folder.Folders[arrFolders[i]];
}
} catch (Exception ex) {
writeLogLine("Error navigating to DRM folder: " + ex.Message);
MessageBox.Show("Error navigating to DRM folder\r\n" + ex.Message);
intErrorCount++;
blnHasErrors = true;
blnAbort = true;
}
setProgressbarMaximum(dtResults.Rows.Count);
setProgressbarMode(ProgressBarStyle.Continuous);
//int intRowCount = 0;
foreach (DataRow drItem in dtResults.Rows) {
if (strDRMType == "Contact") {
try {
Outlook.ContactItem x = (Outlook.ContactItem)folder.Items.Add("IPM.Contact." + strFormName);
for (int i = 0; i < arrMappings.GetLength(0); i++) {
if (arrMappings[i, 1] != null && drItem[arrMappings[i, 0]].ToString() != "") {
x.UserProperties[arrMappings[i, 1]].Value = drItem[arrMappings[i, 0]].ToString();
}
}
x.Save();
} catch (Exception ex) {
writeLogLine("Error importing contact: " + ex.Message);
intErrorCount++;
blnHasErrors = true;
}
}
as i said, when i loop the code it will throw exceptions after 100 to 200 contacts, when i add a delay it will get to contact 400/500 before failing.
This code is supposed to be for a generic import tool for this specific form so there is no need for hardcoding the source column names to the form fields in the import code.
Any help is appreciated.
I'm assuming this is not an Outlook add-in, since you say it doesn't matter if OL is open or closed, right?
One thing you may want to do is ensure you are releasing the COM objects once you are done with them, using System.Runtime.InteropServices.Marshal.ReleaseComObject(...). Also, when you use dot notation like "namespace.Folders[..].Name" you are actually leaking a reference to both the Folders collection object and a Folder object.
When you do folders.Items.Add(...) inside a loop, that leaks a lot of objects.
So, clean up your COM references first, and see how that affects your situation.
Here's how I typically use COM objects:
MyComLib.Foo foo = null;
try
{
foo = new MyComLib.Foo();
foo.DoSomething();
} catch(COMException exc)
{
// handle error, or rethrow
}
finally
{
if(foo != null)
Marshal.ReleaseComObject(foo);
}

Categories

Resources