I am trying to programmatically delete a broken symbolic link and replace it with one that is has a valid target by the same name. However, by the time CreateSymbolicLink() executes, File.Delete() still has not actually deleted the file (I have verified the file still exists after File.Delete() executes, with no errors or warnings).
When the program finishes executing, only then does the file actually get deleted. What the heck? This is blocking the symbolic link from being created. Any ideas what to do?
private static string replaceSymbolicLink(string linkPath, string newTargetPath)
{
Boolean linkIsFile = File.Exists(linkPath);
Boolean linkIsDir = Directory.Exists(linkPath);
// Create a replacement of the same name and link type with the new target
string newTargetPathDOS = getAbsPathFromPath(newTargetPath);
Boolean targetIsFile = File.Exists(newTargetPathDOS);
Boolean targetIsDir = Directory.Exists(newTargetPathDOS);
if (targetIsFile || targetIsDir)
{
if (linkIsFile)
{
File.Delete(linkPath);
Console.WriteLine(File.Exists(linkPath));
}
else
{
Directory.Delete(linkPath);
}
SymbolicLink type;
if (targetIsFile)
{
type = SymbolicLink.File;
}
else
{
type = SymbolicLink.Directory;
}
CreateSymbolicLink(linkPath, newTargetPath, type);
return getGuidFromPath(linkPath);
}
return null;
}
On Windows deletions are not immediate. Files are being marked as deleted and actually disappear when the last handle is being closed. Normally, this mechanism is not visible since most files are opened with sharing rights that prevent deletion. This causes deletes to either fail or go through immediately.
FileShare.Delete allows to keep a file (a FileStream) open while it is being deleted. This can be surprising behavior if you have never heard of this before.
So you probably have the file still open or some other process has.
Related
I want to open an OBJ file in Unity using C# during runtime when I press L. However, the file dialog always opens twice. After I selected the first file, I get a new dialog. Whatever file I select the first and second time, both files are opened and displayed.
I have:
void Update ()
{
if (Input.GetKeyDown(KeyCode.L)) {
LoadObj();
//StartCoroutine(ExecuteAfterTime(5));
}
}
IEnumerator ExecuteAfterTime(float time)
{
yield return new WaitForSeconds(time);
}
void LoadObj()
{
string path = EditorUtility.OpenFilePanel("Load scan file", "", "obj");
\\Open the file and display it
}
I tried:
Add a time (see commented code above) -- did not work
Add a boolean that allows to execute LoadObj() only when the previous file is opened -- did not work
Added EditorUtility.OpenFilePanel() before or after yield return new WaitForSeconds(time) -- in the latter case, there is the delay of 5 seconds, but it still opens twice in both cases.
I searched for other solutions, but did not find anything else.
I work on a Windows machine and use Unity 2018. The aim is to open a single file at a time, but it must be possible to open another file, say, after a few minutes.
Any idea how to prevent the dialog from opening twice?
As #Eshan Mohammadi suggested, I checked if I only had a single instance of the code. I deleted the entire file, created a new one and added it to my GameObject. However, only then I noticed that this particular GameObject is copied, including the code, of course.
So, I chaned the way the GameObject was copied and problem solved.
When I rename a file, I run a GetStatus() method that visually updates the status of my files after they get added/checked out/ reverted/renamed/etc. When I rename a previously checked out file it returns NewInIndex rather than either RenamedInIndex or RenamedInWorkingDir status.
Here is my method:
public Tuple<SourceControlStatus, LockStatus> Status(string path)
{
try
{
var existingPath = path;
//finds an existing path so we can still get the status of deleted files (repo.Discover will fail if the path does not exist)
while (!File.Exists(path) && !Directory.Exists(path))
{
existingPath = Path.GetDirectoryName(existingPath);
}
var repoPath = Repository.Discover(path);
using (var repo = new Repository(repoPath))
{
var status = repo.RetrieveStatus(path);
return new Tuple<SourceControlStatus, LockStatus>(GetStatus(status), LockStatus.None);
}
}
catch (Exception ex)
{
}
return new Tuple<SourceControlStatus, LockStatus>(SourceControlStatus.Checkin, LockStatus.None);
}
Can anyone help me understand what I need to do to get it to accurately return the right status? Or is the fix to simply, if the item returns "NewInIndex", check the status of the entire repo, and then examine the list of renamed files, and see if any match the one in question.
There is no rename detection when you are examining the status of a single path.
Since renames are computed by diffing the HEAD to the index (to determine what's renamed in the index), and by diffing the index to the working directory (to determine what's renamed in the working directory), there is no explicit change type for a file that is renamed. Additionally, the status information is not cached, it is recomputed for every invocation.
Finally, for efficiency, when you request the status for a single path, the rest of the repository is not examined. (Otherwise, repeated GetStatus(string path) operations would become quadratic.) This means that there is no ability to scan other files that could be candidates as the "other half" of that rename operation.
If you want rename information, the best thing to do here is to GetStatus() on the entire repository and then examine the paths you're interested in from the returned results of that status.
I have an created a command line application which takes a crystal report file, opens it, exports it to a text file and then cleans up after itself by deleting the crystal report. This works fine until I suppress sections in the crystal report, then when I try and delete it I get the following:
System.IO.IOException: The process cannot access the file 'C:\ExportCMD\bin\Debug\ReportExport\2ee373f0-e05a-42d6-9b61-9c79e2662c20\14_636271819978854269.rpt' because it is being used by another process.
After some investigation I have found that it happens when I suppress a section in the open report, if I comment out that code it works fine. The code for setting the Suppress flag is:
private static void SuppressReportSection(ref Report openReport, string sectionToFind, bool hideSection)
{
if (!string.IsNullOrWhiteSpace(sectionToFind) && openReport != null)
{
openReport.Sections[sectionToFind].Suppress = hideSection;
}
}
After checking Google for a solution, I gave the following a try:
private static void SuppressReportSection(ref Report openReport, string sectionToFind, bool hideSection)
{
if (!string.IsNullOrWhiteSpace(sectionToFind) && openReport != null)
{
Sections reportSections = openReport.Sections;
try
{
if (reportSections != null)
{
reportSections[sectionToFind].Suppress = hideSection;
}
}
catch
{
throw;
}
finally
{
if (reportSections != null)
{
Marshal.ReleaseComObject(reportSections);
reportSections = null;
}
}
}
}
This unfortunately didn't cure it either. I have tried it with and without the ref in case it is something to do with the report object.
I am having to use the Crystal Reports 8.5, and I have added the reference.
When I destroy my report object I call the Marshal.ReleaseComObject, then GC.WaitForFullGCComplete() in the hope that it will have released the file. Once all this has completed I call the cleanup code which deletes the files. The clean up method will allow multiple attempts at deleting the file before it throws the error.
Where am I going wrong? If there is already an answer to the question can you point me to it please.
I am using C# with .Net 4 as this is the highest version we can get on the servers. I can't use the CrystalDecisions assemblies.
Try to use FinalReleaseComObject instead:
Therefore, use the ReleaseComObject only if it is absolutely required. If you want to call this method to ensure that a COM component is released at a determined time, consider using the FinalReleaseComObject method instead. FinalReleaseComObject will release the underlying COM component regardless of how many times it has re-entered the CLR. The internal reference count of the RCW is incremented by one every time the COM component re-enters the CLR. Therefore, you could call the ReleaseComObject method in a loop until the value returned is zero. This achieves the same result as the FinalReleaseComObject method.
reference
It's all still in your task manager all you have to do is..
Just remove the file in task manager using task kill by opening a .bat file. You can do this after you execute or before deleting the report.. after this you are freely can delete the file or you can open it again without any error.
Two functions in our standard ASP.NET app are:
private static void SaveToFileSystem(AttributeFileAttachment attach, int paId)
{
string fileName = GetAttachmentFullName(attach.FileName, paId);
File.WriteAllBytes(fileName, attach.Content);
}
public static string GetAttachmentFullName(string name, int paId)
{
HttpContext ctx = Util.Util.GetHttpContext();
return string.Format("{0}{1}_{2}_{3}",
ctx.Server.MapPath("<some variable to get the path>" + "attributeFileAttachments\\"),
ctx.Session.SessionID,
paId,
name);
}
when File.WriteAllBytes is executed it returns exception:
he process cannot access the file '\\d$\Home\\attributeFileAttachments\' because it is being used by another process.
The essence are two lines:
ctx.Server.MapPath... (Microsoft code)
and File.WriteAllBytes...
that work on the same file.
It turns out that HttpServerUtility.MapPath locks the file and leaves it locked !?
I don't see any comments on that in official documentation nor I see anybody complains on that.
But it can't be anything else, since the two lines are consecutive.
When I modify fileName for File.WriteAllBytes in immediate window just a bit, the writing succeeds, since that new file is not locked.
One more thing I have noticed is that this happens only and always for some of the attachment files.
Thank you for the time and any advice.
Im having some trouble my program hanging when selecting a file in a file dialog. This is the code that is showing the file browser dialog:
private void isForgeIncluded_btn_Click(object sender, EventArgs e)
{
this.isForgeIncluded.Text = FolderFileDialog("file", isForgeIncluded.Text, "Forge installer file (*.jar)|*.jar");
}
public string FolderFileDialog(string type, string current, string fileTypes = "All files (*.*)|*.*|All files (*.*)|*.*", string StartFolder = "C:\\")
string ReturnString = current;
if (current != "")
{
StartFolder = Path.GetFullPath(current);
}
if (type == "file")
{
OpenFileDialog minecraftFile = new OpenFileDialog();
minecraftFile.Title = "Select file";
minecraftFile.InitialDirectory = StartFolder;
minecraftFile.RestoreDirectory = true;
minecraftFile.Filter = fileTypes;
if (minecraftFile.ShowDialog() == DialogResult.OK)
{
ReturnString = minecraftFile.FileName;
return ReturnString;
}
minecraftFile = null;
}
return ReturnString;
}
I've narrowed the problem down to between the "if" statement and the "Return string = minecraftFile.FileName;" .. When using the debugger the program takes up to a five second break between those two lines. After its break it comes back and returns the value as if nothing was wrong. But IntelliTrace sometimes comes up with a "FileNotFound Exception" even though the program never shows me any error messages, and returns the correct value to the textbox as it should.
The wierd part is that it is not always this happens. Its random and can happen even though i select the same file as last time. The files i select are local files too on the system drive.
What could be wrong? Does the code look as it should?
Two basic problems can cause trouble with OpenFileDialog. First is misbehaving shell extension installed on your machine, they'll get loaded into your process when you open the dialog. A basic check is that you don't see trouble with Notepad's File + Open command and that you see nothing special in the Visual Studio Output window while the dialog is active. Enabling unmanaged debugging gives you more info.
The second cause is having an issue with the thread state of your UI thread. If must be initialized as a single-threaded apartment to be able to show this dialog properly. Go back to your Main() method, normally in Program.cs, and ensure it has the [STAThread] attribute.
If that doesn't pan out then we need more info about the code that's misbehaving. You need to enable unmanaged debugging, Project + Properties, Debug tab. And enable the Microsoft symbol server, Tools + Options, Debugging, Symbols. And disable Just My Code debugging, Tools + Options, Debugging, General. Hit Debug + Break All right after you get it to misbehave and post the content of the Call Stack window.