.net file rename for don't watch(FileSystemWatcher) - filesystemwatcher

i'm use Directory.Move << this watched filesystemwatcher log
Log details full path = e:\web\qe1 type rename old name = web\folder ...
how to bypass filesystemwatcher log ??

Related

Getting more information on Azure File share file handles - Get-AzStorageFileHandle

I have got the open file handles from azure storage account file share, but this information seems to be very less to understand what Process has started it or On which file this file handle is.
Getting file handles https://learn.microsoft.com/en-us/powershell/module/az.storage/get-azstoragefilehandle?view=azps-2.7.0
https://github.com/Azure/azure-powershell/blob/master/src/Storage/Storage.Management/help/Get-AzStorageFileHandle.md#example-1-list-all-file-handles-on-a-file-share-recursively-and-sort-by-clientip-and-opentime
How to get more information using handleid or sessionid from this list?
I have searched a lot on azure docs as well as on internet but no information on this.
Sample script and response :
PS C:\>Get-AzStorageFileHandle -ShareName "mysharename" -Recursive | Sort-Object ClientIP,OpenTime
HandleId Path ClientIp ClientPort OpenTime LastReconnectTime FileId ParentId SessionId
-------- ---- -------- ---------- -------- ----------------- ------ -------- ---------
28506980357 104.46.105.229 49805 2019-07-29 08:37:36Z 0 0 9297571480349046273
28506980537 dir1 104.46.105.229 49805 2019-07-30 09:28:48Z 10376363910205800448 0 9297571480349046273
After a quick research and local test, I believe
the "Path" returned by the command is the file or directory path you are looking for.
File handle is not only for file but also for folder.
The trick here is the handle for file is not being hold always. In fact, most applications release the file handle as soon as they open the file, like notepad. So when you run the command, for the most of time, you could only see handle for folder, not files.
To verify this, I've tested with the code below:
static void Main(string[] args)
{
string path = args[0];
var file=File.Open(path, FileMode.OpenOrCreate);
Console.WriteLine("Press any key to release the handle");
Console.ReadKey();
file.Close();
}
When excuting File.Open, the process holds handle, then I run Get-AzStorageFileHandle. The handle for "test.csv" is displayed:
But if you open the file with notepad, only handle for folder is displayed.
Anyway, you can use the "path" returned to determine which file is being held by others.
By the way, the handle.exe is not applied for cloud environment. You should not use it.

FileSystemWatcher reports file available on network share but file cannot be found

BACKGROUND
I have a server that has a shared folder \\Server\Share with 4 subfolders:
OutboundFinal
OutboundStaging
InboundFinal
InboundStaging
All folders reside on the same physical disk and partition, no junction points used.
I also have several WinForms clients (up to 10) that write and read files to this share, each client is working on multiple threads (up to 5). Files are witten by clients (up to 50 threads altogether) into the \\Server\Share\OutboundStaging folder. Each file has the name of a GUID, so there's no overwriting. Once a file is completely written, it is moved by the client to the \\Server\Share\OutboundFinal folder. A Windows service running on the same server will pick it up, delete it, process it, then writes the file with the same name into the \\Server\Share\InboundStaging folder. Once the file is completely written, it is moved to the \\Server\Share\InboundFinal folder by the service.
This \\Server\Share\InboundFinal folder is monitored by each thread of each WinForms client using a FileSystemWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut);
The FileSystemWatcher.Filter is set to the GUID filename of the file a certain thread expects to see in the \Server\Share\InboundFinal folder, so the FileSystemWatcher waits until a specific file is shown in the folder.
I have read several SO questions about FileSystemWatcher behaving erratically and not reporting changes on UNC shares. This is however not the case for me.
The code I use looks like this:
FileSystemWatcher fileWatcher = new FileSystemWatcher();
fileWatcher.Path = InboundFinalFolder;
fileWatcher.Filter = GUIDFileName; // contains full UNC path AND the file name
fileWatcher.EnableRaisingEvents = true;
fileWatcher.IncludeSubdirectories = false;
var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut);
if (!fileWatcher.TimedOut)
{
using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) {
byte[] res = new byte[stream.Length];
stream.Read(res, 0, stream.Length);
return res;
}
It's the using line that throws the exception.
THE PROBLEM
I would assume that the fileWatcher.WaitForChanged would go on only if the file with the proper GUID name is in the \\Server\Share\InboundFinal folder. This is exactly how FileSystemWatcher works on local folders, but not with file shares accessed over the network (local files, even accessed via a share, also tend to work). FileSystemWatcher reports that the file the thread is waiting for is in the FileSystemWatcher \\Server\Share\InboundFinal folder. However, when I try to read the file, I get a FileNotFoundException. The reading thread has to wait 3-15 seconds before the file can be read. I try to open the file with a FileStream with Read sharing.
What could cause this behavior? How do I work around it? Ideally the FileSystemWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut); should only continue execution if the file can be read or timeout happens.
The FileSystemWatcher has a bad reputation, but actually, it is not that bad...
1.)
Your code sample does not compile. I tried this:
FileSystemWatcher fileWatcher = new FileSystemWatcher();
fileWatcher.Path = "X:\\temp";
fileWatcher.Filter = "test.txt";
fileWatcher.EnableRaisingEvents = true;
fileWatcher.IncludeSubdirectories = false;
var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed |
WatcherChangeTypes.Created, 20000);
if (!res.TimedOut)
{
FileInfo fi = new FileInfo(Path.Combine(fileWatcher.Path, res.Name));
using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] buf = new byte[stream.Length];
stream.Read(buf, 0, (int)stream.Length);
}
Console.WriteLine("read ok");
}
else
{
Console.WriteLine("time out");
}
I tested this where X: is a SMB share. It worked without problems (for me, see below).
But:
You should open / read the file with retries (sleeping for 100 ms after every unsuccessfully open). This is because you may run into a situation where the FileSystemWatcher detects a file, but the move (or another write operation) has not yet ended, so you have to wait until the file create / mover is really ready.
Or you do do not wait for the "real" file but for a flag file which the file move task creates after closing the "real" file.
2.)
Could it be that the move task did not close the file correctly?
3.)
Some years ago I had some tools (written in perl) where one script created a flag file and another script waited for it.
I had some nasty problems on a SMB 2 share. I found out that this was due to SMB caching.
See
https://bogner.sh/2014/10/how-to-disable-smb-client-side-caching/
File open fails initially when trying to open a file located on a win2k8 share but eventually can succeeed
https://technet.microsoft.com/en-us/library/ff686200.aspx
Try this (on the client):
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanWorkstation\Parameters]
"DirectoryCacheLifetime"=dword:00000000
"FileNotFoundCacheLifetime"=dword:00000000
Save this as disablecache.reg and run regedit disablecache.reg
Then reboot.

X-Pages: fileUpload control preventing unwanted files from being uploaded

I am using the accept property in the fileUpload control to only allow certain file Types and prevent uploading .exe or other potentially harmful files.
application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/pdf,text/plain,image/gif,image/jpeg,image/pjpeg,image/png"
This works, however I am using a Tool called Burp Suite that allows me to intercept an acceptable file eg .txt that could contain harmful code and change the filename extension to .exe which is then upload to the X-Page database.
When I goto save the document and after Interception and changing to a .exe, I have added the following code to identify an exe file:
Can we manipulate what has been uploaded and change the file extension to a harmless .txt ?
var fileData:com.ibm.xsp.http.UploadedFile =facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1'));
if (fileData != null) {
var tempFile:java.io.File = fileData.getServerFile();
// Get the path
var filePath:String = tempFile.getParentFile().getAbsolutePath();
// Get file Name
var fileName:String = tempFile.getParentFile().getName();
// Get the Name of the file as it appeared on the client machine - the name on the server will NOT be the same
var clientFileName:String = fileData.getClientFileName();
}
var fileRight = clientFileName.slice(-4);
if (fileRight == ".exe")
{
//facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1').replace(".exe",".txt"))
//facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1').remove(".exe",0))
}
Yes, you can. You have on the properties of control two options 'Use original file name of uploaded file' and 'Replace file name of uploaded file...' where you can put name with extension 'name.txt' . I didn't try to change only extension... That is probably better in code to replace.

How to get local file system path in azure websites

I have a file hosted on the disk along with my website that I want to read .Not sure how do I access the file when I use System.Environment.CurrentDirectory it point to a D drive location .Can someone please tell me how can I get to my file stored at the root of where my site is hosted.
Thanks
There is an environment variable called HOME in your website's environment that will get you part way there.
You can access it using razor syntax or in code (C#). For example, suppose you have a file called data.txt that is at the root of your site with the default document and the rest of your files. You could get it's full path like this.
#{ var dataFileName = Environment.GetEnvironmentVariable("HOME").ToString() + "\\site\\wwwroot\\data.txt"; }
You can find this out on your own using the Site Control Management/"Kudu". For example, if your website is contoso.azurewebsites.net, then simply navigate to contoso.scm.azurewebsites.net. In here you can learn all about the file system and environment variables available to your website.
For testability, I use below code.
string path = "";
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HOME")))
path = Environment.GetEnvironmentVariable("HOME") + "\\site\\wwwroot\\bin";
else
path = ".";
path += "\\Resources\\myfile.json";
In above example, I added myfile.json file to Resources folder in a project with Content and Copy if newer property setting.
This works for me in both localhost and azure:
Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, "file_at_root.txt");
System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath is the full local path to your site's root.
I'm currently using AppDomain.CurrentDomain.BaseDirectory (.NET Core project). It returns "D:\home\site\wwwroot\" in Azure and the application root in local so the only difference is adding "bin\\" when it is Azure. I am searching the entire directory tree, just in case, but it can be trimmed.
It's something like:
private static string GetDriverPath(ILogger logger, string fileName)
{
var path = AppDomain.CurrentDomain.BaseDirectory;
if (File.Exists(Path.Combine(path, fileName)))
{
return path;
}
string[] paths= Directory.GetFiles(path, fileName, SearchOption.AllDirectories);
if (paths.Any())
{
return Path.GetDirectoryName(paths.First());
}
throw new FileNotFoundException($"{fileName} was not found in {path}.", fileName);
}
I'm new answering questions and this is an old one but I hope it helps someone.
You can do it using the below code.
string fullFilePath = Environment.GetEnvironmentVariable("HOME") != null
? Environment.GetEnvironmentVariable("HOME") + #"\site\wwwroot\test.txt" //It will give the file directory path post azure deployment
: Path.GetDirectoryName(Path.GetDirectoryName(Directory.GetCurrentDirectory())) + #"\test.txt";//It will give the file directory path in dev environment.

How do I open a file with my application?

Ok, you know how in programs like Microsoft Excel, or Adobe Acrobat Reader you can click on a file in explorer and it will open with the associated program. That's what I want my application to do. Now, I know how to set up the file associations in Windows so that it knows the default program for each extension. My question is how do I get my application to open the file when I double click the file.
I've searched the web using google, I've searched the msdn site, and I've searched several forums including this one but I haven't found anything that explains how to accomplish this. I'm guessing it has something to do with the parameters of the main method but that's just a guess.
If someone can point me in the right direction I can take it from there. Thanks in advance for your help.
Shane
Setting up the associations in windows will send the filename to your application on the command line.
You need to read the event args in your applications main function in order to read the file path and be able to open it in your application.
See this and this to see how to access the command line arguments in your main method.
static void Main(string[] args)
{
System.Console.WriteLine("Number of command line parameters = {0}", args.Length);
foreach (string s in args)
{
System.Console.WriteLine(s);
}
}
When you open the file, with associations set as you described, your application will be started with the first argument containing the filepath to your file.
You can try this out in a simple way by printing out the args from your main method, after you open your application by clicking on the associated file. The 0th element should be the path to your file.
Now, if you successfully reached this point, the all you need to do now is read the contents of the given file. I'm sure you'll find more than plenty of resources here on how to do that.
I guess this is what you are looking for:
FileInfo fi = new FileInfo(sfd.FileName); //the file you clicked or saved just point
//to the right file location to determine
//full filename with location info
// opening file
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #fi.FullName;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
You will need to create registry-keys for your file-extension. This page describes well, which keys you'll need to set (see «3. How do I create file associations?»).

Resources