File Watch Application fails when file saved by remote user - c#

My problem is this, and before I annoy anybody, this is my first post so if I err, forgive me.
I have created a simple windows service with a file system watcher that triggers a console application if a .txt file is pasted. The service is running as Local System, and works perfectly. However, the files it watches for are saved every morning by a remote user, and the console application fails without cause. If I save the file, the service AND the console application do exactly what they are supposed to.
The console application uses the GeneticParsing Library to read the file into a table, bulk loads it into an oracle 11g db on a remote server, then archives the file. The main code for the console application is below... any help would be much appreciated!
static void Main(string[] args)
{
try
{
FileInfo f = new FileInfo(args[0].ToString());
Thread.Sleep(15000);
GenericParserAdapter p = new GenericParserAdapter();
p.ColumnDelimiter = '|';
p.SetDataSource(f.FullName);
DataTable d = new DataTable();
d = p.GetDataTable();
bb_usage_methods b = new bb_usage_methods(false);
DataTable d_merge = new DataTable();
d_merge.Columns.Add("BB_USAGE_ID", Type.GetType("System.Int32"));
d_merge.Columns.Add("USAGE_DATE", Type.GetType("System.DateTime"));
d_merge.Columns.Add("PARTY_CODE", Type.GetType("System.Int32"));
d_merge.Columns.Add("UPLOAD_USAGE", Type.GetType("System.Decimal"));
d_merge.Columns.Add("DOWNLOAD_USAGE", Type.GetType("System.Decimal"));
d_merge.Columns.Add("TOTAL_USAGE", Type.GetType("System.Decimal"));
DataRow r;
object j = b.get_data_from_datareader("SELECT MAX(BB_USAGE_ID) FROM USAGE");
Int32 max_id = j.ToString() == "Entry is NULL" || j.GetType() == System.Type.GetType("System.Exception") ? max_id = 1 : max_id = Convert.ToInt32(j) + 1;
for (int i = 0; i < d.Rows.Count; i++)
{
r = d.Rows[i];
try
{
object[] o = { max_id, Convert.ToDateTime(r[0]), Convert.ToDecimal(r[1]), Convert.ToDecimal(r[2]), Convert.ToDecimal(r[3]), Convert.ToDecimal(r[4]) };
d_merge.Rows.Add(o);
max_id++;
}
catch { }
r = null;
}
decimal original_count = Math.Round((decimal)(d.Rows.Count * 100) / d_merge.Rows.Count, 2);
b.bulk_insert_into_oracle(d_merge, "USAGE");
DateTime dt = f.LastWriteTime;
try
{
File.Move(f.FullName, f.FullName.Replace(f.Name, #"\..\Archive\" + f.Name));
}
catch (Exception e)
{
// code to log error to db
}
}
catch (Exception ex)
{
// code to log error to db
}
}
}
public class log_methods : x.oracle_data_access
{
public log_methods()
{
base.get_dataset("SELECT * FROM APP_LOG", "LOG_ID");
}
}
public class bb_usage_methods : x.oracle_data_access
{
public bb_usage_methods(Boolean get_dataset)
{
if (get_dataset)
{
base.get_dataset("SELECT * FROM USAGE", "BB_USAGE_ID");
}
}
}

Are you sure the filewatcher sees that file?
Is the program launched at all when remote user saves it.
If i remember right, there are some case where the filewatcher doesn't trigger when it should (in remote or whatnot).

Related

c# Cross-Platform device information from local network from lan scan

I have currently wrote a code which scans the local network with a function called "bool ping()". I want to add a capability to provide basic device information when the function returns 'true'. I've found 'ManagementObjectSearcher'.
At first it looked perfect but when It gets used for a non-windows device it crash. Therefore I suppose that this method cannot be used for non-windows devices.
As I want to add the below code ( or login , after enough polishing ), to an android app that scans the local network and returns the
A) IP address and
B) (one of the following )
the device type ( desktop , laptop , smartphone)
and/or
the OS type ( android , windows , linux , tvOS )
Is there a valid way I can do what I am looking for? I believe I have experienced apps that do stuff like that, though I don't know what language they were based on.
namespace LanConsole
{
class Program
{
static void Main(string[] args)
{
string host = "192.168.1.10"; // android smartphone IP
string temp = null;
// arguments I found
string[] _searchClass = { "Win32_ComputerSystem", "Win32_OperatingSystem", "Win32_BaseBoard", "Win32_BIOS" };
string[] param = { "UserName", "Caption", "Product", "Description" };
bool v = ping(host, 10, 900); // bool function send ping to host
if (v == true)
{
Console.WriteLine("true");
for (int i = 0; i <= _searchClass.Length - 1; i++)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("\\\\" + host + "\\root\\CIMV2", "SELECT *FROM " + _searchClass[i]);
foreach (ManagementObject obj in searcher.Get())
{
temp += obj.GetPropertyValue(param[i]).ToString() + "\n";
if (i == _searchClass.Length - 1)
{
Console.WriteLine(temp, "Hostinfo: " + host);
break;
}
}
Console.WriteLine("");
}
}
else
Console.WriteLine("false");
}
public static bool ping(string host, int attempts, int timeout)
{
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply pingReply;
for (int i = 0; i < attempts; i++)
{
try
{
pingReply = ping.Send(host, timeout);
// If there is a successful ping, return true.
if (pingReply != null &&
pingReply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
return true;
}
}
catch
{
// supressing errors
}
}
// Return false if ping fales "attempts" times
return false;
}
}
}

Use C# to call AS400 program and select file from QTEMP

I have a ASP.Net app to call AS400 program in order to create a file under QTEMP. But when I try to select this file from QTEMP, it does not exist.
I understand the reason: call program and select file are different jobs. I cannot access other job's QTEMP.
I do not know much about the AS400, the only way I can find out is to create this file under another library other than QTEMP. But it will impact my other app functions which I do not want to do.
I am using cwbx.dll to call the AS400 program and then I am using IBM.Data.DB2.iSeries to select the file from QTEMP. Obviously they are two connections opened. I am not sure if under as400 concept, they may be two separate jobs.
Here is the function to call the program:
As400Caller1.CallAs400Program("myProgram", "myLibrary", paramsList1);
Here is the CallAs400Program function:
public void CallAs400Program(string programName, string libraryName, List<AS400Param> parameters) {
try
{
system.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd);
//check connection
if (system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1)
{
//create a program object and link to the system
Program program = new Program();
program.LibraryName = libraryName;
program.ProgramName = programName;
program.system = system;
//create a parameter collection associated with the program and pass data
ProgramParameters prms = new ProgramParameters();
foreach (AS400Param p in parameters)
{
prms.Append(p.ParameterName, cwbrcParameterTypeEnum.cwbrcInout, p.ParameterLength);
if (!p.OutParam)
{
prms[p.ParameterName].Value = AS400ParamStringConverter.ConvertASCIItoEBCDIC(p.ParameterValue.PadRight(p.ParameterLength, ' '));
}
}
//call the program
try
{
program.Call(prms);
}
catch (Exception ex)
{
if (system.Errors.Count > 0)
{
foreach (cwbx.Error error in system.Errors)
{
throw ex;
}
}
if (program.Errors.Count > 0)
{
foreach (cwbx.Error error in program.Errors)
{
throw ex;
}
}
}
}
else
{
Console.WriteLine("No AS400 Service connection");
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (system.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) == 1)
system.Disconnect(cwbcoServiceEnum.cwbcoServiceAll);
}
}
Here is my select SQL code:
try
{
List<TableRowModel> dataList = new List<TableRowModel>();
string library = "QTEMP";
string cmdText = $#"SELECT * FROM {library}.myFile";
iDB2Command command = new iDB2Command(cmdText);
command.Connection = IDB2Context.Current;
iDB2DataReader reader = command.ExecuteReader();
while (reader.Read())
{
}
return dataList;
}
catch (Exception ex)
{
throw ex;
}
Exception throw:
myFile in QTEMP type *FILE not found.
How can I use C# to solve the issue of accessing other Jobs QTEMP?
QTEMP is session specific...you can't access it from another job..
Consider an using an SQL Stored procedure that you can call from .NET.
The stored proc can call the RPG program and the return the results from the file in QTEMP all in a single call.

C# Stops Executing When Opening A Connection To MySql

I am writing an application to transfer data from a simulated OPC server to a MySql Database. I am using some of the libraries from OPC Foundation - OPCNETAPI.DLL, OPCNETAPI.COM.DLL.
I have the program reading from the server happily, but it seems as soon as I open a connection inside the loop of reading data, it loops about 5 times and then stops executing.. There are no exceptions thrown and I have tried for hours to work it out and miserably failed.
I've also changed VisualStudio to break when an exception is thrown, and it doesn't
Hopefully some one may know whats going on, but there is nothing obvious, hopefully the following code will spark ideas!
Windows Forms Code
public void readplc()
{
Opc.URL url = new Opc.URL("opcda://localhost/Matrikon.OPC.Simulation.1");
Opc.Da.Server server = null;
OpcCom.Factory fact = new OpcCom.Factory();
server = new Opc.Da.Server(fact, null);
try
{
server.Connect(url, new Opc.ConnectData(new System.Net.NetworkCredential()));
}
catch (Exception ecy)
{
}
// Create a group
Opc.Da.Subscription group;
Opc.Da.SubscriptionState groupState = new Opc.Da.SubscriptionState();
groupState.Name = "Group";
groupState.Active = true;
group = (Opc.Da.Subscription)server.CreateSubscription(groupState);
// add items to the group.
Opc.Da.Item[] items = new Opc.Da.Item[2];
items[0] = new Opc.Da.Item();
items[0].ItemName = "Random.Int1";
items[1] = new Opc.Da.Item();
items[1].ItemName = "Random.Time";
items = group.AddItems(items);
group.DataChanged += new Opc.Da.DataChangedEventHandler(OnTransactionCompleted);
}
public void OnTransactionCompleted(object group, object hReq, Opc.Da.ItemValueResult[] items)
{
for (int i = 0; i < items.GetLength(0); i++)
{
try
{
string a = items[i].Value.ToString();
string b = items[i].ItemName;
string c = items[i].Key;
MySqlConnection conn = new MySqlConnection("server=localhost;user id=localhost;password=localhost;database=localhost;pooling=false");
conn.Open();
conn.Close();
}
catch (Exception ec)
{
MessageBox.Show(ec.Message);
}
}
}
I have set break points throughout the code, stepped through everything possible and still nothing obvious that's causing the issue.

TF20507: The string argument contains a character that is not valid:'u0009'. Correct the argument, and then try the operation again

I started getting this error when calling ReadIdentities... After updating from Visual studio 2010 to 2012 SDK. It crashes due to invalid "\t" in one of the members. (New validation rules in TFS API probably).
var GSS = tfs.GetService<IIdentityManagementService>();
Identity SIDS = project.GSS.ReadIdentity(SearchFactor.AccountName, "Project Collection Valid Members", QueryMembership.Expanded);
var _TFSUsers = project.GSS.ReadIdentities(SearchFactor.Sid, SIDS.Members, QueryMembership.None);
The saddest part of this story is that I need to find out which member has this tab char. And TFS contains 2000+ members. I tried running one by one, but only ReadIdentities method crashes. ReadIdentity passes. So decided to follow these steps:
foreach (var memberSID in SIDS.Members)
{
try
{
var identity = project.GSS.ReadIdentities(SearchFactor.Sid,new string[] { memberSID,}, QueryMembership.None);
}
catch (Exception ex2)
{
throw new InvalidOperationException("Failed to load TFS user: " + memberSID, ex2);
}
}
Yet somehow this did not work either! As the code ran flawlessly with no exceptions.
I have produced the method which splits the array half and tries to narrow the search until the smallest possible size.
private static void SplitHalf(string[] identities, IIdentityManagementService GSS)
{
var count = identities.Count();
int half = count / 2;
List<string> half1 = new List<string>();
List<string> half2 = new List<string>();
for (int i = 0; i < half; i++)
{
half1.Add(identities[i]);
}
var halfArray1 = half1.ToArray();
try
{
var users = GSS.ReadIdentities(SearchFactor.Sid, halfArray1, QueryMembership.None);
}
catch (Exception ex)
{
SplitHalf(halfArray1, GSS);
}
for (int i = half; i < count; i++)
{
half2.Add(identities[i]);
}
var halfArray2 = half2.ToArray();
try
{
var users = GSS.ReadIdentities(SearchFactor.Sid, halfArray2, QueryMembership.None);
}
catch (Exception ex)
{
SplitHalf(halfArray2, GSS);
}
}
This way, I was able to put breakpoint with condition count == 2. And narrowed down to find out the display name and identity that was crashing the stuff. I hope this saves some time for someone. It appears that crashing occurs only when minimum of two SIDS are supplied for the method parameters, supplying only one, did not result in error...

Automation Error 80004005

I've been beating myself over the head with this for a few days now, searched up and down the internet. I know there is a lot I don't quite get about Com Interop but I've had success building and using simpler DLL's with Excel. Anyways to the point.
I get the above mentioned Error -2147467259 80004005 Automation Error Unspecified Error in Excel VBA when running the following code wrapped in a DLL.
[GuidAttribute("96BE21CD-887B-4770-9FAA-CF395375AEA9")]
[ComVisibleAttribute(true)]
interface QInterface
{
void ConnectionFill(string SQLQuery, string CONStr);
string QueryValue(int QueryKey);
string ConnectionValue(int ConnectionKey);
string outputFile { get; set; }
void ThreadTest();
}
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[ProgIdAttribute("QueryThread")]
class QueryThread : QInterface
{
DataSet QueryReturn = new DataSet();
private ArrayList SQLList = new ArrayList();
private ArrayList ConList = new ArrayList();
private string OutputFile;
public void ConnectionFill(string SQLQuery, string CONStr)
{
SQLList.Add(SQLQuery);
ConList.Add(CONStr);
}
public string QueryValue(int QueryKey)
{
return SQLList[QueryKey].ToString();
}
public string ConnectionValue(int ConnectionKey)
{
return ConList[ConnectionKey].ToString();
}
public string outputFile
{
set { OutputFile = value; }
get { return OutputFile; }
}
public void ThreadTest()
{
int i = 0;
i = SQLList.Count;
Thread[] myThreads;
myThreads = new Thread[i];
for (int t = 0; t != i; t++)
{
myThreads[t] = new Thread(() => ThreadRun(SQLList[t].ToString(), ConList[t].ToString()));
myThreads[t].Name = "Thread " + t;
myThreads[t].IsBackground = true;
myThreads[t].Start();
Thread.Sleep(600);
if (t > 9)
{
myThreads[t - 9].Join();
}
}
for (int t = 0; t != i; t++)
{
while (myThreads[t].IsAlive)
{
Thread.Sleep(20);
}
}
TextWriter tw = new StreamWriter(OutputFile);
for (int t = 0; t < QueryReturn.Tables.Count; t++)
{
DataTableReader DR = QueryReturn.Tables[t].CreateDataReader();
while (DR.Read())
{
tw.WriteLine("{0} : {1}", DR.GetValue(0), DR.GetValue(1));
}
}
tw.Close();
QueryReturn.Dispose();
}
private void ThreadRun(string SQLString, string ConString)
{
try
{
OleDbConnection DBCon = new OleDbConnection(ConString);
DBCon.Open();
Thread.Sleep(200);
OleDbCommand DBCmd = new OleDbCommand(SQLString, DBCon);
OleDbDataAdapter DataAdapter = new OleDbDataAdapter(DBCmd);
Thread.Sleep(200);
DataAdapter.Fill(QueryReturn, Thread.CurrentThread.Name.ToString());
DBCon.Close();
DataAdapter.Dispose();
DBCon.Dispose();
DBCmd.Dispose();
}
finally
{
}
}
}
using this VBA code...
Sub test()
Dim QT As New QueryThreading.QueryThread
Dim MyResults As String
Dim outputfile As String
Dim InputStuff(1, 1) As String
InputStuff(0, 0) = "Select DISTINCT * From TrackingData;"
InputStuff(0, 1) = "Provider =Microsoft.ACE.OLEDB.12.0;Data Source =C:\Users\Nick\Desktop\test.accdb; Persist Security Info =False;Connection Timeout=7;"
InputStuff(1, 0) = "Select DISTINCT * From TrackingData;"
InputStuff(1, 1) = "Provider =Microsoft.ACE.OLEDB.12.0;Data Source =C:\Users\Nick\Desktop\test2.accdb; Persist Security Info =False;Connection Timeout=7;"
QT.ConnectionFill InputStuff(0, 0), InputStuff(0, 1)
QT.ConnectionFill InputStuff(1, 0), InputStuff(1, 1)
outputfile = "C:\Users\Nick\Desktop\testrun.txt"
QT.outputfile = outputfile
QT.ThreadTest
End Sub
It runs fine is a pure C# console application. Works perfect and quick with no problems. But via VBA I get the error.
I'm assuming it's something to do with the calling of the access databases in multiple threads. I know there is a lot of junk code in there, it's not optimized of course I'm still in the "playing around" phase.
I've used RegAsm and enabled com interop and all such stuff, I can read back from the returns just fine. So I know the DLL is working right, just when I fill the threads and run "ThreadTest()" I get the automation error.
If I run it a second time Excel locks up.
Any help would be greatly appreciated.
You are calling QT.DictionaryFill though I can't seem to find a corresponding method in you C# code... what happens if you change the call to QT.ConnectionFill instead ?
Another point: IIRC then VBA runs the object in STA - not sure whether MTA is supported though
EDIT:
According to this rather old post VBA does not support multi-threading...

Categories