File being used by another process error - c#

Can anyone tell me how to get rid of the error
The process cannot access the file because it is being used by another process
Here is my code
if (!File.Exists(FlagFilePath))
{
Debug.WriteLine("Trying to download sales data file ");
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = ConfigurationManager.AppSettings["SFTPDomain"],
UserName = ConfigurationManager.AppSettings["SFTPUser"],
Password = ConfigurationManager.AppSettings["SFTPPass"],
PortNumber = Convert.ToInt32(ConfigurationManager.AppSettings["SFTPPortNumber"]),
GiveUpSecurityAndAcceptAnySshHostKey = true,
};
using (Session session = new Session())
{
//Attempts to connect to your SFtp site
session.Open(sessionOptions);
//Get SFtp File
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary; //The Transfer Mode - Automatic, Binary, or Ascii
transferOptions.FilePermissions = null; //Permissions applied to remote files;
transferOptions.PreserveTimestamp = false; //Set last write time of destination file
//to that of source file - basically change the timestamp to match destination and source files.
transferOptions.ResumeSupport.State = TransferResumeSupportState.Off;
//SFTP File Path
Sftp_RemotePath = ConfigurationManager.AppSettings["SFTPFileName"].ToString();
//Delete File if Exist
if (System.IO.File.Exists(FilePath))
{
System.IO.File.Delete(FilePath);
}
//the parameter list is: remote Path, Local Path with filename
TransferOperationResult transferOperationResult = session.GetFiles(Sftp_RemotePath, FilePath , false, transferOptions);
//Throw on any error
transferOperationResult.Check();
Debug.WriteLine("Downloaded fresh sales data file!");
}
}
I am using MVC and have two controllers which access this class. When I run the controllers one at a time then it works fine but when I run both controllers together then I get this error in one of the controller:
WinSCP.SessionRemoteException: Can't create file 'D:\TESTING\SFTP\Data.csv'. ---> WinSCP.SessionRemoteException: System Error.
Code: 32.
The process cannot access the file because it is being used by another process
--- End of inner exception stack trace ---
at WinSCP.OperationResultBase.Check()
at JetStarAPI.Models.SFTPClient.DownloadFile(String FilePath) in D:\TESTING\SFTP\Models\SFTPClient.cs:line 65}
I am getting this error after this line
transferOperationResult.Check();
If I change the name of the file here
TransferOperationResult transferOperationResult = session.GetFiles(Sftp_RemotePath, FilePath+Path.GetRandomFileName() , false, transferOptions);
It works fine and save the file with random file name but I want to pass my FileName. How to solve this?

static bool IsDownloadInProgress = false;
public static string DownloadFile(string FilePath)
{
string SalesStatus = "ok";
try
{
if (!File.Exists(FlagFilePath) && !IsDownloadInProgress)
{
Debug.WriteLine("Trying to download sales data file ");
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = ConfigurationManager.AppSettings["SFTPDomain"],
UserName = ConfigurationManager.AppSettings["SFTPUser"],
Password = ConfigurationManager.AppSettings["SFTPPass"],
PortNumber = Convert.ToInt32(ConfigurationManager.AppSettings["SFTPPortNumber"]),
GiveUpSecurityAndAcceptAnySshHostKey = true,
};
using (Session session = new Session())
{
//Attempts to connect to your SFtp site
session.Open(sessionOptions);
//Get SFtp File
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary; //The Transfer Mode - Automatic, Binary, or Ascii
transferOptions.FilePermissions = null; //Permissions applied to remote files;
transferOptions.PreserveTimestamp = false; //Set last write time of destination file
//to that of source file - basically change the timestamp to match destination and source files.
transferOptions.ResumeSupport.State = TransferResumeSupportState.On;
//SFTP File Path
Sftp_RemotePath = ConfigurationManager.AppSettings["SFTPFileName"].ToString();
//Delete File if Exist
if (System.IO.File.Exists(FilePath))
{
System.IO.File.Delete(FilePath);
}
//Throw on any error
session.FileTransferred += OnFileTransferComplete;
IsDownloadInProgress = true;
//the parameter list is: remote Path, Local Path with filename
// string result = Path.GetRandomFileName();
session.GetFiles(Sftp_RemotePath,FilePath,false, transferOptions).Check();
session.Dispose();
// File.Move(FilePath, "foo2.png");
Debug.WriteLine("Downloaded fresh sales data file!");
}
}
}
catch (Exception ex)
{
string _errorMsg = "";
// Setting Sales Status values
if (ex.InnerException != null)
{
if (ex.InnerException.Message.Contains("Authentication failed"))
{
_errorMsg = ex.InnerException.Message;
Debug.WriteLine("wrong username/password");
SalesStatus = "2";
}
else if (ex.InnerException.Message.Contains("No such file or directory"))
{
_errorMsg = ex.InnerException.Message;
Debug.WriteLine("File is not Available");
SalesStatus = "3";
}
}
else
{
_errorMsg = ex.Message;
Debug.WriteLine("General SFTP Error");
SalesStatus = "4";
}
//Create log error file
if (!File.Exists(FlagFilePath))
{
// create SFTP LocalErrorFlag
Debug.WriteLine("Creating SFTP flag file");
System.IO.File.WriteAllText(FlagFilePath, "SFTP Error: " + _errorMsg);
}
else
{
Debug.WriteLine("SFTP error Flag file already exists");
}
}
return SalesStatus;
}
private static void OnFileTransferComplete(object sender, TransferEventArgs e)
{
IsDownloadInProgress = false;
((Session)sender).FileTransferred -= OnFileTransferComplete;
}

Related

Downloading .mp3 file from the server and load in MediaPlayer

I want to download a .mp3 file from the localhost server, but the only problem I think is the directory that I am downloading to. Code is not giving any errors but in if(file.Exists()) is always returning false, it seems that the file is not properly downloaded.
Downloading the file:
if (isConnectedToInternet())
{
using (var client = new WebClient())
{
int numberFile = 1;
ProgressDialog pd = new ProgressDialog(Activity);
pd.SetCancelable(true);
pd.SetMessage("Pleasy wait for files to be downloaded... 0/16");
pd.Show();
client.DownloadFileCompleted += (o, s) => {
Toast.MakeText(Activity, "Download file completed.", ToastLength.Long).Show();
};
try
{
client.DownloadFileCompleted += (o, s) => {
if (numberFile == 1)
{
pd.Cancel();
}
};
string appDataDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string filePath = soundListViewAdapter.GetItemAtPosition(e.Position).path1;
if (!Directory.Exists(appDataDir))
{
Directory.CreateDirectory(appDataDir);
}
//I have to do .Remove(0,1) because filePath starts with the '/'
string path = Path.Combine(appDataDir, filePath.Remove(0, 1));
Toast.MakeText(Activity, path, ToastLength.Long).Show();
System.Uri url = new System.Uri(server + "rpad/api" + soundListViewAdapter.GetItemAtPosition(e.Position).path1);
client.DownloadFileAsync(url, path);
}
catch
{
Toast.MakeText(Activity, "Files are not downloaded", ToastLength.Long);
}
}
}
else
{
Toast.MakeText(Activity, "No connection", ToastLength.Long).Show();
}
Loading the file:
m1 = new MediaPlayer();
string appDataDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string filePath = prefs.GetString("path1", "empty");
string path = Path.Combine(appDataDir, filePath.Remove(0, 1));
Java.IO.File file = new Java.IO.File(path);
if (file.Exists())
{
FileInputStream fileStream = new FileInputStream(file);
m1.SetDataSource(fileStream.FD);
m1.Prepare();
m1.Start();
}
Code is not giving any errors but in if(file.Exists()) is always returning false, it seems that the file is not properly downloaded.
By Java.IO.File file = new Java.IO.File(path);, you are only creating a File instance. The file hasn't been created on the device. You need to call File.CreateNewFile to create this file, and before that, make sure all the parent folders are created by using Directory.CreateDirectory:
string appDataDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string filePath = "Test/empty/abc.txt";
string parentPath = Path.Combine(appDataDir, "Test/empty");
string path = Path.Combine(appDataDir, filePath);
Java.IO.File file = new Java.IO.File(path);
Directory.CreateDirectory(parentPath);//make sure the parent directory is created
file.CreateNewFile();//create the file
if (file.Exists())
{
...
}

Upload file to folder or subfolder on Sharepoint

Im trying to create a method to upload a file stream to a sharepoint so far i have this
public static void SPUploadFileStream(string username, string filePath, Stream fileData)
{
//string siteUrl = Configuration.SPSiteURL;
string siteUrl = SPContext.Current.Web.Url;
SPUser currentUser = SPUtils.GetCurrentUser(username);
if (currentUser == null)
{
throw new SPGappUnknownUserException(username);
}
using (SPSite site = new SPSite(siteUrl, currentUser.UserToken))
{
using (SPWeb web = site.OpenWeb())
{
bool allowWebUnsafeUpdt = web.AllowUnsafeUpdates;
if (!allowWebUnsafeUpdt)
web.AllowUnsafeUpdates = true;
try
{
SPCreateFolder(Path.GetDirectoryName(filePath), username);
SPFile newFile = web.Files.Add(filePath, fileData, true); //true = replace
}
catch (Exception ex)
{
LoggingService.LogError(ex);
//site.AllowUnsafeUpdates = allowSiteUnsefaUpdt;
web.AllowUnsafeUpdates = allowWebUnsafeUpdt;
throw new ApplicationException("ERROR "+ ex.ToString());
}
}
}
}
but it works ok if i have a path like "FOLDER/file.jpg" but it doesn't when i have subfolders "FOLDER/SUB/file.jpg"
can anyone give me some pointers?
My guess is that the problem lies inside your SPCreateFolder method. It should have created folders recursively. As when the you try to add new file with
SPFile newFile = web.Files.Add(filePath, fileData, true); //true = replace
the server relative path must exist. Try following method for folder creation
private static void SPCreateFolder(SPWeb web, string filepath)
{
// since you pass this as Path.GetDictionary it's no longer split by '/'
var foldersTree = filepath.Split('\\');
foldersTree.Aggregate(web.RootFolder, GetOrCreateSPFolder);
}
private static SPFolder GetOrCreateSPFolder(SPFolder sourceFolder, string folderName)
{
SPFolder destination;
try
{
// return the existing SPFolder destination if already exists
destination = sourceFolder.SubFolders[folderName];
}
catch
{
// Create the folder if it can't be found
destination = sourceFolder.SubFolders.Add(folderName);
}
return destination;
}
Then you can execute this with
...
SPCreateFolder(web, Path.GetDirectoryName(filePath));
SPFile newFile = web.Files.Add(filePath, fileData, true); //true = replace
...
Let me know if that helps

Can't restore a .bak file to a database

I have successfully restored a database using smo restore method. But when I try to restore the same .bak file to another database it returns an exception as seen below
I have created the .bak file from a database template I used which is GC_BranchName. GC_Muntinlupa is the first database I have created and restored the .bak file on to it successfully. Can anyone advise me on this?
Here is my restore code:
bool RestoreDB(string name)
{
try
{
var connection = new ServerConnection(Properties.Settings.Default.Well);
var sqlServer = new Server(connection);
var rstDatabase = new Restore();
rstDatabase.Database = name;
rstDatabase.Action = RestoreActionType.Database;
rstDatabase.Devices.AddDevice(System.Environment.CurrentDirectory + "\\GC.bak", DeviceType.File);
rstDatabase.ReplaceDatabase = true;
rstDatabase.SqlRestore(sqlServer);
connection.Disconnect();
return true;
}
catch (Exception ex)
{
MessageBox.Show("A problem occured when building the branch!" + ex, "Monytron Consolidator", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
Sorry J.P Masangcay but i didn't had time to put it all together for you until now.
Here is the solution that works for you, verified by me.
Your problem is that you have file conficts if you restore your database backup to a new database.
Why file conflicts?
The default behavior of SQL Server is to restore the database using file paths and names for data and log files as they have been at the time of the backup. Therefore, if that originating database exists at the time of the restore process this leads to filesystem conflicts. They same conflict arises if you restore your database backup template to another server multiple times.
Your Case:
Database: GC_BranchName
Data File: GC_BranchName.mdf
Log File: GC_BranchName_log.ldf
Resore Database: GC_Muntinlupa
Data File: GC_BranchName.mdf
Log File: GC_BranchName_log.ldf
To solve the proplem you have to relocate files to have distinct filenames for your databases. Here is a solution, which simply adds/prepends the "new database name" to all files. This relocating under the hood restores the database using the TSQL "RESTORE DATABASE ... WITH MOVE" option, as your exception above is suggesting.
Resore Database: GC_Muntinlupa
Data File: GC_Muntinlupa_GC_BranchName.mdf
Log File: GC_Muntinlupa_GC_BranchName_log.ldf
bool RestoreDB(string name)
{
try
{
var connection = ServerConnection(Properties.Settings.Default.Well);
var sqlServer = new Server(connection);
var rstDatabase = new Restore();
rstDatabase.Database = name;
rstDatabase.Action = RestoreActionType.Database;
rstDatabase.Devices.AddDevice(System.Environment.CurrentDirectory + "\\GC.bak", DeviceType.File);
rstDatabase.ReplaceDatabase = true;
foreach (DataRow r in rstDatabase.ReadFileList(sqlServer).Rows)
{
var relocateFile = new RelocateFile();
relocateFile.LogicalFileName = r["LogicalName"].ToString();
// move/rename physical filename by prepending database name to prevent FileSystem conflicts
var physicalName = r["PhysicalName"].ToString();
var path = System.IO.Path.GetDirectoryName(physicalName);
var filename = System.IO.Path.GetFileName(physicalName);
physicalName = System.IO.Path.Combine(path, string.Format("{0}_{1}", name, filename));
relocateFile.PhysicalFileName = physicalName;
rstDatabase.RelocateFiles.Add(relocateFile);
}
rstDatabase.SqlRestore(sqlServer);
connection.Disconnect();
return true;
}
catch (Exception ex)
{
MessageBox.Show("A problem occured when building the branch!" + ex, "Monytron Consolidator", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
This should solve the issue
namespace DB_Restore
{
class Program
{
static void Main(string[] args)
{
RestoreDatabase();
}
public static void RestoreDatabase()
{
try
{
ServerConnection connection = new ServerConnection(#"Server\instance", "uname", "PWD");
Server sqlServer = new Server(connection);
Restore rstDatabase = new Restore();
rstDatabase.Action = RestoreActionType.Database;
rstDatabase.Database = "H5MI_Automation_Restore_Backup";
BackupDeviceItem bkpDevice = new BackupDeviceItem(#"E:\DATA\QA_SP\MSSQL11.QA_SP\MSSQL\Backup\H5MI_Automation.bak", DeviceType.File);
rstDatabase.Devices.Add(bkpDevice);
rstDatabase.ReplaceDatabase = true;
//As mentioned in the above solution this code will take care .mdf and .ldf file location issue
foreach (DataRow r in rstDatabase.ReadFileList(sqlServer).Rows)
{
var relocateFile = new RelocateFile();
relocateFile.LogicalFileName = r["LogicalName"].ToString();
Console.WriteLine(relocateFile.LogicalFileName);
var physicalName = r["PhysicalName"].ToString();
Console.WriteLine(physicalName);
var path = System.IO.Path.GetDirectoryName(physicalName);
Console.WriteLine(path);
var filename = System.IO.Path.GetFileName(physicalName);
Console.WriteLine(filename);
physicalName = path + #"\H5MI_Automation_Restore_Backup_" + filename;
Console.WriteLine(physicalName);
relocateFile.PhysicalFileName = physicalName;
Console.WriteLine(relocateFile.PhysicalFileName);
Console.WriteLine(relocateFile);
rstDatabase.RelocateFiles.Add(relocateFile);
}
rstDatabase.SqlRestore(sqlServer);
connection.Disconnect();
}
catch (Exception e)
{
Console.Write(e);
}
}
}
}
Add the explanation of the code. Essentially the issue in the above-attached screenshot is because of the .mdf and .ldf file location. When you try to manually restore the DB u will also face the same issue. attaching the screenshot.Manual DB restore
Why its throwing error?
Its because the file is used by the actual DB(from where .bak file is genrated)
So, this piece of code will help you to change the location of both .mdf and .ldf file path.
foreach (DataRow r in rstDatabase.ReadFileList(sqlServer).Rows)
{
var relocateFile = new RelocateFile();
relocateFile.LogicalFileName = r["LogicalName"].ToString();
Console.WriteLine(relocateFile.LogicalFileName);
var physicalName = r["PhysicalName"].ToString();
Console.WriteLine(physicalName);
var path = System.IO.Path.GetDirectoryName(physicalName);
Console.WriteLine(path);
var filename = System.IO.Path.GetFileName(physicalName);
Console.WriteLine(filename);
physicalName = path + #"\H5MI_Automation_Restore_Backup_" + filename;
Console.WriteLine(physicalName);
relocateFile.PhysicalFileName = physicalName;
Console.WriteLine(relocateFile.PhysicalFileName);
Console.WriteLine(relocateFile);
rstDatabase.RelocateFiles.Add(relocateFile);
}

BackupDevice.PhysicalLocation does not add to specified location

Using C# and SMO, when I create backups they are being copied to the default backup location used by SQL Server (C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\Backup), instead of the physical location that I specify in code:
Database database = Server.Databases[dbName]);
Backup backup = new Backup();
device = new BackupDevice();
device.Parent = Server;
device.Name = dbName + ".bak";
device.BackupDeviceType = BackupDeviceType.Disk;
device.PhysicalLocation = Path.Combine(filePath + device.Name); // doesn't appear to do anything
device.Create();
backup.Action = BackupActionType.Database;
backup.Database = database.Name;
backup.Devices.AddDevice(filePath, DeviceType.File);
backup.SqlBackup(server);
When I run my code, I find that the path that I specified ("C:\backupTest") is empty and the backup has been added to the default backup location.
Anyone know why this is?
try with below code
static void BackupDataBase(string databaseName, string destinationPath)
{
try
{
Server myServer = GetServer();
Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = databaseName;
destinationPath = System.IO.Path.Combine(destinationPath, databaseName + ".bak");
backup.Devices.Add(new BackupDeviceItem(destinationPath, DeviceType.File));
backup.Initialize = true;
backup.Checksum = true;
backup.ContinueAfterError = true;
backup.Incremental = false;
backup.LogTruncation = BackupTruncateLogType.Truncate;
backup.SqlBackup(myServer);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private static Server GetServer()
{
ServerConnection conn = new ServerConnection("server", "username", "pw");
Server myServer = new Server(conn);
return myServer;
}
refere this codeproject article for more information.

Problems uploading files using Chilkat

I am trying to upload a file to a Server using sftp. I have downloaded and installed Chilkat and i am downloading files without any issues. But when i try to upload files to the server, i get no error stating that the uploading files. When i check for response messages, it says "file upload success 1" and one is true But the files doesn't get uploaded to the server.
this is my code:
public void UploadAndMoveFile()
{
bool success = false;
string path = #"\\geodis\";
string archive = #"\\Archive\";
string[] files = Directory.GetFiles(path);
if (files.Count() == 0)
{
//no files
}
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string fileSource = path + fileName;
string fileDestination = archive + fileName;
string handle;
string ftp = #"\IN\"+fileName;
handle = sftp.OpenFile(ftp, "writeOnly", "createTruncate");
if (handle == null)
{
Console.WriteLine(sftp.LastErrorText);
return;
}
success = sftp.UploadFile(handle, fileSource);
if (success == true)
{
AppendLogFile("Uploading File Succeeded", "Uploade File", fileName);
System.IO.File.Move(fileSource, fileDestination);
AppendLogFile("Moving File Succeeded", "Moving File", fileName);
}
else
{
// no files
}
}
}
Can anyone help me find out what I am doing wrong?
Found the Issue, in the upload method i had handle variable instead of the ftp variable.
here is the solution:
public void UploadAndMoveFile()
{
bool success = false;
string path = #"\\geodis\";
string archive = #"\\Archive\";
string[] files = Directory.GetFiles(path);
if (files.Count() == 0)
{
//no files
}
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string fileSource = path + fileName;
string fileDestination = archive + fileName;
string handle;
string ftp = #"\IN\"+fileName;
handle = sftp.OpenFile(ftp, "writeOnly", "createTruncate");
if (handle == null)
{
Console.WriteLine(sftp.LastErrorText);
return;
}
success = sftp.UploadFile(ftp, fileSource);
if (success == true)
{
AppendLogFile("Uploading File Succeeded", "Uploade File", fileName);
System.IO.File.Move(fileSource, fileDestination);
AppendLogFile("Moving File Succeeded", "Moving File", fileName);
}
else
{
// no files
}
}
}

Categories

Resources