Firebird embedded multiple user support - c#

I'm trying to create an app that communicate with a Firebird 3.0 embedded database.
I need that two or more of my app instances can connect and edit the same database at the same time.
I had create the connection part and it works.
When I start the first instance it connects correctly, but when I try to access to the database with another app it raise this error: Error while trying to open file -Impossible to open the file.
I also had try to connect with different account for example user2 and user1 (manually created with isql) but without results.
I search on google all day but I found nothing.
Any suggestion? Thanks in advance
This is the acutal code:
using System;
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 Firebird;
namespace Firebird_multiuser
{
public partial class Form1 : Form
{
//private TextBox console = new TextBox();
Firebird.Firebird conn = new Firebird.Firebird();
public Form1()
{
InitializeComponent();
input_box.Text = #"G:\Coding\oribruniv8\Firebird\Firebird_multiuser\test.fdb";
}
private void button1_Click(object sender, EventArgs e)
{
if (conn.connect(input_box.Text))
console.AppendText("Successfully connect to database\n");
else
{
console.AppendText("Error during connection ...\n");
return;
}
}
}
}
Firebird class
using FirebirdSql.Data.FirebirdClient;
using FirebirdSql.Data.Isql;
namespace Firebird
{
public class Firebird
{
FbConnectionStringBuilder csb = new FbConnectionStringBuilder();
int pageSize = 8192;
bool forcedWrites = true;
bool overwrite = true;
FbConnection conn;
public Firebird()
{
csb.ClientLibrary = **correct path to fbclient.dll**;
csb.UserID = "sysdba";
csb.Password = "masterkey";
csb.ServerType = FbServerType.Embedded;
}
public bool create(string path)
{
csb.Database = path;
FbConnection.CreateDatabase(csb.ToString(), pageSize, forcedWrites, overwrite);
this.conn = new FbConnection(csb.ToString());
this.conn.Open();
return this.connection_check();
}
public bool connect(string path)
{
csb.Database = path;
this.conn = new FbConnection(csb.ToString());
this.conn.Open();
return this.connection_check();
}
public void query(string SQLquery)
{
this.conn.Open();
using (var transaction = this.conn.BeginTransaction())
using (var command = new FbCommand())
{
command.Connection = this.conn;
command.Transaction = transaction;
command.CommandText = SQLquery;
command.ExecuteNonQuery();
transaction.Commit();
}
}
private bool connection_check()
{
if (this.conn.State == ConnectionState.Open)
{
conn.Close();
return true;
}
else
{
return false;
}
}
}
}

If you want two or more apps to connect to the same database, it is time to consider installing Firebird server instead.
That said, if you are using Firebird 3 embedded, it is possible. By default, Firebird 3 embedded will require exclusive access to the database. This can be changed by making sure there is a firebird.conf in the same location as your fbclient.dll used by your application, and setting the ServerMode setting to SuperClassic (or ThreadedShared).
Doing this carries a small risk. If the database is shared, then all processes must use the same lock files. By default that is the case, but if applications have different FIREBIRD_LOCK environment variable settings, this can corrupt a database as each process will think it doesn't have contenders for its locks.

Related

Database insert on FileSystemEventHandler with Windows Service

I have managed to get the Service working, along with the FileSystemEventHandler inserting into a text file, but this now needs to be changed to insert into a database and a text file.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace WindowsServiceTest
{
public partial class Service1 : ServiceBase
{
Timer timer = new Timer(); // name space(using System.Timers;)
public static string path = ConfigurationManager.AppSettings["findpath"];
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WriteToFile("Service is started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 10000; //number in milisecinds
timer.Enabled = true;
FileSystemWatcher watcher = new FileSystemWatcher
{
Path = path,
NotifyFilter = NotifyFilters.LastWrite,
};
watcher.Created += new FileSystemEventHandler(FileSystemWatcher_Changed);
watcher.Renamed += new RenamedEventHandler(FileSystemWatcher_Renamed);
watcher.Changed += new FileSystemEventHandler(FileSystemWatcher_Changed);
watcher.EnableRaisingEvents = true;
}
public static void FileSystemWatcher_Changed(object source, FileSystemEventArgs e)
{
using (SqlConnection con = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Database=ServiceTest;Integrated Security=True;"))
{
try
{
con.Open();
var command = new SqlCommand("Insert into test(URL, Location) values(#URL, #agendaname);", con);
command.Parameters.Add("#URL", System.Data.SqlDbType.VarChar, 100).Value = e.Name;
command.Parameters.Add("#agendaname", System.Data.SqlDbType.VarChar, 100).Value = "Case History";
command.ExecuteNonQuery();
}
catch
{
WriteToFile($"Failed to insert: {e.Name} into the database");
}
}
}
public static void FileSystemWatcher_Renamed(object source, RenamedEventArgs e)
{
WriteToFile($"File Renamed: {e.OldFullPath} renamed to {e.FullPath}");
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
WriteToFile("Service is recalled at " + DateTime.Now);
}
protected override void OnStop()
{
WriteToFile("Service is stopped at " + DateTime.Now);
}
public static void WriteToFile(string Message)
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\ServiceLog_" + DateTime.Now.Date.ToShortDateString().Replace('/', '_') + ".txt";
if (!File.Exists(filepath))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(filepath))
{
sw.WriteLine(Message);
}
}
else
{
using (StreamWriter sw = File.AppendText(filepath))
{
sw.WriteLine(Message);
}
}
}
}
}
I think that I've done the database insert wrong because the catch block is being inserted into the text file. However, I've run the code by itself in a separate project and was inserting into the database in a Console Application.
Any help is appreciated, kind regards.
Windows services run under a different security context than console apps. As the comments have disclosed, the exception is related to your connection string.
If we analyze the connectiong string we can see that you are authenticating with IntegratedSecurity="True". Because your windows service is running under
a service account authentication is failing. I've specified 2 options for resolving this.
Option 1: Have Service run as windows account (Not recommended but will work for testing)
Open run box (Win Flag + R)
Type Services.MSC
Locate your service and right click properties
Choose the logon tab
Enter your windows auth username and password for service to run as
Option 2: Create SQL Server account
Create username and password in SQL for database
Update connection string to specify new username and password created

Clearing DropDown List with Invalidate() Outlook Addin C#

Ribbon1.cs using Ribbon Designer (ie, no XML)
I am trying to clear the contents of a Drop Down list before repopulating the list with new data.
I have tried using Invalidate() in several places but I can't get it to work.
The flow of the Addin is as followed:
Copy text to clipboard -> works
Click Search -> works
Get new Data from Database using text from Clipboard -> works
Clear Dropdown -> doesn't work
Populate Drop Down with data. -> Does work but add items to drop down instead of
clearing it first
Thanks in advance
using System;
using System.Collections.Generic;
using System.IO;
using System.Data;
using System.Data.Odbc;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Office = Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Tools.Ribbon;
namespace MSTEST
{
public partial class Ribbon1 : Office.IRibbonExtensibility
{
private Office.IRibbonUI ribbon;
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
this.ribbon = RibbonUI;
}
private void eventDB(object sender, RibbonControlEventArgs e)
{
RibbonUI.Invalidate();
//this.ribbon.InvalidateControl("resultsDB");
string getTextFromClipboard = Clipboard.GetText();
string queryString = "select distinct file_path as FP, case_id as CS, date_added from documents CONTAINS(documents.file_path, '" + getTextFromClipboard + "') group by case_id,file_path, datE_added order by Date_Added DESC";
using (OdbcConnection odbcConnection = new OdbcConnection("dsn=Needles;UID=dba;PWD=sql;"))
{
OdbcCommand command = new OdbcCommand(queryString, odbcConnection);
try
{
odbcConnection.Open();
OdbcDataReader reader = command.ExecuteReader();
// ribbon.InvalidateControl("resultsDB");
int i = 0;
while (reader.Read())
{
// Being DropDown Populate
RibbonDropDownItem item = this.Factory.CreateRibbonDropDownItem();
item.Label = reader["FP"].ToString();
resultsDB.Items.Add(item);
//MessageBox.Show(reader["CS"].ToString());
// End DropDown Populate
i = i + 1;
}
reader.Close();
odbcConnection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
public string GetCustomUI(string RibbonID)
{
throw new NotImplementedException();
}
}
}
I have solved this by tinkering around with the Clear() function of the object. example: resultsDB.Items.Clear();

How to connect to instrument through USB using c#

I am trying to use the Ivi.Visa.Interop .dll to communicate to a Voltech PM1000+ power meter using USB. I'm relatively new to C# and do not know really where to start. I am using Visual Studio 2015 Community. I have already talked to a different instrument using GPIB and here is the code for that:
using System;
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 Ivi.Visa.Interop;
namespace commOverIP
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void InitiateIOBtn_Click(object sender, EventArgs e)
{
///testing out excel
InitiateIOBtn.Text = "Initializing";
try
{
// resource manager and message-based session manager
Ivi.Visa.Interop.ResourceManager mngr = new Ivi.Visa.Interop.ResourceManager();
// GPIB address
string srcAddress = "GPIB::27::INSTR"; // GPIB address of data acquisition
//setting up communication
Ivi.Visa.Interop.FormattedIO488 instrument = new Ivi.Visa.Interop.FormattedIO488();
Ivi.Visa.Interop.IMessage Imsg = (mngr.Open(srcAddress, Ivi.Visa.Interop.AccessMode.NO_LOCK, 1000, "") as IMessage);
instrument.IO = Imsg;
instrument.IO.Clear();//clear io buffer
instrument.WriteString("*RST", true);//send RST? command to instrument
instrument.WriteString("*IDN?", true);//send IDN? command to instrument
returnOfCommand.Text = instrument.ReadString();//read IDN? result
//close communication
instrument.IO.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(instrument);
System.Runtime.InteropServices.Marshal.ReleaseComObject(mngr);
InitiateIOBtn.Text = "Initialize I/O";
//*/
}
catch(Exception exp)
{
MessageBox.Show(exp.Message);
}
InitiateIOBtn.Text = "Initialize I/O";
}
}
}
This works fine but USB seems to be a different beast. The only real lead I found was in the .dll with the:
IUsb.Init(string, Ivi.Visa.Interop.AccessMode, int, string)
I tried implementing this but I don't really know where to start.
If anyone could give me an example of how to query a "*IDN?" command that would be great. Or, even if there is a better way of doing this than through the Ivi.Visa.Interop dll.
Thanks in advance
Restart your device once. Clearing the IO also helps. Afterwards following code should work fine:
string resourceString= "USB0::xxx::xxx::xxx::0::INSTR";
ResourceManager manager = new ResourceManager();
FormattedIO488 connection = new FormattedIO488();
connection.IO = (IMessage)manager.Open(resourceString, AccessMode.NO_LOCK, 0, "");
connection.IO.Clear();
connection.WriteString("*IDN?", true);
string result = connection.ReadString();
I do what you are asking all of the time and I completely understand how frustrating it can be. I remember doing Google searches to come up with this code. The code actually came from some Keysight documentation when I bought the Agilent 82357B USB/GPIB Controller.
This can be adapted for any GPIB instrument, the only difference being the strings that you send to the instrument. These can be obtained by getting the programming manual for the instrument in which you're interested.
I installed the Keysight (formerly Agilent) I/O Library Suites that is used with the Agilent 82357B. One thing that is not obvious is that you should disable the 'Auto Discovery' option, as this feature will occasionally put your device in Local mode.
using System.Threading;
using System.Runtime.InteropServices;
// Add reference for VISA-COM 5.9 Type Library
using Ivi.Visa.Interop;
namespace USBCommunications
{
class Program
{
static void Main(string[] args)
{
Gpib.Write(address: 5, command: "*IDN?");
bool success = Gpib.Read(address: 5, valueRead: out string valueRead);
System.Console.WriteLine($"The ID is {valueRead}");
System.Console.ReadLine();
}
}
public class Gpib
{
static ResourceManager resourceManager;
static FormattedIO488 ioObject;
public static bool Write(byte address, string command)
{
resourceManager = new ResourceManager();
ioObject = new FormattedIO488();
string addr = $"GPIB::{address.ToString()}::INSTR";
try
{
ioObject.IO = (IMessage)resourceManager.Open(addr, AccessMode.NO_LOCK, 0, "");
Thread.Sleep(20);
ioObject.WriteString(data: command, flushAndEND: true);
return true;
}
catch
{
return false;
}
finally
{
try { ioObject.IO.Close(); }
catch { }
try { Marshal.ReleaseComObject(ioObject); }
catch { }
try { Marshal.ReleaseComObject(resourceManager); }
catch { }
}
}
public static bool Read(byte address, out string valueRead)
{
resourceManager = new ResourceManager();
ioObject = new FormattedIO488();
string addr = $"GPIB::{address.ToString()}::INSTR";
try
{
ioObject.IO = (IMessage)resourceManager.Open(addr, AccessMode.NO_LOCK, 0, "");
Thread.Sleep(20);
valueRead = ioObject.ReadString();
return true;
}
catch
{
valueRead = "";
return false;
}
finally
{
try { ioObject.IO.Close(); }
catch { }
try { Marshal.ReleaseComObject(ioObject); }
catch { }
try { Marshal.ReleaseComObject(resourceManager); }
catch { }
}
}
}
}
Happy programming!!

keep having this exception System.Data.OleDb.OleDbException (0x80004005):?

i am developping a really simple program in c# with Visual studio, it consists simply by extracting data from an Excel sheet and transfer it to a database (only one table ), using MySql it worked i just saved the files as CSV and then imported them into my database but i had a big problem which was the encoding UTF8 i have many french characters ans arabic ones that just showed as random characters, so i went back to OleDb but it keeps shong exceptions now i am stuck with this one: System.Data.OleDb.OleDbException (0x80004005)
i ve tried to change running config to x86 but nothing (notice that i am using a windows 8 X64). its a cummon ISAM problem.
please help me .
this is my code :
using System;
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 Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
using System.IO;
using System.Data.OleDb;
namespace testoledb
{
public partial class Form1 : Form
{
DataSet OleDs = new DataSet();
OleDbDataAdapter OleAdapter = new OleDbDataAdapter();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
}
private void upload_excl_Click(object sender, EventArgs e)
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
path = Path.Combine(path, "AGENDA.xlsx");
string OleConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="+path+#";Extend Properties=Excel 12.0 Macro;MDR=Yes;ImportMixedTypes=Text;TypeGuessRows=0"; //,HDR=Yes;IMEX=1""";
OleDbConnection OleConn = new OleDbConnection(OleConnectionString);
string OleStrCmd = "select * from [SHeet1$A1:H330]";
OleDbCommand OleCmd = new OleDbCommand(OleStrCmd, OleConn);
try
{
OleConn.Open();
OleDs.Clear();
OleAdapter.SelectCommand = OleCmd;
OleAdapter.Fill(OleDs);
dataGridView1.DataSource = OleDs.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
OleConn.Close();
}
}
}
}

C# asp.net Disconnecting users terminal service session via loacl intranet

I have written code that uses a .bat file (code: rwvinstat /server:servername) that populates a DataGrid of users logged in to a terminal service session in c#. The .bat lives on the server with the app. files and will run properly if executed manually on the server .Also if i run the app. locally and call the .bat file on the server it works fine.
The problem is when i deploy my web app on the server the DataGrid never populates nor do i get any errors. i have given full permissions to IUSER_MACHINENAME(and various users) and i set the virtual directory permissions to read, run, execute. Ialso have set my web.conf fig to:< "identity impersonate="true" userName="username" password="password"/>
Here is my Source code:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.IO;
public partial class ilsap01_users : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("C:\\listUsersIlsap01.bat");
psi.RedirectStandardOutput = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
System.Diagnostics.Process listFiles;
listFiles = System.Diagnostics.Process.Start(psi);
System.IO.StreamReader rawUserData = listFiles.StandardOutput;
listFiles.WaitForExit(20000);
try
{
DataTable table2 = new DataTable();
table2.Columns.Add(new DataColumn("UserName", typeof(string)));
table2.Columns.Add(new DataColumn("SessionId", typeof(string)));
String myString = rawUserData.ReadToEnd();
string exp = #"([\w_]+)"; ;
MatchCollection matches = Regex.Matches(myString, exp, RegexOptions.IgnoreCase);
IEnumerator en = matches.GetEnumerator();
if (en.MoveNext())
{
while (en.MoveNext())
{
Match match = (Match)en.Current;
if (en.Current.ToString() == "rdpwd")
{
if (en.MoveNext())
{
if (en.Current.ToString() == "rdp")
{
en.MoveNext();
en.MoveNext();
en.MoveNext();
Match match_Item = (Match)en.Current;
string item = match_Item.Value;
en.MoveNext();
Match match_Item2 = (Match)en.Current;
string item2 = match_Item2.Value;
DataRow row = table2.NewRow();
row[0] = item.Split()[0];
row[1] = item2.Split()[0];
table2.Rows.Add(row);
}
}
}
}
}
this.displayUsers.DataSource = table2;
this.displayUsers.DataBind();
}
catch (Exception ex)
{
Response.Write(ex);
}
}
protected void dg_SelectedIndexChanged(object sender, EventArgs e)
{
}
protected void Button2_Click(object sender, EventArgs e)
{
Response.Redirect("ILSRF01_USERS.ASPX");
}
protected void Button1_Click(object sender, EventArgs e)
{
}
}
Is the executable that the batch file is calling (rwvinstat) in the system path? You might need to call it explicitly - c:\windows\system32\rwvinstat.exe or wherever it is located.
Did you grant the user the application pool is running as the appropriate Remote Desktop Services permissions?
Also, you might find the Cassia library a bit easier to use for your purposes.

Categories

Resources