Directory.Move() throws IOException regardless of the FileShare options for internal files - filesystems

I am trying to rename or move the folder with a file, which is located in this folder being opened for reading. This blocks the folder renames, even though the file is opened with FileShare.Delete, which to my understanding, should allow rename.
Here is my C# code that reads the file:
using (FileStream fs = File.Open(#"C:\Test\1.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
{
// My long-running code here.
}
Here is my code that renames the "C:\Test" folder:
Directory.Move(#"C:\Test", #"C:\Test1");
It throws:
IOException: 'The process cannot access the file because it is being
used by another process.'
I do not have any Windows Explorer open or any other apps blocking the file or folder.
At the same time "create folder -> move file -> delete folder" sequence works just fine:
Directory.CreateDirectory(#"C:\Test1");
File.Move(#"C:\Test\1.txt", #"C:\Test1\1.txt");
Directory.Delete(#"C:\Test");
How is this possible? How can I rename the folder with the file being opened?

Related

how to create an .inf file that will open a .bat file

I'm trying to create an inf file containing a command which opens a .bat file, but it doesn't work.
I've used "run=", "open=", "shellexecute=" but nothing worked.
I've also tried to plug the removable disk, (which contains the inf file), into another computer, but still doesn't work.
Additionally, I've also tried other commands like "icon=" and which works. But when I use the command "run=", "open=", etc. I still can't open the .bat file that I created, and have placed in the same removable disk.

Open file in the default application WinForms (.NET Core) [duplicate]

i want to ask for help with opening a file from c# app with associated app.
I tried this:
ProcessStartInfo pi = new ProcessStartInfo(file);
pi.Arguments = Path.GetFileName(file);
pi.UseShellExecute = true;
pi.WorkingDirectory = Path.GetDirectoryName(file);
pi.FileName = file;
pi.Verb = "OPEN";
Process.Start(pi);
or this:
Process.Start(file);
where string file in both examples represents full path to the file trying to open. Now, everything is working well, except the (jpg) images with ACDSee app. Irfanview associations works well, MS office documents too. After trying to open the jpg image associated with acdsee it just runs the acdsee in the notification area and does not open the file.
I discovered, that in the registry CLASSES_ROOT for *.jpg images, there is an ACDSee.JPG value as associated app, and under this key there is in the shell->Open->Command a path:
"C:\Program Files\ACD Systems\ACDSee\ACDSee.exe" /dde
and I thing that this weird /dde is the reason, why i cannot open the file. I realized that in the same reg key shell->Open there is some DDEExec key entry with value [open("%1")]
For Irfan view or other checked app there is not a ddeexec, just the normal command like
"C:\Program Files (x86)\IrfanView\i_view32.exe" "%1"
that can be run from command line after swaping the %1 for file name, but I could not run the command from acdsee entry in the command line :(
So my question is, how can I set up the ProcessStartInfo object to ensure that it will run all the files as it would be in the explorer by doubleclick, the standards and this DDEExec ones? Is there something other like DDEExec that I shoul be aware of?
thanks and sorry for my EN
UPDATE: because this question still gets upvotes, I want to clarify that accepted answer works. I only had problem with old version of ACDSee and not with the Process.Start command or with the jpg extension.
Just write
System.Diagnostics.Process.Start(#"file path");
example
System.Diagnostics.Process.Start(#"C:\foo.jpg");
System.Diagnostics.Process.Start(#"C:\foo.doc");
System.Diagnostics.Process.Start(#"C:\foo.dxf");
...
And shell will run associated program reading it from the registry, like usual double click does.
In .Net Core (as of v2.2) it should be:
new Process
{
StartInfo = new ProcessStartInfo(#"file path")
{
UseShellExecute = true
}
}.Start();
Related github issue can be found here
This is an old thread but just in case anyone comes across it like I did.
pi.FileName needs to be set to the file name (and possibly full path to file ) of the executable you want to use to open your file. The below code works for me to open a video file with VLC.
var path = files[currentIndex].fileName;
var pi = new ProcessStartInfo(path)
{
Arguments = Path.GetFileName(path),
UseShellExecute = true,
WorkingDirectory = Path.GetDirectoryName(path),
FileName = "C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe",
Verb = "OPEN"
};
Process.Start(pi)
Tigran's answer works but will use windows' default application to open your file, so using ProcessStartInfo may be useful if you want to open the file with an application that is not the default.

When starting a process how do I set the directory for that process to read/write files?

In a WPF project this line is very simple to start mspaint with a given filename
Process.Start("mspaint.exe", filename)
While mspaint.exe will work with 'filename' in it's directory, if I try to open other files or do a 'SaveAs', mspaint.exe is looking at the Visual Studio \bin directory where the application was compiled to. Even if I move the .exe elsewhere, it keeps looking at the \bin location.
I tried the following:
Dim process1StartInfo As New ProcessStartInfo
process1StartInfo.WorkingDirectory = "C:\Users\theuser\Pictures"
process1StartInfo.FileName = "mspaint.exe"
process1StartInfo.Arguments = filename
process1StartInfo.UseShellExecute = False
Dim process1 = Process.Start(process1StartInfo)
I thought setting .WorkingDirectory would change the behavior but it does not.
Is it possible to and how do I change the directory that mspaint.exe is looking at when it is launched from within an application? Especially after the application is compiled and moved.

Revit Copy addin dll at shutdown

I am working on creating a revit addin and I want to have it automatically pull a copy ofthe .dll and.addin files at shutdown using a batch file. By themselves the code and the batch file routines work correctly but when I have them running with each other I get a have a sharing violation for copying the .dll file. Can anyone tell me how I can get around the sharing violation? The purpose is to deploy these two files to all users and copy the file updates to their computer when they shut down Revit.
public Result OnShutdown(UIControlledApplication application)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "S:\\Revit 2015\\Addins\\Revit Tabs\\2015_RevitTab.bat";
proc.StartInfo.WorkingDirectory = "S:\\Revit 2015\\Addins\\Revit Tabs\\";
proc.Start();
return Result.Succeeded;
}
And here is the copy syntax
xcopy "S:\Revit 2015\Addins\Revit Tabs\Revit Tabs.addin" "C:\ProgramData\Autodesk\Revit\Addins\2015" /y
xcopy "S:\Revit 2015\Addins\Revit Tabs\Revit Tabs\bin\Debug\Revit Tabs.dll" "C:\ProgramData\Autodesk\Revit\Addins\2015" /y
You could add a call to your own stand-alone utility exe that monitors whether the current Revit process is still alive, and thenexecutes the add-in DLL copy process once Revit really is gone.
I wanted to same auto-update process and after a bit of trial and error I found some code that worked for me. Hopefully, you can use it or improve it.
I have ribbon.addin, ribbon.dll ("Ribbon") and commands.dll ("Commands") files. All files are installed as part of the deployment into the "%appdata%\Autodesk\Revit\Addins\2016" folder ("Local"). It's important that these are installed in the "%appdata%" folder and not the "%programdata%\Autodesk\Revit\Addins\2016" folder because of write protection issues!
The Ribbon addin is only for checking which version of the Commands is currently in the Local folder and if that's out-of-date from the Commands file I have in a shared network folder ("Shared"). Because of security, I can't read the AssemblyVersion of the Local DLL or the Shared DLL. To get around this I have a TXT file in the Local folder that has the AssemblyVersion as the first line and, in the Shared folder I have another TXT file (where I actually have the "About" information of the Commands addin) which has the Shared Commands AssemblyVersion as the first line.
So my Ribbon OnStartup(UIControlledApplication a) code checks the TXT files using System.IO.StreamReader. If the Local file is out-of-date it updates the Local TXT and DLL files with this c#:
try
{
string AddinsDir = a.ControlledApplication.CurrentUserAddinsLocation + #"\";
string tempDir = System.IO.Path.GetTempPath();
StreamWriter myStream = new StreamWriter(tempDir + "Commands.txt", false, System.Text.Encoding.Default);
myStream.WriteLine(AssemblyVersion);
//AssemblyVersion is the first line of the Shared Commands TXT file we read
myStream.Close();
File.Copy(tempDir + "Commands.txt", AddinsDir + "Commands.txt", true);
File.Delete(tempDir + "Commands.txt");
File.Delete(AddinsDir + "Commands.dll");
File.Copy(SharedPath + "Commands.dll", AddinsDir + "Commands.dll", true);
//SharedPath is the Shared folder
}
catch (Exception e)
{
TaskDialog.Show("Error Loading Ribbon", "There was an error loading the Ribbon. Please contact the BIM Manager for assistance.\n\n" + e.Message);
return Result.Failed;
}
If, at this point the code is still running the file is up-to-date and it's time to load it:
Assembly Commands = Assembly.LoadFrom(AddinsDir + "Commands.dll");
Type type = Commands.GetType("Commands.App");
//Commands.App is my class where my Ribbon is created and Events are registered
object instanceOfCommands = Activator.CreateInstance(type, new object[] { a });
return Result.Succeeded;
My plan for Revit 2017 deployment is to create my custom Ribbon in the Ribbon.dll so I can have my "About" button there and accessible at all times. Then, I'll add a button in the "About" dialog box that would manually update the Local Commands DLL.
I hope that helps!!

Batch File Copying

I am trying to copy a file from the C:\ drive to the steam directory using this
copy "C:\CSS.zip" "C:\%ProgramFiles86%\Steam\CSS.zip"
but it always makes a new folder and places the file in a new folder called %ProgramFiles86% but i want it to go in the actual Program Files (x86)
Thanks for the help
You aren't using the program files path correctly. Your code should be this:
copy C:\CSS.zip "%programfiles(x86)%\CSS.zip"

Resources