Background: I'm writing an application in C# (.NET 3.5), that looks at multiple users Outlook 2003 calendars (using COM objects), gets the appointments and inserts the data for those appointments into a database.
Problem: After the first users calendar, any recurring items on the following calendars, will always have a start and end time of the first occurrence of that item. I'm releasing the COM Objects between users (and during, if the user has a lot of items), and The item collection is being restricted correctly (due to there only being a handful of the recurring tasks inserted (albeit the wrong start/end) instead of infinite from the "no end" tasks). The correct start/end time is part of the requirements, having the information available for this or another application to work out how much free time a user has for a given range of dates, and working hours.
Code: (Variable declarations omitted, they're at the top of the relevant functions)
Looping through the users (in Main()):
foreach (DataRow drUserCalendar in dtCalendars.Rows)
{
//for each calendar we're looking at, export their calendar data and put it in the database
try
{
appOutlook = new Outlook.Application();
ExportCalendar(drUserCalendar);
Marshal.FinalReleaseComObject(appOutlook);
GC.Collect();
}
catch (Exception ex)
{
//report error
}
}
Extracting information from the calendar
static void ExportCalendar(DataRow drUser)
{
strDisplayName = drUser["DisplayName"].ToString();
strUserID = drUser["ID"].ToString();
int.TryParse(drUser["PreviousDays"].ToString(), out intPrevious);
int.TryParse(drUser["FutureDays"].ToString(), out intFuture);
dtmAllowedPreviousStart = DateTime.Now.AddDays(-intPrevious);
dtmAllowedFutureStart = DateTime.Now.AddDays(intFuture);
nsOne = appOutlook.GetNamespace("MAPI");
nsOne.Logon(null, null, false, false);
rcpOne = nsOne.CreateRecipient(strDisplayName);
intCount = 0;
if (rcpOne.Resolve())
{
fldOne = nsOne.GetSharedDefaultFolder(rcpOne, Outlook.OlDefaultFolders.olFolderCalendar);
strRestrict = "[Start] > '" + MIN_START_DATE.ToString("g") + "' And [End] < '" + MAX_START_DATE.ToString("g") + "'";
itms = fldOne.Items;
itms.Sort("[Start]", Type.Missing);
itms.IncludeRecurrences = true;
itmsRestricted = itms.Restrict(strRestrict);
itmsRestricted.Sort("[Start]", Type.Missing);
itmsRestricted.IncludeRecurrences = true;
blnIsRecurring = false;
dicRecurringTaskTracker = new Dictionary<string, int>();
foreach (object objOne in itmsRestricted)
{
if (intCount >= 100 || blnIsRecurring)
{
//release COM objects. Outlook doesn't like you having more than 250 ish items without cleaning up.
Marshal.FinalReleaseComObject(appOutlook);
appOutlook = new Outlook.Application();
GC.Collect();
intCount = 0;
}
if (objOne is Outlook.AppointmentItem)
{
appItem = (Outlook.AppointmentItem)objOne;
blnException = false;
//get data from the item
strEntryID = appItem.EntryID;
strSubject = appItem.Subject;
strBody = appItem.Body;
dtmStart = appItem.Start;
dtmEnd = appItem.End;
blnException = EXCEPTIONS.Contains(strSubject);
//if the item is an exception we're done with it.
if (!blnException)
{
strRecurrenceInterval = "";
strRecurrenceType = "";
strRecurrenceInfo = "";
//check if it's a recurring task.
blnIsRecurring = appItem.IsRecurring;
if (blnIsRecurring)
{
//check to see if we've already had a task from this series
if (!dicRecurringTaskTracker.Keys.Contains(strEntryID))
{
//Start at 0 so the first (this) task
//is number 1.
dicRecurringTaskTracker.Add(strEntryID, 0);
}
//update number
dicRecurringTaskTracker[strEntryID] += 1;
//change the subject to add the count on the end
strEntryID = strEntryID + '-' + dicRecurringTaskTracker[strEntryID].ToString();
//it's a recurring task, so we need to find out when/how often.
rpTaskRecurrence = appItem.GetRecurrencePattern();
rtTaskRecurrenceType = rpTaskRecurrence.RecurrenceType;
strRecurrenceType = rtTaskRecurrenceType.ToString();
strRecurrenceInterval = rpTaskRecurrence.Interval.ToString();
switch (strRecurrenceType)
{
case "olRecursDaily":
case "olRecursMonthNth":
case "olRecursWeekly":
strRecurrenceInfo = rpTaskRecurrence.DayOfWeekMask.ToString();
break;
case "olRecursMonthly":
strRecurrenceInfo = rpTaskRecurrence.DayOfMonth.ToString();
break;
}
}
if (strEntryID != null && strSubject != null && dtmStart != null && dtmEnd != null
&& (intPrevious == 0 || (dtmStart > dtmAllowedPreviousStart)) && (intFuture == 0 || (dtmStart < dtmAllowedFutureStart)))
{
//build up the SQL
strSQL = "EXEC UpdateCalendarEntry ";
strSQL += "#EntryID='" + strEntryID + "', ";
strSQL += "#Subject='" + strSubject.Replace("'", "''") + "', ";
strSQL += "#Body='" + strSubject.Replace("'", "''") + "', ";
strSQL += "#StartDate='" + dtmStart.ToString("dd-MMM-yyyy HH:mm:ss") + "', ";
strSQL += "#EndDate='" + dtmEnd.ToString("dd-MMM-yyyy HH:mm:ss") + "', ";
strSQL += "#UserCalendarID=" + strUserID + ",";
strSQL += "#Recurring = " + blnIsRecurring.ToString() + ",";
strSQL += "#RecurrenceType = '" + strRecurrenceType + "',";
strSQL += "#RecurrenceInterval = '" + strRecurrenceInterval + "',";
strSQL += "#RecurrenceInfo = '" + strRecurrenceInfo + "';";
try
{
//Execute SQL
}
catch (Exception ex)
{
//Print error message
MessageBox.Show(ex.ToString());
}
}
}
Marshal.FinalReleaseComObject(appItem);
GC.Collect();
}
strEntryID = null;
strSubject = null;
strBody = null;
intCount++;
}
//finished looping, do some clean up.
Marshal.FinalReleaseComObject(nsOne);
Marshal.FinalReleaseComObject(rcpOne);
Marshal.FinalReleaseComObject(fldOne);
Marshal.FinalReleaseComObject(itms);
Marshal.FinalReleaseComObject(itmsRestricted);
GC.Collect();
}
else
{
throw new Exception("Could not resolve name");
}
}
I can't see an obvious problem with your code I'm afraid but as I expect your well aware there is probably some other stuff happening behind the scenes that is causing your problem.
I have covered some things I found to be best practice when I was working with this stuff in a blog article - http://jynxeddevelopment.blogspot.com. It might be worth a read to see if anything seems different to what you are doing, I think the section 'Keep references to everything' might be useful.
I'm not sure your COM objects will be collected with the GC call as you're not setting them to null first, however either way this shouldn't make a difference. I got this sort of thing working without any GC calls.
Things to look at:
objOne should be release EVERY loop if it's a COM object (I expect it is)
Closing your Outlook application before releasing it (appOutlook.Close()), I'm surprised your not getting lots of them hanging around
Examine every field you are using on the COM object, if they are COM objects too they might need Finalising too
Sorry this is nothing concrete but working with this stuff is hard work :/ Good luck!
-Jynx
After testing I've found that the issue relates to my (or whoever runs the application) permissions on the users (shared) calendar(s) that are being looked at.
It works on the first user because that's myself in this case. It doesn't work on users after that because i don't have sufficient rights it seems (confirmed by having my colleague changing it so default users are "owners" on his calendar and running the application again, and it working for his calendar).
I have since tried to use GetOccurrence(DateTime) (surrounded with a while loop), however that lead to the same issue. The function would error when there was no occurrence (as expected), but when it found an occurrence it would return a null object.
However because I wasn't using the object for anything other than getting the start and end date of the task, I worked it out manually (I had the original task, meaning i could get the duration, by incrementing each day until I get an occurrence I'd get the reccurring tasks start date, and using the duration of the task I calculated the end date).
It's not an ideal solution, but if you're just wanting to get recurring tasks it's simple enough to do (though resource consuming if you have a lot of reccurring tasks and are looping for a long period of time)
Related
I have tried to wipe this data while trying to export a database into my program.
The basic problem is that I do not know why he can not use LIKE in my SQL statement.
So I wanted to catch all DataRows and write them into an array, which I can edit later.
The program throws an exception:
Error message: System.IndexOutOfRangeException: "The index was outside the array area."
If I did something unusual or wrong in my Post I sincerely apologies, this is my first entry in this forum.
Code:
public void TestQuery()
{
string file = #"C:\Users\Michael\Downloads\7z1900-x64.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(file, 0);
// Open a view on the Property table for the version property
View view = database.OpenView("SELECT * FROM `File`");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
int i = 1;
string[] sreturns = new string[60];
while (record != null)
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
sreturns[i] = record.get_StringData(0).ToString();
i++;
}
}
First thing I see is that you're starting at 1, while (C#) arrays are 0-based.
In you screenshot I see that i is 60, so that would be the problem. Index 60 doesn't actually exist in your array, as it goes from 0 to 59.
You can add i < sreturns.Length to make sure you are in the array range.
Also, make sure you start with i = 0 and not 1.
int i = 0;
string[] sreturns = new string[60];
while (record != null && i < sreturns.Length)
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
sreturns[i] = record.get_StringData(0).ToString();
i++;
}
Why not using a list instead of an array?
List<string> sreturns = new List<string>();
while (record != null)
{
try
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
var result = record.get_StringData(0);
sreturns.Add(result.ToString());
}
catch (Exception e)
{
Console.WriteLine("No record...");
}
}
This way you dont need to worry about the array size - its maintainable -efficient - and if in the future the size change you don't have to worry about it.
List documentation here
What is the query with LIKE that you have tried? The following should work:
SELECT * FROM File WHERE FileName LIKE '%.exe' OR FileName LIKE '%.msi'
EDIT: On further investigation (https://learn.microsoft.com/en-us/windows/win32/msi/sql-syntax), the documentation seems to imply that the LIKE operator is not supported. But you could start off with an IS NOT NULL and do more complex filtering in the loop, like you're doing.
EDIT 2, expanding on Alex Leo's answer.
List<string> sreturns = new List<string>();
while (record != null)
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
var result = record.get_StringData(0);
if(!string.IsNullOrWhiteSpace(result) && (result.EndsWith(".exe") || result.EndsWith(".msi")))
{
sreturns.Add(result.ToString());
}
record = view.Fetch();
}
Note that the view.Fetch() inside the while loop has been moved to the end, or you would skip the first record, as well as get another null reference when the last record has already been read, but the while loop executes one more time.
here we using if statement and it's work fine for first time
then when i enter barcode and pressed enter again it's going direct to else statement
it's mean shown me error message under as we see on else statement and i think it's not repeat whole statement as new process because i'm sure from condition it's true and it shouldn't go to else statement
but in third time when i try enter barcode and check from condition it's work fine like first time and then in forth time show me error again
why error shown on every second time
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (checkBox1.Checked)
{
if (qtystate == true)
{
DataTable dt;
barcode = textBox1.Text;
dt = pro.GetProdcutBar(textBox1.Text);
if (dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
barcode = row[0].ToString();
itemno = row[1].ToString();
itemname = row[2].ToString();
salespric = row[3].ToString();
costprice = row[4].ToString();
}
cont.addprodcuttocount(Convert.ToString(barcode), Convert.ToString(itemno), Convert.ToString(itemname),
Convert.ToString(salespric), Convert.ToString(costprice), "1", DateTime.Now, SystemInformation.ComputerName);
refershgridview();
//sum qty
try
{
int sum = 0;
for (int i = 0; i < dataGridView1.Rows.Count; ++i)
{
if (Convert.ToString(dataGridView1.Rows[i].Cells[1].Value) == textBox1.Text)
{
sum += Convert.ToInt32(dataGridView1.Rows[i].Cells[6].Value);
}
}
label3.Text = "Barcode " + barcode + " - " + "Item NO" + itemno + " - " + "item name " + itemname + " - " + "qty " + sum.ToString();
}
catch
{
}
barcode = "";
itemno = "";
itemname = "";
salespric = "";
costprice = "";
qtyitem = "";
textBox1.Clear();
textBox1.Focus();
}
else
{
MessageBox.Show("00barcode not found", "barcode", MessageBoxButtons.OK, MessageBoxIcon.Stop);
barcode = "";
itemno = "";
itemname = "";
salespric = "";
costprice = "";
qtyitem = "";
textBox1.Clear();
textBox1.Focus();
}
}
}
}
}
The discriminator for your if...else block is this line:
if (dt.Rows.Count > 0)
Every other call to the function, the body of the if clause is executed. For the remaining calls, the else clause is executed.
Based on these symptoms, it appears that something is changing the result of this line:
dt = pro.GetProdcutBar(textBox1.Text)
In half the calls, you get at least one row; in the others, you get zero rows. The question for you is, Why are the results changing every other call?
A couple of causes spring to mind:
Your GetProdcutBar method doesn't simply retrieve data, it modifies it (a side-effect). This is undesirable, as it hides the fact that your result set changes with each call.
Another method somewhere in the program is changing the data. This is possibly in response to user activity (a mouse click, for example).
The underlying code that retrieves the data is written in such a way that it returns a set of data that cannot be reliably predicted (that is, it is non-deterministic). Perhaps one of the selection criteria uses the time of day, or clock ticks, thread ID, or some other volatile value.
If any of these are the case, your data may change from one call to the next, potentially returning no results. Examine the function and make sure it reliably returns the data you expect every time you call it, and that you are not using volatile function arguments (unless you absolutely must).
Also, as a parting thought: Is it truly an error condition if no records are returned by a query? In the vast majority of cases, it is not (unless the query is for required lookup data). The key thing to do is process all available rows, and do nothing if there is no data to process.
I will be amazed if I find a solution for this, since it is very specific and vague, but I figured I would try. I'll try to give as much information as humanly possible, since I've been searching for answers for some time now.
I am building a utility in C# which copies records from a file in a library on the i-series/AS400 and builds an encrypted text file with each record from the AS400 as a comma separated string. In the file, it will have values like filename, fieldvalue1, fieldvalue2, fieldvalue3. I then take that text file to another PC, and run a C# utility which copies that record into the same file name in a library over there on a different i-series machine. Unfortunately, I receive the outside bounds of the array exception in some cases, but I cannot determine why. In the record just prior to the exception, the record looks pretty much the same and it works fine. My code is below in a nutshell. I usually don't give up, but I don't expect to ever figure this out. If someone does, I'll probably sing karaoke tonight.
// Select records from AS400 file and write them to text file
Recordset rs = new Recordset();
sqlQuery = "SELECT * FROM " + dataLibrary + "." + fileName;
try
{
rs.Open(sqlQuery, con);
while (!rs.EOF)
{
int[] fieldLengths;
fieldLengths = new int[rs.Fields.Count];
String[] fieldValues;
fieldValues = new String[rs.Fields.Count];
String fullString = "";
for (i = 0; i < rs.Fields.Count; i++)
{
fieldLengths[i] += rs.Fields[i].DefinedSize;
fieldValues[i] += rs.Fields[i].Value;
}
fullString = fileName + "," + String.Join(",", fieldValues);
fullString = Functions.EncryptString(fullString);
File.AppendAllText(savefile.FileName, fullString + Environment.NewLine);
rs.MoveNext();
}
}
catch (Exception ex)
{
}
cmd.Dispose();
// This gives me a text file of filename, fieldvalue1, fieldvalue2, etc...
// Next, I take the file to another system and run this process:
while ((myString = inputFile.ReadLine()) != null)
{
int stringLength = myString.Length;
String[] valuesArray = myString.Split(',');
for (i = 0; i < valuesArray.Length; i++)
{
if (i == 0)
{
fileName = valuesArray[0];
// Create file if it doesn't exist already
createPhysicalFile(newLibrary, fileName);
SQLStatement = "INSERT INTO " + newLibrary + "." + fileName + "VALUES(";
}
else
{
if (i == valuesArray.Length - 1)
{
SQLStatement += "#VAL" + i + ")";
}
else
{
SQLStatement += "#VAL" + i + ", ";
}
}
}
try
{
using (connection)
{
try
{
connection.Open();
}
catch (Exception ex)
{
}
// Create a new SQL command
iDB2Command command = new iDB2Command(SQLStatement, connection);
for (i = 1; i < valuesArray.Length; i++)
{
try
{
command.Parameters.AddWithValue("#VAL" + i, (valuesArray[i]));
}
catch (Exception ex)
{
}
}
// Just split the array into a string to visually check
// differences in the records
String arraySplit = ConvertStringArrayToString(valuesArray);
// The query gets executed here. The command looks something
// like:
// INSERT INTO LIBNAME.FILENAME VALUES(#VAL!, #VAL2, #VAL3, #VAL4)
// There are actually 320 fields in the file I'm having a problem with,
// so it's possible I'm overlooking something. I have narrowed it down to
// field # 316 when the exception occurs, but in both cases
// field 316 is blanks (when it works and when it doesn't).
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
// Here I get the exception out of bounds error in MSCORLIB.DLL.
// Some records are added fine, while others cause this exception.
// I cannot visibly tell any major differences, nor do I see any
// errors in the AS400 job log or anything in C# that would lead me
// down a certain path.
String error = ex.Message;
}
}
For what it's worth, I found this happening one a smaller file in the system and was able to figure out what going on, after painstaking research into the code and the net. Basically, the file file has numeric fields on the i-series. Somehow, the records were written to the file on the original system with null values in the numeric fields instead of numeric values. When storing the original records, I had to do this calculation:
String fieldType = rs.Fields[i].Type.ToString();
object objValue = rs.Fields[i].Value;
if (fieldType == "adNumeric" && objValue is DBNull)
{
fieldValues[i] += "0";
}
else
{
fieldValues[i] += rs.Fields[i].Value;
}
After this, if null values were found in one of the numeric fields, it just put "0" in it's place so that when writing to the new machine, it would put a valid numeric character in there and continue on writing the rest of the values. Thanks for all the advice and moral support. :)
I have managed to store data, but I can't retrieve it and i would be so grateful if someone could just help me get at least 1 example working.
First I am storing data when the user signs up:
public void SetupNewParseMember(ParseUser user)
{
ParseObject gameScore = new ParseObject("GameScore");
gameScore["cash"] = 500;
gameScore["playerName"] = user.Username;
gameScore["HighestCash"] = 500;
gameScore["GamesPlayed"] = 0;
Task saveTask = gameScore.SaveAsync();
}
This works fine, I can see the data in parse and all seems ok..
The problem is when i try to retrieve the objects.
public void SetupMainScreen(ParseUser user)
{
var query = ParseObject.GetQuery("GameScore").WhereEqualTo("playerName", user.Username);
query.FindAsync().ContinueWith(t =>
{
IEnumerable<ParseObject> results = t.Result;
List<ParseObject> resultsList = results.ToList();
DealWithResults(resultsList, user);
});
}
public void DealWithResults(List<ParseObject> resultsList, ParseUser me)
{
userGamesPlayed = resultsList[1].Get<int>("GamesPlayed");
userHighestCash = resultsList[2].Get<int>("HighestCash");
userCash = resultsList[3].Get<int>("Cash");
WelcomeText.text = "Welcome, " + me.Username + "\n" +
"Cash: $" + userCash + "\n" +
"Highest Cash: $" + userHighestCash + "\n" +
"Games Played: " + userGamesPlayed;
}
First I tried just making changes to the unity ui from inside the Query but that did not work, So i made an outside function and passed the results to it that way, and that still does not work?
I tried to debug what i was getting in the list with this:
foreach (var res in resultsList)
{
Debug.Log("Class Name = " + res.ClassName + "| Keys are: " + res.Keys);
}
But all it returned was:
Class Name = GameScore| Keys are: System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.Object]
Can anyone offer any insights?
EDIT2:
ok so first i found results list and its contents
http://i.imgur.com/IKcBbey.png
Then if i open it, it seems to be null ref?
http://i.imgur.com/VmSpi9c.png
But if i go digging, i found the info i need all the way down here
http://i.imgur.com/1Wwu5uc.png
Now just need to work out how to get it?
As there is only one set of data it is always accessible through resultsList[0]. What you want is:
double cash = (double)resultsList[0]["cash"];
string playerName = (string)resultsList[0]["playerName"];
double highestCash = (double)resultsList[0]["HighestCash"];
int gamesPlayed = (int)resultsList[0]["GamesPlayed"];
Though you probably want to check that resultsList is not null and contains one element before you try to dereference it.
Also as your ParseObject appears to be a Dictionary you might find this MSDN page useful.
Ended up solving it.. Much different to the examples...
I had to make a coroutine that called a function on callback to access the variables outside of the query.
I called it with
StartCoroutine(SetupMainScreen(me, DealWithResults));
then called this.
public IEnumerator SetupMainScreen(ParseUser user, Action<GameScore> callback)
{
var query = ParseObject.GetQuery("GameScore").WhereEqualTo("playerName", user.Username).FirstOrDefaultAsync();
while (!query.IsCompleted)
{
yield return null;
}
if (query.IsFaulted || query.IsCanceled)
{
Debug.Log("Getting of GameScores faulted or cancelled...");
}
else
{
var obj = query.Result;
if (obj != null)
callback(new GameScore(obj.Get<int>("cash"),obj.Get<string>("playerName"),obj.Get<int>("HighestCash"),obj.Get<int>("GamesPlayed")));
}
}
public void DealWithResults(GameScore gs)
{
WelcomeText.text = "Welcome, " + gs.Username + "\n" +
"Cash: $" + gs.Cash + "\n" +
"Highest Cash: $" + gs.HighestCash + "\n" +
"Games Played: " + gs.GamesPlayed;
}
And i just made a class to hold the objects.. Hopefully this helps someone else.
I have an odd problem with setting time range for oneshot search. I set time range for my oneshot search, but results are just first found on server matching query. It seems like oneshot is just ignoring time range.
I've read:
How to run searches and jobs using the Splunk SDK for C# -
http://dev.splunk.com/view/csharp-sdk/SP-CAAAEQG
Service.SearchOneShotAsync Method -
http://docs.splunk.com/DocumentationStatic/CshrpSDK/2.1.1/Splunk.Client/html/a5323948-7506-ad15-6f04-7a95b70e616d.htm
JobArgs Class -
http://docs.splunk.com/DocumentationStatic/CshrpSDK/2.1.1/Splunk.Client/html/7dc4e71d-1ed7-4eb1-5a10-183d7663da26.htm
Time modifiers for search -
http://docs.splunk.com/Documentation/Splunk/6.0.3/SearchReference/SearchTimeModifiers
but after hours of tests and experiments - nothing.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var connectArgs = new ServiceArgs
{
Host = "myip",
Port = 8089,
Scheme = "https"
};
Splunk.Service service = new Splunk.Service(connectArgs);
service.Login("login", "password");
var oneshotSearchArgs = new Splunk.Client.JobArgs();
oneshotSearchArgs.EarliestTime = "2015-08-23 13:00";//textBoxOD.Text + "T" + textBoxODG.Text + ":00.000";
oneshotSearchArgs.LatestTime = "2015-08-23 14:00";//textBoxDO.Text + "T" + textBoxDOG.Text + ":00.000";
String oneshotSearchQuery = "search query *" + textBox1.text + "* | head 500";
var outArgs = new JobResultsArgs
{
OutputMode = JobResultsArgs.OutputModeEnum.Xml,
Count = 0,
};
try
{
using (var stream = service.Oneshot(oneshotSearchQuery, outArgs))
{
using (var rr = new ResultsReaderXml(stream))
{
string raw = "_raw";
foreach (var #event in rr)
{
wynik += "EVENT:" + Environment.NewLine;
foreach (string key in #event.Keys)
{
if (key.Contains(raw))
{
wynik += " " + key + " -> " + #event[key] + Environment.NewLine + Environment.NewLine;
}
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Sorry for being so late with an answer. I landed into the same issue.
The reason that your OneShot search ignores the time range is because it does not take one. (I did not come across any documentation to do so)
To overcome this issue, I tried the 2.X SDK for C#. It fixed the issue.
You can use the 2.X version in 3 steps:
Setting up Service parameters. (host, port etc.)
Authenticating the Service.
Setting up parameters for the OneShot job and executing it.
You can find the NuGet package "Splunk PCL Client for .Net" in NuGet library here.
Here is a sample code:
// Setting up Service parameters
Service _splunkService = new Service(Scheme.Https, "your-api-or-ip", 8089);
// Authenticating
await _splunkService.LogOnAsync("username", "password");
// Setting up parameters for the OneShot job and executing it
var query = "your search query";
var oneShot = new JobArgs();
oneShot.EarliestTime = DateTime.Now.AddMinutes(-2).Date.ToString("yyyy-MM-dd") + "T" + DateTime.Now.AddMinutes(-2).TimeOfDay; //"2015-09-12T12:00:00.000-07:00";
oneShot.LatestTime = "your latest time";
using (var stream = await _splunkService.SearchOneShotAsync(query, 0, oneShot))
{
try
{
foreach (var result in stream)
{
var rawValue = Convert.ToString(result.GetValue("_raw"));
if (rawValue != null)
{
// do something.
}
}
}
}
Make sure the 'await' parts go inside an async method.