We have a C# .Net client application that sends some commands via REST over HTTP. The server is on a Linux machine written in Perl.
These commands contain file paths located on the server that can be entered by the user. Since the users are on windows, we'd like for them to be case-insensitive, but this is giving us some issues in locating the files server side.
How can we get the correct casing?
We have 2 possible solutions:
Use a winapi call on the client to fix the path to be properly cased. (These files are visible by a shared folder on the clients computer)
Use some perl code on the server to locate a file with a case-insensitive path as input
Any suggestions? We would like this to work on all client machines that are Windows XP SP2 and higher.
UPDATE: We decided it should be fixed client side, on the rare case that there is a case mismatch.
We run this if we get a "file not found" error on the directory of the file. Someone would have to modify this to work for files as well, but in our case the filename could never be wrong (I'd rather not explain why):
string FixDirectory(string fullpath)
{
return fullpath
.Split(Path.DirectorySeparatorChar)
.Skip(1)
.Select(path =>
{
string[] split = fullpath.Split(new string[] { path }, StringSplitOptions.None);
string tempDir = split[0];
string[] dirs = Directory.GetDirectories(tempDir, path);
fullpath = fullpath.Replace(Path.Combine(tempDir, path), dirs[0]);
return fullpath;
})
.Last();
}
Your first proposal makes sense -- if the client can see the file, then use an API call on the client to get the real filename (with the correct case) before submitting that data to the server. The user shouldn't have to manually type in a filename at all - use the standard "Browse..." widget to bring up a dialog box that allows the user to find the file in his filesystem.
Using a case-insensitive file search on the case-sensitive server should only be a last resort. As you mentioned in your follow-up comment, there are various edge cases that are annoying to account for, so it would be best to avoid this scenario entirely.
This sounds like a job for the server. If you give a case sensitive server a case insensitive string, it can more easily find the desired file than the client can.
Can you normalize the character cases on your server? For example, force all directory and file names to be lowercase.
If so, then your server process would easily convert requests for My/FILE.XLS and my/file.XLS to my/file.xls.
Normalization avoids a lot of complicated search logic and it prevents collisions between similar file names.
Related
I have an application in Visual Studio C# which includes saving into a text file, how can I have a .exe sent to another computer and not have an exception in saving?
I need to send a .exe file by email (Yes it's possible) and this application includes saving the state of the game. How can I send this .exe file and let the user be able to save in his computer please?
The problem is that when I send my application's executable file on another computer, I'm getting an exception in saving. Because on the other computer I don't have the text file which I'm saving the game.
I am saving here :
StreamWriter myFile = File.CreateText(Directory.GetCurrentDirectory()+"//ConnectFour.txt");
in the obj/Debug/ of the project..
Thanks for your help :)
Sending an executable should work just fine.
Make sure the other computer has the appropriate Microsoft .NET Framework installed.
Latest framework installer: MSDN
Also, make sure the path inwhich you're saving the file to exists on the remote computer. For example, if you're trying to save to the D:\ drive and it doesn't exist. You will get an exception.
Most likely current location is not writable by current user.
Using "current directory" is dangerous as you have no control over where application is launched from. It is very useful for command line utilities, but not so much for regular windowed applications. Use location that you know you can save files to - i.e. "My Documents".
var filePath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\",
ConnectFour.txt");
using(var myFile = File.CreateText(filePAth))
{
// save data here.
}
The problem when sending executables by email are the anti-virus-scanners. Some of them refuse e-mails containing executables. Others accept the mails but delete the attachment.
The solution consists in hiding the executable. This can be done by zipping the executable and sending the zip-file.
Often this is enough to solve the problem but some anti-virus-scanners are very smart and even recognize executables within the zip-attachment. The solution here is to encrypt the zip-file with a password. I often just use the password "pwd" and mention it in the e-mail text. The anti-viruses are not (yet) smart enough to understand this text.
UPDATE
Now I understand your problem. It has nothing to do with sending the executable.
An application can determine from which directory it has been started like this
string dir = System.IO.Path.GetDirectoryName(
System.Windows.Forms.Application.ExecutablePath
);
An alternative is (if you don't have a reference to WinForms):
string dir = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetEntryAssembly().Location
);
You probably do not have sufficient privileges to save the file on the remote machine. If you give us more information on the exact exception that is being thrown (type of exception, message, stack trace, etc) you will get a more accurate answer.
I have some VB6 .ocx files that I would like to register. These .ocx files would be on a remote machine.
What is the best way to register these .ocx files programatically?
string arg_fileinfo = "/s" + " " + "\"" + "\\<remotemachine>\\<directory>\\<ocx>" + "\"";
Process reg = new Process();
//This file registers .dll files as command components in the registry.
reg.StartInfo.FileName = "regsvr32.exe";
reg.StartInfo.Arguments = arg_fileinfo;
reg.StartInfo.UseShellExecute = false;
reg.StartInfo.CreateNoWindow = true;
reg.StartInfo.RedirectStandardOutput = true;
reg.Start();
reg.WaitForExit();
reg.Close();
I'm not getting any errors but it isn't registering the .ocx either. Any ideas?
If you want to register a remote file for use on a local machine, there is nothing special required for registering a file on a UNC path, but you do need to make sure that the UNC path or mapped drive is still available to all users, especially the user that is running regsvr32. Presumably, this will be the local admin which (by default on Windows Vista+) will require elevation which can disconnect network connections.
Also note that your example is missing the extra \ from the beginning of the UNC path. Your code will result in arg_fileinfo containing /s "\<remotemachine>\<directory>\<ocx>".
You can add the extra \, or use the # decorator which makes it a lot clearer when entering Windows paths:
string arg_fileinfo = "/s \"" + #"\\<remotemachine>\<directory>\<ocx>" + "\"";
Or just use it for the entire string and the alternative quote escaping method:
string arg_fileinfo = #"/s ""\\<remotemachine>\<directory>\<ocx>""";
Take this as a warning you're free to ignore (because I know you will anyway):
Doing this isn't a good practice. Just to begin with "run from network" PE files (EXE, DLL, OCX) need to be specially linked for it or you risk high network activity and crashes due to intermittent network interruptions. And registering anything not on the boot drive or at least a local hard drive isn't sensible anyway. Doing any of this ranks high on the "poor practices" list even though it might seem to work most of the time.
Why not just do normal deployment following accepted practices?
My guess would be that you are doing a lot of Mort development, throwing together version after version of some program hoping one of them will eventually "stick." So you want to dump some or all of it onto a network share, thinking "Installation? Installation? We don't need no steenking installation. I can just plop new files out there and have everything magically work with no effort."
I'll assume you don't have the luxury of a managed network you can use to push out updates via Group Policy, and that you aren't creating the necessary MSI installer packages handling the Product and Upgrade Codes in them.
One alternative would be to use reg-free COM, which will solve a lot of small issues for you.
Now, you could do this and still ignore the hazards of PE files run from a network share, or you could bypass that using a small launcher program. That launcher could check a network share for a new version, and if found copy the newer files to the local PC before starting the actual application and terminating. This is basically an auto-updated XCopy Deployment technique.
You can get as fancy as need be. For example if your application accepts command line parameters it might do the new version check itself and if found then start the small updater (passing it the command line parameters), then terminate. The updater app could restart and pass those parameters to the new version.
But yes, life as Mort (or even an official on-the-payroll developer) can be a pain. It can be extremely difficult to get the attention of your friendly neighborhood box jockeys to do things properly even if you are working in a managed corporate LAN environment. That goes double if your application isn't part of some highly engineered sanctioned Major Project.
I had to do this several years ago. As best I can remember, UNC names wouldn't work, a mapped drive letter was required. Whether it was strictly a regsvr32 issue, or was caused by something else (e.g. Windows 95) is lost in the fog of time.
If you want to register the file for use on the remote machine, you you need to run the code on that remote machine.
You can either do this by physically sitting in front of the computer, using remote control software, or a remote admin tool like psexec.exe.
How can I get the path of a file on my computer or on the local area network.
I would to show a window that allows me to browse the file system when I click a button, and I want to select a file and get the path to the file. How can I do this?
P.S. I'm not looking to upload the file; I just want to get the path.
The web application is running on the server, and you don't have access to the client file system at all. Can you imagine how much of a vulnerability that would be? I know I don't want the sites I visit inspecting my file system...
EDIT: Question is for a WinForms application
For a WinForms application, you can use the OpenFileDialog, and extract the path with something like this:
If you're looking for the file path:
string path = OpenFileDialog1.FileName; //output = c:\folder\file.txt
If you're looking for the directory path:
string path = Path.GetDirectoryName(OpenFileDialog1.FileName); //output = c:\folder
In general, the System.IO.Path class has a lot of useful features for retrieving and manipulating path information.
To do this in VB.NET use the FolderBrowserDialog.
Due to security restrictions browsers include for user safety, you can't manipulate the client file system directly. You can only use to let them pick a file, and even then it only sends the filename, not the whole path.
The FileSystem API in HTML5 allows for file manipulation, but only within a sandbox for your site specifically, not browsing across the network or other files on the client system.
Instead, provide your users easy steps on how they should use My Computer (or whatever equivalent on other OS's) to navigate to the file and copy & paste the path into a simple text input box.
Have you taken a look at the Path class from System.IO ?
I'm creating a program which downloads files off various types of servers, such as network paths or HTTP servers, based upon criteria. So far I have it working based upon a regex, but I'd also like it to find files newer (last accessed, modified or created) than a given date. This is easy in the network path type because I can access the FileInfo for that file, but all I have in my FTP server is a 'line' string which obviously just holds the file name.
Is it easy/possible to access the last modified/accesesed/created dates for a file on an FTP server in C#?
Unfortunately FTP provides only limited information about the remote file. With default LIST command you get OS-specific response where one date is usually present (this is usually last modification time). With MLST/MLSD extension commands you get machine-parsable response string but also with just one time.
The exact way to get the date depends on what component or class you use to access the FTP server.
If you need to get more than one date (eg. date of creation and last access), and you can go SFTP route, I'd recommend using SFTP instead.
You could use a third party library such as edtFTP to connect to the FTP server and inspect the last modified/created (not sure if you can get the the last accessed timestamp) timestamps. Its quite an easy library to use:
I need to download some files via ftp from an old AS/400 server. My code looks more or less like:
FtpWebRequest _request = (FtpWebRequest)WebRequest.Create("ftp://ftpaddress/FOO.CSV");
_request.Credentials = new NetworkCredential(_ftpUsername, _ftpPassword);
_request.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)_request.GetResponse();
However, an exception is being thrown with the message:
501 Character (/) not allowed in object name.
I'm guessing the AS400 uses a different path separator than / but I can't figure out how to phrase the uri in a way (1) FtpWebRequest accepts and (2) the AS400 understands.
Anyone else bumped into this?
According to this page, fwd slash is the path separator character:
The forward slash is the separator character for paths sent to the FTP server.
A similar conversation over at Microsoft's forums (2005 era) indicates it's a bug in FtpWebRequest:
Currently FtpWebRequest does not support quote and I cannot think of a way you'll be able to overide the method without exposing our code Mariya Atanasova [NCL]MSFT, Moderator, Nov 2005
Try updating to the most recent versions or try a different library; the MS forum thread has several.
I've had this message often in the past, and it meant that I forgot to change the name format.
There are two name formats possible when doing FTP with an AS400, and it can be changed with the FTP command NAMEFMT:
0 is for the library system files (library\filename.member)
1 is for the files in the IFS, where a CSV file would be
By default, it is set to 0.
Change it to 1 and it should work. However I'm not sure how it can be changed with a FtpWebRequest.
To make life a little bit easier, the FTP server decides what NameFormat you want to use, based on your first command. If you start with "cd /home", then the FTP server does automatically set NAMEFMT to 1 for you.
Indeed, you can change this manually during your session with the remote FTP command NAMEFMT. Please, notice that you don't need the (old) iSeries way. You can address EVERY object on the iSeries with NAMEFMT 1. For example, "get /QSYS.LIB/MYLIBRARY.LIB/MYFILE.FILE/MYMEMBER.MBR" will do the trick for any iSeries database table. Even for multimember files!
This is an aggregate answer from the ones previously provided, but I was able to get this working by using the following structure:
ftp://[HostName]/%2F/[directory]/[subdirectory]/[filename].csv
The '%2F' was required and serves as a separator between the host name and the path.