C# Directory.CreateDirectory stop working - c#

I have a C# application, it works properly on many pc, laptop. But, I copied to my customer's pc (4TB HDD - windows 10 Home Edition), my application stop working!
I try to put MessageBox.Show() in some line to find where is broken. And it stop at Directory.CreateDirectory(#"D:\\mypath")
The PC have D: and I don't know why it broken.
Here is my code:
string now = DateTime.Now.ToString("HH_mm_ss");
string strDuongDan;
strDuongDan = #"D:\VideoLuuTru\" + DateTime.Now.Month.ToString() + "_" + DateTime.Now.Year.ToString();
if (!Directory.Exists(strDuongDan))
Directory.CreateDirectory(strDuongDan);
string strDuongDan2 = strDuongDan + "\\" + DateTime.Now.ToString("dd"); ;
if (!Directory.Exists(strDuongDan2))
Directory.CreateDirectory(strDuongDan2);
How can I trace exactly my errors, and is there anything wrong from my code? It running perfectly in many PCs but with this PC, it broken.
Is my problem related to large hard drive space?
My customer's IT staff installed my app on his laptop (Windows 10 Home) and installed the same windows to this pc. My app run on His laptop without errors
Thanks you!
EDIT:
My Function and my errors:
Function:
public void makevideo()
{
string now = DateTime.Now.ToString("HH_mm_ss");
string strDuongDan;
strDuongDan = #"D:\VideoLuuTru\" + DateTime.Now.Month.ToString() + "_" + DateTime.Now.Year.ToString();
if (!Directory.Exists(strDuongDan))
Directory.CreateDirectory(strDuongDan);
string strDuongDan2 = strDuongDan + "\\" + DateTime.Now.ToString("dd"); ;
if (!Directory.Exists(strDuongDan2))
Directory.CreateDirectory(strDuongDan2);
}
Call function
ThreadStart childref = new ThreadStart(() => makevideo());
Thread childThread = new Thread(childref);
try { childThread.Start(); }
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Errors:
**
Application: camera.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException at camera.Form1.makevideo() at camera.Form1.<Form1_Load>b__6_0() at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object) at
System.Threading.ThreadHelper.ThreadStart()
**

I don't usually recommend catching errors like this
However you can use a logger, or if you really must you can just push the error into a MessageBox. at least you will know the exception
Alternatively you could check the event log viewer, if your application crashes it will give you clues as to what happened.
Lastly, most likely this is a permission thing, but who knows. Make sure your client has given the appropriate permissions to that directory or run your application at an elevated privilege
try
{
// Note you don't need to check if a directory exists before you create it
// it does it for you
// if (!Directory.Exists(strDuongDan))
Directory.CreateDirectory(strDuongDan);
}
catch(Exception ex)
{
// log here
// or
MessageBox.Show("Error : " + ex.Message)
}
Directory.CreateDirectory Method (String)
Exceptions
IOException
The directory specified by path is a file.
The network name is not known.
UnauthorizedAccessException
The caller does not have the required permission.
ArgumentException
path is a zero-length string, contains only white space, or contains one or more invalid characters. You can query for invalid
characters by using the GetInvalidPathChars method.
path is prefixed with, or contains, only a colon character (:).
ArgumentNullException
path is null.
PathTooLongException
The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be
less than 248 characters and file names must be less than 260
characters.
DirectoryNotFoundException
The specified path is invalid (for example, it is on an unmapped drive).
NotSupportedException
path contains a colon character (:) that is not part of a drive label ("C:\").

Related

.NET Console App throws error when scheduled. Runs fine when executed manually

So I decided to make a console application to automate some repetitive jobs that I generally do on a daily basis. The objective is to move some files to a network location as backup. The application runs fine when executed manually. But when scheduled, it throws an error. On examining the log file (to which all program output is mapped), I found the following stack trace and exception message:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)
at System.IO.File.Copy(String sourceFileName, String destFileName)
at automateDump.Program.Main(String[] args) in D:\software\automateDump\Program.cs:line 78
The user name or password is incorrect.
I'm using the File.Copy(src, dest) method in System.IO.
And for context, the file paths are:
Source: D:\u01\test.file. Destination: \\NetDrive\test.file
Any help would be appreciated.
EDIT 1
Code:
if (File.Exists(movePath + et1))
{
Console.WriteLine($"Copying {et1} to network location. Size - {sizeInMegaBytes(new FileInfo(movePath + et1).Length)}");
File.Copy(movePath + et1, networkPath + et1);
Console.WriteLine("Done Copying");
}
movePath and networkPath are source and destination paths, and et1 is the file.
sizeInMegaBytes() is a utility function that I wrote. It's irrelevant in this context.
EDIT 2
Exception Handling code:
catch (Exception ex)
{
using (logger = File.AppendText(#"D:\u01\logs.txt"))
{
logger.WriteLine($"{ex.StackTrace} \n {ex.Message}");
}
}
Theory: you have not checked the option to save the user password for the task:
Note the explanatory text: using a UNC path means you are trying to access a non-local resource!

Directory.Exists throws Object not set to an instance of an object exception

I am completely stumped on this one, I have a static class attempting to detect if a directory exists, but for some reason, it throws the following error:
Program.Main encountered an error: Object reference not set to an instance of an object. Stack trace: at csv.prepareCSVData() in path/csv.cs:line 21
at RLCSVTools.Program.Main(String[] args) in path\Program.cs:line 31
This is the code that produces that error in csv.cs.prepareCSVData:
ConfigurationSync.logDebugMessage(logMessageType.warning, "CSV class Dir: " + exportPath);
//this log works and reveals exportPath has been populated
if (Directory.Exists(exportPath) == false)
//breaks here regardless of dir existing or not
{
ConfigurationSync.logDebugMessage(logMessageType.warning, "Recreating the directory: " + exportPath);
// I have never seen this log run
Directory.CreateDirectory(exportPath);
}
I have added some comments in the code to show at exactly what line the error occurs.
All members of this class, including the class, are static. public static class csv
Has anyone experienced anything like this? I can't seem to find a solution.
So lets look at the documentation
Directory.Exists(String) Method
Doesn't throw any exception
CreateDirectory(String)
Creates all directories and subdirectories in the specified path
unless they already exist.
Exceptions
IOException
The directory specified by path is a file.
-or-
The network name is not known.
UnauthorizedAccessException
The caller does not have the required permission.
ArgumentException
path is a zero-length string, contains only white space, or contains one or more invalid characters. You can query for invalid
characters by using the GetInvalidPathChars() method.
-or-
path is prefixed with, or contains, only a colon character (:).
ArgumentNullException
path is null.
PathTooLongException
The specified path, file name, or both exceed the system-defined maximum length.
DirectoryNotFoundException
The specified path is invalid (for example, it is on an unmapped drive).
NotSupportedException
path contains a colon character (:) that is not part of a drive label ("C:\").
Its clear that CreateDirectory(String) is not your problem
So by deducation the only obvious issue here is exportPath is null
For which this is relevant
What is a NullReferenceException, and how do I fix it?
if exportPath is not null, then you need to debug your application, something is not what it seems

How to save data to network path on .NET?

I'm really struggling with saving data to my local network NAS (a Synology DS214 if that matters).
I need to store some files in my network folders after creating them in another part of my program, but I haven't been able to handle the authentication/permissions properly.
My code atm is this:
WrapperImpersonationContext WIContext =
new WrapperImpersonationContext("\\\\DiskStation", "admin", "admin");
try
{
WIContext.Enter();
// code to select the final path simplified.
string fileName = "file.txt";
string originalPath = Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments);
originalPath= Path.Combine(new string[] {originalPath, fileName});
string finalPath = "\\\\DiskStation\\Virtual\\DestFolder";
if (!Directory.Exists(finalPath))
{
// This goes well for whatever reason
Directory.CreateDirectory(finalPath);
}
finalPath = Path.Combine(new string[] {finalPath, fileName});
// This fails for wrong username/password
File.Move(originalPath, finalPath);
} catch (Exception ex)
{
// Exception showing simplified here
MessageBox.Show(ex.ToString());
throw;
} finally
{
WIContext.Leave();
}
The code used for the WrapperImpersonationContext I found here:
WindowsImpersonationContext made easy
As written in my code when I try to move the file I get an UnauthorizedAccessException: Access to the path is denied. I also tried to create a new file in the network folder with the same results.
While looking at the Michiel Vanotegem's code linked above, I discovered that I get an authentication error calling the LogonUser function (error code 1326 that gets me a Win32Exception (0x80004005): The user name or password is incorrect).
I tried to use the WNetUseConnection function looking at this and this pages but while I get no error from the function (after substituting it in the Michiel code), when I try to move the file I get the same UnauthorizedAccessException: Access to the path is denied.
I also tried to fiddle with the domain passed to the Impersonation Wrapper but I couldn't seem to make it work. I feel like I'm missing something... Can someone kindly point me to the right direction or help me with this issue?
Ty all who contributes in advance.
Edit 15/12/2017 11:52: I discovered that if I try to rerun the LogonUser function immediately after the first error I get a different exception (error 87 Win32Exception (0x80004005): The parameter is incorrect)
I followed on #LennartStoop suggestion, so I enclosed my code in a using block instead of a try finally using the code I borrowed from this answer:
using (NetworkConnection netConn =
new NetworkConnection("\\\\DiskStation", new NetworkCredential("admin", "admin")))
{
// My code here
}
Using this I've been able to establish a connection the network folder and perform all the IO operation I needed so ty very much for the tip Lennart :)

C#: ArgumentException when calling System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()

I am in a bit of a strange situation. I have been given a fairly large suite of PowerShell modules and functions, and it is my job to tie these together into an executable. The requirements state that this must be a single, standalone executable with no installer and .net 3.5 may be the only dependency. The Windows Management Framework is not an exception and cannot be assumed to exist on the machine. To get around this, I have added System.Management.Automation as a reference and made it an embedded resource, along with all of the PowerShell module files, and load them from reflection at runtime. This seems to work OK, but I have some errors that I cannot seem to figure out and think it might have something to do with this system.
So Here is the issue: When I start to initialize things to run the PowerShell command, I get a strange error that I can't seem to control.
Here is the code:
public static void RunCommand(object objcommand)
{
//create a script block for toolbox once, get the embeded resource, convert from byte array to string, make scriptblock from string
ScriptBlock toolbox = System.Management.Automation.ScriptBlock.Create(System.Text.Encoding.Default.GetString(Properties.Resources.toolbox));
string command = (string)objcommand;
//get the module name
string modname = options.Commands[command]["module"];
//get the module from the embeded resources, convert to string, convert to scriptblock
var module = System.Management.Automation.ScriptBlock.Create(new System.IO.StreamReader(myasm.GetManifestResourceStream("piramids.Resources." + modname + ".psm1")).ReadToEnd());
using (var powerShell = PowerShell.Create())
{
System.Management.Automation.Runspaces.Runspace rs = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(); //i think this line triggers the exception
rs.Open();
powerShell.Runspace = rs;
//make the necesary powershell modules of the command availible
powerShell.AddCommand("new-module").AddParameter("ScriptBlock", toolbox).Invoke();
powerShell.AddCommand("new-module").AddParameter("ScriptBlock", module).Invoke();
//if inethistory, make dlls availible
if (modname.Equals("inethistory"))
{
powerShell.AddCommand("add-type").AddParameter("Path", sqldll).Invoke();
powerShell.AddCommand("add-type").AddParameter("Path", esentdll).Invoke();
}
ICollection<PSObject> output = new List<PSObject>(0);
try {
output = powerShell.AddCommand("get-" + command).AddCommand(format).AddCommand("out-string").Invoke();//pipeline.Invoke();
} catch (System.Management.Automation.RuntimeException e)
{
Console.Error.WriteLine("An Error occured while executing '" + command + "'");
Console.Error.WriteLine(e.Message);
}
//do stuff with the results
and here is the stack trace:
Unhandled Exception: System.ArgumentException: The path is not of a legal form.
at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
at System.IO.Path.NormalizePath(String path, Boolean fullCheck)
at System.IO.Path.GetFullPathInternal(String path)
at System.IO.Path.GetFullPath(String path)
at System.Diagnostics.FileVersionInfo.GetFullPathWithAssert(String fileName)
at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName)
at System.Management.Automation.PSVersionInfo.GetPSVersionTable()
at System.Management.Automation.PSVersionInfo.get_PSVersion()
at Microsoft.PowerShell.DefaultHost..ctor(CultureInfo currentCulture, CultureInfo currentUICulture)
at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()
at piramids.Program.RunCommand(Object objcommand)
at piramids.Program.Main(String[] args)
I believe this line is where the exception occurs:
System.Management.Automation.Runspaces.Runspace rs = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
The CreateRunspace method is not documented to throw any exceptions, and this exception comes from so many levels down that I have no idea what kind of path this thing is checking, as I never called a function that asked for a path.
I am stumped. Does anyone have any idea what may be causing this?
EDIT: After some digging, here is what I found. PSVersionTable is a static field of VersionInfo, so the static constructor is called the first time get called for this field. The static constructor calls an internal method called GetBuildVersion, which tries to get the assembly location of PSVersionInfo. According to This documentation page:
If the assembly is loaded from a byte array, such as when using the Load(Byte[]) method overload, the value returned is an empty string ("").
I am loading from a byte array, so this will be an empty string. But then GetBuildVersion uses this location to do FileVersionInfo.GetVersionInfo which verifies the path with Path.GetFullPath. According to This documentation page:
ArgumentException:
the path is a zero-length string
So there is the problem. Now the question is, How do I assign a location to an assembly loaded from a byte array? May God have mercy on me.
I'm not at all convinced this is even remotely reasonable to expect PowerShell code to work without installing WMF. If I were approached with that request I would respond that all code must be rebuilt in another .NET language (that is, C#).
Still, perhaps you can see if it's this static method. You'll have to de-PowerShell the code I'm afraid. The PowerShell accelerator is just a simple way for me to get at the System.Management.Automation assembly. The class is not public and the method on the class is not public either.
$verInfo = [PowerShell].Assembly.GetTypes() | Where-Object Name -eq 'PSVersionInfo'
$verInfo.GetMethod('get_PSVersion', [System.Reflection.BindingFlags]'NonPublic,Static').Invoke($null, [System.Reflection.BindingFlags]'NonPublic,Static', $null, #(), $null)
Chris

Check if directory exists on Network Drive

I'm trying to detect if the directory exists, but in this particular situation my directory is a network location.
I used VB.NET's My.Computer.FileSystem.DirectoryExists(PATH) and the more general System.IO.Directory.Exists(PATH), and in both cases, the system response is false.
I checked and the PATH exists, I can view it in MyComputer Folder.
If I debug the program, and watch the My.Computer.FileSystem.Drives variable, the network location does not appear in that list.
UPDATE: I checked and in Windows XP the Response is True, but not in Windows 7.
UPDATE2: I tested both proposed solutions but I still have the same problem, on the image below you will see that I can access using Explorer but my program cannot.
The GetUNCPath function returns a valid path (no errors), but Directory.Exists stil returns false.
I also tried with the UNC path "\\Server\Images"; same result.
UPDATE3: If I cannot link with a network drive, how can I link to UNC path directly?. I discovered that if i run VS in normal mode, it works, but my software must run in administrator mode. So, there is any way to check the existence of a network directory as administrator?
If UAC is turned on, mapped network drives only exist "by default" in the session they are mapped: Normal or elevated. If you map a network drive from explorer, then run VS as admin, the drive will not be there.
You need to enable what MS calls "linked connections":
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System: EnableLinkedConnections (REG_DWORD) = 0x1
Background Information about "two logon sessions" with UAC: http://support.microsoft.com/kb/937624/en-us
When you use System.IO.Directory.Exists, it only lets you know that it couldn't find the directory, but this could be because the directory doesn't actually exist or because the user doesn't have sufficient access rights to the directory.
In order to resolve this, we add a secondary test after Directory.Exists fails to obtain the real reason for the directory's absence and we have wrapped this into a global method that is used in place of the standard Directory.Exists method:
''' <summary>
''' This method tests to ensure that a directory actually does exist. If it does not, the reason for its
''' absence will attempt to be determined and returned. The standard Directory.Exists does not raise
''' any exceptions, which makes it impossible to determine why the request fails.
''' </summary>
''' <param name="sDirectory"></param>
''' <param name="sError"></param>
''' <param name="fActuallyDoesntExist">This is set to true when an error is not encountered while trying to verify the directory's existence. This means that
''' we have access to the location the directory is supposed to be, but it simply doesn't exist. If this is false and the directory doesn't exist, then
''' this means that an error, such as a security error, was encountered while trying to verify the directory's existence.</param>
Public Function DirectoryExists(ByVal sDirectory As String, ByRef sError As String, Optional ByRef fActuallyDoesntExist As Boolean = False) As Boolean
' Exceptions are partially handled by the caller
If Not IO.Directory.Exists(sDirectory) Then
Try
Dim dtCreated As Date
' Attempt to retrieve the creation time for the directory.
' This will usually throw an exception with the complaint (such as user logon failure)
dtCreated = Directory.GetCreationTime(sDirectory)
' Indicate that the directory really doesn't exist
fActuallyDoesntExist = True
' If an exception does not get thrown, the time that is returned is actually for the parent directory,
' so there is no issue accessing the folder, it just doesn't exist.
sError = "The directory does not exist"
Catch theException As Exception
' Let the caller know the error that was encountered
sError = theException.Message
End Try
Return False
Else
Return True
End If
End Function
public static class MappedDriveResolver
{
[DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int WNetGetConnection([MarshalAs(UnmanagedType.LPTStr)] string localName, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder remoteName, ref int length);
public static string GetUNCPath(string originalPath)
{
StringBuilder sb = new StringBuilder(512);
int size = sb.Capacity;
// look for the {LETTER}: combination ...
if (originalPath.Length > 2 && originalPath[1] == ':')
{
// don't use char.IsLetter here - as that can be misleading
// the only valid drive letters are a-z && A-Z.
char c = originalPath[0];
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
int error = WNetGetConnection(originalPath.Substring(0, 2), sb, ref size);
if (error == 0)
{
DirectoryInfo dir = new DirectoryInfo(originalPath);
string path = Path.GetFullPath(originalPath).Substring(Path.GetPathRoot(originalPath).Length);
return Path.Combine(sb.ToString().TrimEnd(), path);
}
}
}
return originalPath;
}
}
To use it, pass in a Network folder path, convert to UNC folder path and see if the folder exists:
File.Exists(MappedDriveResolver.GetUNCPath(filePath));
Edit:
I saw your second edit and the only difference (in my Windows7) when I view a network drive I see Computer > Images (\\xyzServer). Is your PC's name Equipo? is that team in spanish? is that your PC? I tried to reproduce your problem but it works for me:
Adding to this, I needed to do an 'Exists' check on network shares that could listed, but the account did not have permission to access, so Directory.Exists would return False.
Various solutions posted did not work for me, so here is my own:
public static bool DirectoryVisible(string path)
{
try
{
Directory.GetAccessControl(path);
return true;
}
catch (UnauthorizedAccessException)
{
return true;
}
catch
{
return false;
}
}

Categories

Resources