问候朋友,
FileStream或Process,请帮助弄清楚。
以下Windows窗体应用程序首先从openFileDialog1中选择一个或多个文件,检查这些文件是否在数据库中(GetInsertNummer),然后将它们写入数据库(InsertInTable)。
然后,它从数据库读取它们并在Windows(FileGetSimple)中写入。接下来,打开,关闭这些文件,然后通过电子邮件(CreateMessage)发送这些文件。
一切似乎都正常,但是当反复选择文件或Excel格式的文件时,会引发此异常。
该进程无法访问文件”,因为它正在被另一个进程使用。
[运行程序时,我只按了一次按钮(btnSales_Click。)第一次,一切正常。
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Globalization;
using System.Diagnostics;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.Net.Mime;
//using System.Threading.Tasks;
namespace GebrNaimSalesWindowsForms
{
public partial class Form1 : Form
{
//SqlConnection con = new SqlConnection(@"Data Source=DESKTOP-E2S6MTB\SQLEXPRESS;Initial Catalog=GebrNaimProject;Integrated Security=True");
//SqlDataAdapter adapt;
//public string[] files { get; set; }
public List<string> files { get; set; }
public List<string> outputfiles { get; set; }
public int insertNummer;
public int row_id;
public Process sp;
public string ExceptionMessage { get; set; }
public Form1()
{
InitializeComponent();
//DisplayData();
}
//Display Data in DataGridView
//private void DisplayData()
//{
// con.Open();
// DataTable dt = new DataTable();
// adapt = new SqlDataAdapter("select * from StoredFile", con);
// adapt.Fill(dt);
// dataGridView1.DataSource = dt;
// con.Close();
//}
private void btnSales_Click(object sender, EventArgs e)
{
outputfiles = null;
files = null;
sp = null;
//sp.Refresh();
if (InformationWindow("Выбирете пожалйста фалы и сохраните в Windows", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.OK)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
foreach (var item in openFileDialog1.FileNames)
{
//files.Add(item);
files = new List<string>();
files.Add(item);
}
}
else
{
files = null;
}
GetInsertNummer(@"SELECT (SELECT MAX(id) FROM StoredFile) id, MAX(InsertNummer) InsertNummer
FROM StoredFile");
if (files != null)
{
for (int i = 0; i < files.Count; i++)
{
InsertInTable(i);
row_id++;
FileGetSimple(row_id, files[i]);
}
InformationWindow("Все в порядке с выбранными файлами?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
CreateMessage("smtp.strato.de");
MessageBox.Show("success");
}
//DisplayData();
}
}
public DialogResult InformationWindow(string v1, string v2, MessageBoxButtons oKCancel, MessageBoxIcon information)
{
string message = v2;
string caption = v1;
MessageBoxButtons buttons = oKCancel;
DialogResult result;
// Displays the MessageBox.
return result = MessageBox.Show(message, caption, buttons, information);
}
public void CreateMessage(string server)
{
using (SmtpClient client = new SmtpClient(server))
{
client.Port = 587;
client.EnableSsl = true;
client.Credentials = new NetworkCredential("[email protected]", "");
MailAddress from = new MailAddress("---",--- );
MailAddress to = new MailAddress("---", ---);
MailMessage message = new MailMessage(from, to);
// message.Subject = "Using the SmtpClient class.";
message.Subject = "Es funktioniert.";
message.Body = @"Вы получили письмо с вложением";
foreach (var item in outputfiles)
{
if (!sp.HasExited)
{
//sp.WaitForExit();
sp.Kill();
//if (Marshal.IsComObject(sp))
//{
// Marshal.ReleaseComObject(sp);
//}
//Marshal.ReleaseComObject(sp);
}
else
sp = null;
//sp.WaitForExit();
//sp.Close();
//Process[] ps2 = System.Diagnostics.Process.GetProcessesByName("EXCEL");
//foreach (Process p2 in ps2)
//{
// Marshal.ReleaseComObject(p2);
// p2.Kill();
//}
message.Attachments.Add(new Attachment(item));
}
InformationWindow("Success", $"Sending an email message to" + to.Address + " by using the SMTP host " + client.Host + ".", MessageBoxButtons.OK, MessageBoxIcon.Information);
try
{
client.Send(message);
}
catch (Exception ex)
{
// Me.WriteLine("Exception caught in CreateCopyMessage(): {0}",ex.ToString());
InformationWindow("Exception", ex.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
//
}
}
//using(SmtpClient smtpClient = new SmtpClient())
//{
// var basicCredential = new NetworkCredential("username", "password");
// using(MailMessage message = new MailMessage())
// {
// MailAddress fromAddress = new MailAddress("[email protected]");
// smtpClient.Host = "mail.mydomain.com";
// smtpClient.UseDefaultCredentials = false;
// smtpClient.Credentials = basicCredential;
// message.From = fromAddress;
// message.Subject = "your subject";
// // Set IsBodyHtml to true means you can send HTML email.
// message.IsBodyHtml = true;
// message.Body = "<h1>your message body</h1>";
// message.To.Add("[email protected]");
// try
// {
// smtpClient.Send(message);
// }
// catch(Exception ex)
// {
// //Error, could not send the message
// Response.Write(ex.Message);
// }
// }
//}
private void InsertInTable(int i)
{
// **** Write BLOB to the Database
byte[] filebyte = File.ReadAllBytes(files[i]);
string sql = @"insert into StoredFile(FileName,Data,InsertNummer,Date) values(@FileName,@Data,@InsertNummer,@Date)";
var cmd = MakeConnection(sql);
SqlParameter parameter1 = cmd.Parameters.AddWithValue("@FileName", Path.GetFileName(files[i]));
SqlParameter parameter2 = cmd.Parameters.AddWithValue("@Data", filebyte);
SqlParameter parameter3 = cmd.Parameters.AddWithValue("@InsertNummer", insertNummer);
SqlParameter parameter4 = cmd.Parameters.AddWithValue("@Id", row_id);
SqlParameter parameter5 = cmd.Parameters.AddWithValue("@Date", DateTime.Now);
cmd.ExecuteNonQuery();
}
public bool FileGetSimple(int Identifier, string filePath)
{
var pa = Path.Combine(Path.GetTempPath(), Path.GetFileName(filePath));
var statement = "SELECT Id, Data, FileName FROM StoredFile WHERE Id = @id;";
var mc = MakeConnection(statement);
mc.Parameters.AddWithValue("@id", Identifier);
SqlDataReader reader = mc.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
// the blob field
int ndx = reader.GetOrdinal("Data");
var blob = new Byte[(reader.GetBytes(ndx, 0, null, 0, int.MaxValue))];
reader.GetBytes(ndx, 0, blob, 0, blob.Length);
reader.Close();
try
{
//using (var fs = new FileStream(pa, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
//{
// fs.Write(blob, 0, blob.Length);
//}
if (File.Exists(pa))
{
File.Delete(pa);
}
using (var fs = new FileStream(pa, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
fs.Write(blob, 0, blob.Length);
}
//using (FileStream fs = File.Create(pa))
//{
// fs.Write(blob, 0, blob.Length);
//}
//using (var stream = File.Create(pa))
//{
//File.WriteAllBytes(pa, blob);
//}
}
catch (IOException e) {
InformationWindow("Warning", e.Message + " Schließen Sie diese Datei, um fortzusetzen.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
FileGetSimple(Identifier, filePath);
}
}
OpenFiles(pa);
return true;
}
private void OpenFiles(string tempFilePath)
{
using (sp = new Process())
{
sp = Process.Start(tempFilePath);
}
outputfiles = new List<string>();
outputfiles.Add(tempFilePath);
}
public void GetInsertNummer(string ins_num_query)
{
var ins_num = MakeConnection(ins_num_query);
SqlDataReader read_ins_nummer = ins_num.ExecuteReader();
while (read_ins_nummer.Read())
{
int ins = read_ins_nummer.GetOrdinal("InsertNummer");
int ins_id = read_ins_nummer.GetOrdinal("Id");
if (!read_ins_nummer.IsDBNull(read_ins_nummer.GetOrdinal("InsertNummer")))
{
insertNummer = read_ins_nummer.GetInt32(ins);
row_id = read_ins_nummer.GetInt32(ins_id);
insertNummer++;
}
else
{
insertNummer = 1;
row_id = 0;
}
}
}
public SqlCommand MakeConnection(string sql)
{
SqlConnection connection = new SqlConnection(Properties.Settings.Default.connection_str);
connection.Open();
using (SqlCommand cmd = new SqlCommand() { Connection = connection, CommandText = sql })
{
try
{
return cmd;
}
catch (Exception ex)
{
ExceptionMessage = ex.Message;
return cmd;
}
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
//this.Close();
Application.Exit();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'gebrNaimProjectDataSet.StoredFile' table. You can move, or remove it, as needed.
//this.storedFileTableAdapter.Fill(this.gebrNaimProjectDataSet.StoredFile);
}
}
}
查看您的代码(在注释中:):
public partial class Form1 : Form
{
public List<string> files { get; set; }
public List<string> outputfiles { get; set; }
// these fields are public but not properties, why?
public int insertNummer;
public int row_id;
public Process sp;
public string ExceptionMessage { get; set; }
public Form1()
{
InitializeComponent();
}
private void btnSales_Click(object sender, EventArgs e)
{
outputfiles = null;
files = null;
sp = null;
// didn't compile
if (InformationWindow("Выбирете пожалйста фалы и сохраните в Windows", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.OK)
{
// invert and return
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
foreach (var item in openFileDialog1.FileNames)
{
files = new List<string>();
files.Add(item);
}
}
else
{
// useless since files is already null at this point
files = null;
}
GetInsertNummer(@"SELECT (SELECT MAX(id) FROM StoredFile) id, MAX(InsertNummer) InsertNummer FROM StoredFile");
// useless if return above
if (files != null)
{
for (int i = 0; i < files.Count; i++)
{
InsertInTable(i);
// use ++row_id in FileGetSimple instead
row_id++;
FileGetSimple(row_id, files[i]);
}
// doesn't compile
InformationWindow("Все в порядке с выбранными файлами?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
CreateMessage("smtp.strato.de");
MessageBox.Show("success");
}
}
}
public DialogResult InformationWindow(string v1, string v2, MessageBoxButtons oKCancel, MessageBoxIcon information)
{
// bad practise, rename v1 to caption and v2 to message in method parameter
string message = v2;
string caption = v1;
// unnecessary variable definitions, also weird name "oKCancel" for dynamically assigned MessageBoxButtons that aren't always Ok/Cancel?
MessageBoxButtons buttons = oKCancel;
DialogResult result;
// Displays the MessageBox.
// return the value directly instead of an unneeded assignment
return result = MessageBox.Show(message, caption, buttons, information);
}
public void CreateMessage(string server)
{
using (SmtpClient client = new SmtpClient(server))
{
client.Port = 587;
client.EnableSsl = true;
client.Credentials = new NetworkCredential("[email protected]", "");
// didn't compile ---
MailAddress from = new MailAddress("---", "");
MailAddress to = new MailAddress("---", "");
MailMessage message = new MailMessage(from, to);
message.Subject = "Es funktioniert.";
// unnecessary @
message.Body = @"Вы получили письмо с вложением";
// outputfiles will always only contain a single file --> the loop will only run once, ever!
foreach (var item in outputfiles)
{
// dispose of possibly previously disposed process, not necessary or using statement of sp not necessary
if (!sp.HasExited)
{
sp.Kill();
}
else
sp = null;
message.Attachments.Add(new Attachment(item));
}
InformationWindow("Success", $"Sending an email message to" + to.Address + " by using the SMTP host " + client.Host + ".", MessageBoxButtons.OK, MessageBoxIcon.Information);
try
{
client.Send(message);
}
catch (Exception ex)
{
InformationWindow("Exception", ex.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void InsertInTable(int i)
{
// **** Write BLOB to the Database
byte[] filebyte = File.ReadAllBytes(files[i]);
// unnecessary variable declaration (it's only used once), put statement directly in MakeConnection("...")
string sql = @"insert into StoredFile(FileName,Data,InsertNummer,Date) values(@FileName,@Data,@InsertNummer,@Date)";
var cmd = MakeConnection(sql);
// unnecessary variable declarations, parameter1..5 is never used anywhere
SqlParameter parameter1 = cmd.Parameters.AddWithValue("@FileName", Path.GetFileName(files[i]));
SqlParameter parameter2 = cmd.Parameters.AddWithValue("@Data", filebyte);
SqlParameter parameter3 = cmd.Parameters.AddWithValue("@InsertNummer", insertNummer);
SqlParameter parameter4 = cmd.Parameters.AddWithValue("@Id", row_id);
SqlParameter parameter5 = cmd.Parameters.AddWithValue("@Date", DateTime.Now);
cmd.ExecuteNonQuery();
}
public bool FileGetSimple(int Identifier, string filePath)
{
// why did you start using var instead of the types?
var pa = Path.Combine(Path.GetTempPath(), Path.GetFileName(filePath));
var statement = "SELECT Id, Data, FileName FROM StoredFile WHERE Id = @id;";
var mc = MakeConnection(statement);
mc.Parameters.AddWithValue("@id", Identifier);
SqlDataReader reader = mc.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
// the blob field
int ndx = reader.GetOrdinal("Data");
// that is wrong and not how to read a buffer, read up on how to use buffers/GetBytes correctly!
var blob = new Byte[(reader.GetBytes(ndx, 0, null, 0, int.MaxValue))];
// oh jeez
reader.GetBytes(ndx, 0, blob, 0, blob.Length);
reader.Close();
try
{
if (File.Exists(pa))
{
File.Delete(pa);
}
using (var fs = new FileStream(pa, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
fs.Write(blob, 0, blob.Length);
}
}
catch (IOException e)
{
InformationWindow("Warning", e.Message + " Schließen Sie diese Datei, um fortzusetzen.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
FileGetSimple(Identifier, filePath);
}
}
// function is called OpenFiles but only a single file is supplied?
OpenFiles(pa);
return true;
}
private void OpenFiles(string tempFilePath)
{
// what is this even supposed to do?
// create new process instance
using (sp = new Process())
{
// then throw away the instance and start a process instead
sp = Process.Start(tempFilePath);
// then dispose process
}
// quiz: has new Process() or Process.Start been disposed by the using statement?
// every time a file is opened the outputfiles list is re-initialized and a single element is addded?
// it's never going to contain more than one element!
outputfiles = new List<string>();
outputfiles.Add(tempFilePath);
}
public void GetInsertNummer(string ins_num_query)
{
// using dynamic sql statements but accessing columns statically, how do you guarantee that these columns exist?
// is there a point in providing a parameter, why can the statement not be inside this function, it never changes!
var ins_num = MakeConnection(ins_num_query);
SqlDataReader read_ins_nummer = ins_num.ExecuteReader();
while (read_ins_nummer.Read())
{
int ins = read_ins_nummer.GetOrdinal("InsertNummer");
int ins_id = read_ins_nummer.GetOrdinal("Id");
// use previously defined variable "ins" instead of re-executing GetOrdial
if (!read_ins_nummer.IsDBNull(read_ins_nummer.GetOrdinal("InsertNummer")))
{
// insertNummer and row_id is the same, dont' execute GetInt32 twice, use the same value instead!
insertNummer = read_ins_nummer.GetInt32(ins);
row_id = read_ins_nummer.GetInt32(ins_id);
insertNummer++;
}
else
{
insertNummer = 1;
row_id = 0;
}
}
}
public SqlCommand MakeConnection(string sql)
{
SqlConnection connection = new SqlConnection("");
connection.Open();
// you're using object initializer here, why not everywhere else?
using (SqlCommand cmd = new SqlCommand() { Connection = connection, CommandText = sql })
{
try
{
return cmd;
}
catch (Exception ex)
{
// this is never used anywhere
ExceptionMessage = ex.Message;
return cmd;
}
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
很难阅读,甚至更难弄清楚应该发生什么。看起来像是从不同教程/ stackoverflow帖子中复制/粘贴frankencode。 YOU知道发生了什么吗? I应该如何?
也,
FileStream或Process,请帮助弄清楚
你怎么不知道?您正在获取异常,您应该知道异常发生的位置。
抱歉,此答案没有用,但可能是您得到的最好的答案。提供minimal, reproducible example,然后再次询问。