Selenium2 - Running tests on CI causes multiple driver instances - selenium

For our BDD tests we use Specflow that talks to selenium 2 webdriver (Chrome driver in this instance).
While running on local host (Yes, "it works on my machine" has came up in conversation a few times) the tests work fine. They setup the data and a new webdriver, do the test and then tear down the webdriver and data. Even if a test goes horribly wrong because I'm using correct attributes the tear down is always hit and therefore driver.Quit() is run destroying the browser and the driver.
The problem arises when I run it on our server [Windows Server 2008 r2] using our continuous integration [TeamCity]. For some reason it will start to run multiple driver instances which cause the tests to fail.
Has anyone ran into this problem before and found a fix? We need a solution that uses a driver that isn't HtmlUnitDriver.
Extra information:
Language = C#
Server = Windows Server 2008 R2
CI = TeamCity
EDIT:
The Webdriver is set up by making sure that it isn't already created and then creates a new instance of the ChromeDriver. Pseudo/real code example bellow shows how its set up, sorry I cant show the full code as it has to much fluff in that we use for other options that we stick in (e.g zap or fiddler integration / language changes etc).
Setup
[SetUp]
[BeforeScenario()]
public static void BeforeWebScenario()
{
if driver == null
driver = new ChromeDriver();
// Code to start page
}
Tear down
[TearDown]
[AfterScenario()]
public static void AfterWebScenario()
{
try
{
driver.Quit();
} catch (Exception)
{
throw Exception
}
driver = null;
}

I had this problem too. I fixed it by killing any running instances of chromedriver.exe in my testSetup() method. I used a VBScript and some Groovy code to run the scripts. Sorry this answer is kind of long.
I had this in my setUp):
if (wshsc.isRunningByCommandLineContents("chromedriver.exe"))
wshsc.killProcessByCommandLineContents("chromedriver.exe")
isRunningByCommandLineContents:
If WScript.Arguments.Count = 1 Then
strCmdLine = WScript.Arguments.Item(0)
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objShell = CreateObject("WScript.Shell")
Set colProcessList = objWMIService.ExecQuery _
("Select * from Win32_Process")
If colProcessList.Count > 0 Then
For Each objItem in colProcessList
If (InStr(objItem.CommandLine, strCmdLine)) Then
If (InStr(objItem.CommandLine, "cscript")) Then
Else
WScript.StdOut.Write "A process is running with " + strCmdLine + " in its command line = " + objItem.Name
End If
End If
Next
End If
End If
killProcessByCommandLineContents:
If WScript.Arguments.Count = 1 Then
strProcess = WScript.Arguments.Item(0)
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objShell = CreateObject("WScript.Shell")
Set colProcessList = objWMIService.ExecQuery _
("Select * from Win32_Process")
If colProcessList.Count > 0 Then
For Each objItem in colProcessList
If InStr(objItem.CommandLine, strProcess) Then
If (InStr(objItem.CommandLine, "cscript")) Then
Else
WScript.StdOut.Write objItem.Name + " "
objItem.Terminate()
End If
End If
Next
Else
WScript.StdOut.Write "No instances found running"
End If
Else
WScript.StdOut.Write "Bad Arguments"
End If
And the "run the scripts part":
public void killProcessByCommandLineContents(String contents) {
List<String> arg = new ArrayList<String>()
arg.add(contents)
String [] args = arg.toArray()
runScript("killByCmdLineContents.vbs", args, true)
}
public boolean isRunningByCommandLineContents(String contents) {
List<String> arg = new ArrayList<String>()
arg.add(contents)
String [] args = arg.toArray()
String returnData = runScript("IsRunningByCmdLineContents.vbs", args, true)
if (returnData.contains(contents)) {
return true
} else {
return false
}
}
public String runScript(String name, String [] args, boolean returnOutput) {
String s = null;
List<String> cmdLine = new ArrayList<String>()
cmdLine.add("C://Windows//System32//cscript.exe")
cmdLine.add(dir + "dir//src//com//misc//wshScripts//" + name)
int index = 0
args.each() {
cmdLine.add(args[index])
index++
}
try {
String [] cmdLineArray = cmdLine.toArray()
Process p = Runtime.getRuntime().exec(cmdLineArray, null);
if (returnOutput) {
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String dataToReturn
Log.logger.info("Standard output: ");
while ((s = stdInput.readLine()) != null) {
Log.logger.info(s)
dataToReturn = s // should get last line
}
Log.logger.info("Standard error: ");
while ((s = stdError.readLine()) != null) {Log.logger.info(s);}
return dataToReturn
} else {
return ""
}
}
catch (IOException e) {
Log.logger.info(e.message, e);
}
}

If you use the DriverService interface, hold onto the service until you're done with the driver, and call DriverService.stop() as well. For me, the driver.quit() wasn't enough because I was using DriverService as well.
driver.close();
driver.quit();
driverService.stop();

Related

Get current URL from active tab chrome vb net?

I have search on google with keyword same as this question title.
Some code not work or complicated explanation, even in stackoverflow link.
I found one link work here.
But that code result is page title, not url.
How to make this code below to retrieve current url active tab on chrome?
here the code,
'//Grab all the Chrome processes
Dim chrome() As Process = Process.GetProcessesByName("chrome")
'//Exit if chrome isn't running
If chrome.Length <= 0 Then Exit Sub
For Each chromeProcess As Process In chrome
'//If the chrome process doesn't have a window handle then ignore it
If chromeProcess.MainWindowHandle <> IntPtr.Zero Then
'//To find the tabs we first need to locate something reliable - the 'New Tab' button
Dim rootElement As AutomationElement = AutomationElement.FromHandle(chromeProcess.MainWindowHandle)
Dim condNewTab As Condition = New PropertyCondition(AutomationElement.NameProperty, "New Tab")
Dim elemNewTab As AutomationElement = rootElement.FindFirst(TreeScope.Descendants, condNewTab)
'//Get the tabstrip by getting the parent of the 'new tab' button
Dim tWalker As TreeWalker = TreeWalker.ControlViewWalker
Dim elemTabStrip As AutomationElement = tWalker.GetParent(elemNewTab)
'//Loop through all the tabs and get the names which is the page title
Dim tabItemCondition As Condition = New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem)
For Each tabItem As AutomationElement In elemTabStrip.FindAll(TreeScope.Children, tabItemCondition)
Debug.WriteLine(tabItem.Current.Name)
Next
End If
Next
Solved, From another forum,
Imports System.Windows.Automation
Module GoogleChrome
Private Const ChromeProcess As [String] = "chrome"
Private Const AddressCtl As [String] = "Address and search bar"
Public Function GetChromeActiveWindowUrl() As [String]
Dim procs = Process.GetProcessesByName(ChromeProcess)
If (procs.Length = 0) Then
Return [String].Empty
End If
Return procs _
.Where(Function(p) p.MainWindowHandle <> IntPtr.Zero) _
.Select(Function(s) GetUrlControl(s)) _
.Where(Function(p) p IsNot Nothing) _
.Select(Function(s) GetValuePattern(s)) _
.Where(Function(p) p.Item2.Length > 0) _
.Select(Function(s) GetValuePatternUrl(s)) _
.FirstOrDefault
End Function
Private Function GetUrlControl( _
proses As Process) _
As AutomationElement
Dim propCondition = _
New PropertyCondition( _
AutomationElement.NameProperty, _
AddressCtl)
Return AutomationElement _
.FromHandle(proses.MainWindowHandle) _
.FindFirst( _
TreeScope.Descendants, _
propCondition)
End Function
Private Function GetValuePatternUrl( _
element As Tuple(Of _
AutomationElement, AutomationPattern())) As [String]
Dim ap = element.Item2(0)
Dim ovp = element.Item1.GetCurrentPattern(ap)
Dim vp = CType(ovp, ValuePattern)
Return vp.Current.Value
End Function
Private Function GetValuePattern( _
element As AutomationElement) _
As Tuple(Of _
AutomationElement, _
AutomationPattern())
Return New Tuple(Of _
AutomationElement, _
AutomationPattern())( _
element, _
element.GetSupportedPatterns())
End Function
End Module
If you are using .Net framework 2.0 it works for Google Chrome 55 And Firefox. Send the process name to the method ("CHROME" or "FIREFOX"). Also, you must import UIAutomationClient.dll. I hope it helps someone.
private string GetBrowserUrlActivaChromeFirefox(string process)
{
Process[] procsChrome = Process.GetProcessesByName(process);
foreach (Process chrome in procsChrome)
{
if (chrome.MainWindowHandle == IntPtr.Zero)
continue;
UIAutomationClient.CUIAutomation element = new UIAutomationClient.CUIAutomation();
UIAutomationClient.IUIAutomationElement root = element.ElementFromHandle(chrome.MainWindowHandle);
if (element == null)
return "";
UIAutomationClient.IUIAutomationCondition condition1 = element.CreatePropertyCondition(UIAutomationClient.UIA_PropertyIds.UIA_ProcessIdPropertyId, chrome.Id);
UIAutomationClient.IUIAutomationCondition condition2 = element.CreatePropertyCondition(UIAutomationClient.UIA_PropertyIds.UIA_IsControlElementPropertyId, true);
UIAutomationClient.IUIAutomationCondition condition3 = element.CreatePropertyCondition(UIAutomationClient.UIA_PropertyIds.UIA_IsContentElementPropertyId, true);
UIAutomationClient.IUIAutomationCondition condition4 = element.CreatePropertyCondition(UIAutomationClient.UIA_PropertyIds.UIA_ControlTypePropertyId, UIAutomationClient.UIA_ControlTypeIds.UIA_EditControlTypeId);
UIAutomationClient.IUIAutomationCondition[] conditions = new UIAutomationClient.IUIAutomationCondition[4];
conditions[0] = condition1;
conditions[1] = condition2;
conditions[2] = condition3;
conditions[3] = condition4;
UIAutomationClient.IUIAutomationCondition andCondition = element.CreateAndConditionFromArray(conditions);
UIAutomationClient.IUIAutomationElement elementx = root.FindFirst(UIAutomationClient.TreeScope.TreeScope_Descendants, andCondition);
return ((UIAutomationClient.IUIAutomationValuePattern)elementx.GetCurrentPattern(UIAutomationClient.UIA_PatternIds.UIA_ValuePatternId)).CurrentValue.ToString();
}
return string.Empty;
}
This C# code works for me on non-English browsers:
// Check for Chrome
if (processName.Equals("chrome"))
{
Process[] procsChrome = Process.GetProcessesByName("chrome");
foreach (Process chrome in procsChrome)
{
// the chrome process must have a window
if (chrome.MainWindowHandle == IntPtr.Zero)
continue;
try
{
CUIAutomation _automation = new CUIAutomation();
var appElement = _automation.ElementFromHandle(chrome.MainWindowHandle);
IUIAutomationCondition[] conditionArray = new IUIAutomationCondition[3];
conditionArray[0] = _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_ProcessIdPropertyId, chrome.Id);
conditionArray[1] = _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_NamePropertyId, "Google Chrome");
conditionArray[2] = _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_PaneControlTypeId);
IUIAutomationCondition conditions = _automation.CreateAndConditionFromArray(conditionArray);
IUIAutomationElement frameElement = appElement.FindFirst(TreeScope.TreeScope_Subtree, conditions);
if (frameElement != null)
{
conditionArray = new IUIAutomationCondition[2];
conditionArray[0] = _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_ProcessIdPropertyId, chrome.Id);
conditionArray[1] = _automation.CreatePropertyCondition(UIA_PropertyIds.UIA_ControlTypePropertyId, UIA_ControlTypeIds.UIA_EditControlTypeId);
conditions = _automation.CreateAndConditionFromArray(conditionArray);
frameElement = frameElement.FindFirst(TreeScope.TreeScope_Descendants, conditions);
if (frameElement != null)
return ((IUIAutomationValuePattern)frameElement.GetCurrentPattern(10002)).CurrentValue;
}
}
catch (Exception e)
{
continue;
}
}
}
The COM interface is much more efficient then the old one from System.Windows.Automation.

Executing script on a remote server

The following code works when the script is executed on the current machine
(Currently, the script is a simple messagebox displaying the argument passed)
Arguments:
UserName = Nothing
Password = Nothing
RemoteMachineName = "CurrentMachineName"
PathBashFile = "Path/To/My/Local/Script.ps1"
Params = "parameter1"
However, when I want to run a local script on a remote computer, the script is never actually executed. The code doesn't throw any exception.
Arguments:
UserName = "MyUsername"
Password = "MyPassword"
RemoteMachineName = "RemoteMachineName"
PathBashFile = "Path/To/My/Local/Script.ps1"
Params = "parameter1"
All I have as a result is :
outParams("processId") = Nothing
outParams("returnValue") = 8
What's going on? Why isn't my script running as expected on the remote machine? (No message box pops up on either machine. I have tried other cmdlets, but none ever work)
Here is the code:
Try
connOptions = New ConnectionOptions()
connOptions.Username = UserName
connOptions.Password = Password
connOptions.Impersonation = ImpersonationLevel.Impersonate
connOptions.Authentication = Management.AuthenticationLevel.PacketPrivacy
managementPath = New ManagementPath("\\" & RemoteMachineName & "\root\cimv2:Win32_Process")
Scope = New ManagementScope(managementPath, connOptions)
Scope.Connect()
objectGetOptions = New ObjectGetOptions()
processClass = New ManagementClass(Scope, New ManagementPath("root\cimv2:Win32_Process"), objectGetOptions)
inParams = processClass.GetMethodParameters("Create")
inParams("CommandLine") = "cmd.exe /c powershell """ & PathBashFile & """ " & params
inParams("CurrentDirectory") = workingDirectoryPath
outParams = processClass.InvokeMethod("Create", inParams, Nothing)
MsgBox(outParams("processId") & " " & outParams("returnValue"))
Catch ex As Exception
Throw New Exception("[ExecuteRemoteBashFile] " & ex.Message)
End Try
If someone could point out any mistakes in my code, it would be greatly appreciated!
I solved my problem by putting the complete path to powershell.exe, instead of assuming that the console knows where to look for that...
inParams("CommandLine") = "cmd.exe /c C:\Windows\System32\WindowsPowerShell\v2.0\powershell.exe """ & PathBashFile & """ " & params

lotuscript: some questions about connecting to a SQL DB

I've got this code that is working... I read from an MS SQL database some rows from a table and then send an email for each row.
I'm about to add an "attachment" field, on my SQL database and I'd like to add the attachment at the end of my body.
I have two questions: 1) what datatype should I use on MS SQL? (Binary field, maybe) and 2) if someone else has some example code, I'd really appreciate it.
A bonus question: on a more advanced version of this script, i first run by all my results from my resultset to get the IDs from the messages and then update their status on the MS SQL table.
Then I try and run by the same resultset again, to actually perform the sending....
Somehow, on the second run, I'm having trouble starting from row 1, using the same code than bellow... any advice on what's the best way to do that?: My requirement is that I have to run twice by the same resultset. :)
Thanks in advance.
Option Public
Uselsx "*LSXODBC"
Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim subject As String, cc As String, bcc As String, sender As String, OID As String, mailto As String, bodyNotMIME As String
Dim body As NotesMIMEEntity
On Error Goto errorCounter
Set db = session.CurrentDatabase
Gosub SendMailGeneral
Exit Sub
SendMailGeneral:
Dim con As New ODBCConnection
Dim qry As New ODBCQuery
Dim result As New ODBCResultSet
Dim defaultQuery As String
Set qry.Connection = con
con.SilentMode = True
If con.ConnectTo("DSN_Name","USER_NAME", "PASSWORD") Then
Set result.Query = qry
defaultQuery = "select TOP (10) * from Message where StatusType=0"
qry.SQL = defaultQuery
result.Execute
If (result.IsResultSetAvailable) Then
Do
result.NextRow
Gosub GetRowFields
Gosub SendMail
Loop Until result.IsEndOfData
End If
End If
result.Close(DB_CLOSE)
Return
End Sub
GetRowFields:
mailto = result.GetValue("To")
cc = result.GetValue("CC")
bcc = result.GetValue("Bcc")
sender = result.GetValue("Sender")
subject = result.GetValue("Subject")
bodyNotMIME = result.GetValue("Body")
OID = result.GetValue("OID")
Return
SendMail:
Dim mail As NotesDocument
Set mail = New NotesDocument(db)
Dim stream As NotesStream
Set stream = session.CreateStream
'Recipients
mail.SendTo = mailto
mail.CopyTo = cc
mail.BlindCopyTo = bcc
' Set all sender-related fields
mail.ReplyTo = sender
mail.Principal = sender
mail.From = sender
mail.AltFrom = sender
mail.SendFrom = sender
mail.INetFrom = sender
mail.tmpDisplaySentBy = sender
mail.tmpDisplayFrom_Preview = sender
mail.DisplaySent = sender
'Body
Call stream.WriteText(bodyNotMIME)
Set body = mail.CreateMIMEEntity
Call body.SetContentFromText _
(stream, "text/html; charser=iso-8859-1", ENC_NONE)
'Subject
mail.Subject = subject
'Send
Call mail.Send(False, False)
Return
Wasn't this line:
result.NextRowcode
supposed to be:
result.NextRow
?
I don't know about MSSQL, but in DB2 we routinely use Blob/Clob binary data type to store any type of files.
I hear that many MSSQL experts recommend rather storing files on file system with only their path and file name in a DB.
OK, here's the abbreviated code from my Java ScriptLibrary that uses JDBC to connect to DB2 and execute a query (you would only need to import your db's jar-s and use com.microsoft.sqlserver.jdbc.SQLServerDriver for MS SQL):
import java.sql.*;
import com.ibm.db2.jcc.DB2Driver;
public class DB2Connection {
protected String server;
protected String port;
protected String dbName;
protected String userdb2;
protected String pwddb2;
protected java.sql.Connection con;
public DB2Connection( String srv, String port, String db, String user, String pass ){
this.server = srv;
this.port = port;
this.dbName = db;
this.userdb2 = user;
this.pwddb2 = pass;
connectDB2();
}
public void connectDB2() {
try {
Class.forName("com.ibm.db2.jcc.DB2Driver"); // .newInstance();
String url = "jdbc:db2://" + server + ":" + port + "/" + dbName;
con = DriverManager.getConnection(url, userdb2, pwddb2);
System.out.println("Connection to DB2 succeded");
} catch (Exception e) {
System.out.println("Error connecting DB2 Server") ;
e.printStackTrace();
}
}
protected ResultSet executeQuery( String queryString ) throws SQLException, Exception {
System.out.println( "Preparing query:\t" + queryString );
ResultSet rs = null;
try {
Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery(queryString);
} catch (SQLException sqle) {
String error = ("SQLException : Could not execute query");
throw new SQLException(error);
} catch (Exception e) {
String error1 = ("Exception : An Unknown error occurred.");
throw new Exception(error1);
}
return rs;
}
protected int executeCountQuery( StringBuffer queryStr ){
System.out.println( "Preparing query:\t" + queryStr );
try {
ResultSet rs = executeQuery( queryStr.toString( ) );
rs.next(); //only one row in result set
return rs.getInt(1);
} catch (SQLException sqle) {
System.out.println("SQLException: Could not get ResultSet from DB2Connection.executeQuery");
sqle.printStackTrace();
} catch (Exception e) {
System.out.println("Exception : An Unknown error occurred while calling.");
e.printStackTrace();
}
return 0;
}
protected int executeCountQuery( PreparedStatement ps ){
//System.out.println( "Preparing prepared statement - query:\t" ); //+ ps.getQuery( ) );
try {
ResultSet rs = ps.executeQuery( );
rs.next(); //only one row in result set
return rs.getInt(1);
} catch (SQLException sqle) {
System.out.println("SQLException: Could not get ResultSet from DB2Connection.executeQuery");
sqle.printStackTrace();
} catch (Exception e) {
System.out.println("Exception : An Unknown error occurred while calling.");
e.printStackTrace();
}
return 0;
}
public Connection getConnection(){
return con;
}
}
To check out the examples of using LS2J to use Java classes directly from your LotusScript code, download this great LS2J samples database from Julian Robichaux:
http://www.nsftools.com/tips/NotesTips.htm#ls2jexamples
And here's a good link to start with, explains how to use JDBC with MS SQL server:
http://support.microsoft.com/kb/313100

Timeout not working in SQL Connection

I have this simple code to test that a DB is ready:
Function testlocalcon() As Boolean
Dim constr As String = _clconstr
Try
Using t As New SqlConnection()
constr = constr & " ; Connect Timeout=1"
If Not t.State = Data.ConnectionState.Open Then
t.ConnectionString = constr
t.Open()
If t.State = Data.ConnectionState.Open Then
Return True
Else
Return False
End If
Else
Return True
End If
End Using
Catch ex As Exception
Return False
End Try
End Function
I do not want to execute a query, just to check the connection, but no matter what the time out parameter is ignored. I search here (Stackoverflow) and internet and found nothing in how to fix this.
Any one else have this problem? Or, are there any other ideas on how to let the application know that the DB is ready?
I appologize for the code differenc but this is C# and I have used it in the past. Its pretty simple and should be readable.
private SQLServerConnection
private SqlConnection _SQLServerConnection;
public SqlConnection SQLServerConnection
{
get
{
return _SQLServerConnection;
}
set
{
_SQLServerConnection = value;
}
}
private void SetSQLServerConnectionString (string sqlServerName, string databaseName, string saPassword, int connectTimeout)
{
SQLServerConnection = new SqlConnection("Password=" + saPassword + ";Persist Security Info=True;User ID=sa;Initial Catalog=" + databaseName + ";Data Source=" + sqlServerName + ";connection timeout=" + connectTimeout.ToString(CultureInfo.InvariantCulture));
}
internal bool TestSQLServerConnection(string sqlServerName, string databaseName, string saPassword, int connectTimeout)
{
try
{
SetSQLServerConnectionString(sqlServerName, databaseName, saPassword, connectTimeout);
SQLServerConnection.Open();
return true;
}
catch (SqlException e)
{
return false;
}
finally
{
SQLServerConnection.Close();
}
}

FileUpload1.PostedFile.FileName is throwing exception

I am using ASP.NET to read the data in the excel file. I am using a file upload control to read the file. I am able to read the data from the file in my local machine, but after deploying my code in the server, when I try to read the file from the client machine, I am getting an exception.
FileUpload1.PostedFile.FileName is throwing the exception in the server.
The exception message is:
'D:\path in client machine\MyExcel.xls' could not be found. Check the spelling of the file name, and verify that the file location is correct. If you are trying to open the file from your list of most recently used files on the File menu, make sure that the file has not been renamed, moved, or deleted.
Please help.
Code :
<add key="OleDbConnection" value="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=
FilePath ;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1""/>
string OleDbConnection =
ConfigurationManager.AppSettings["OleDbConnection"].ToString().Replace("FilePath",
fileUpload.PostedFile.FileName).Trim();
Excel.ApplicationClass xlApp = new Excel.ApplicationClass();
Excel.Workbooks xlWorkBooks = (Excel.Workbooks)xlApp.Workbooks;
Excel.Workbook wb = xlWorkBooks._Open(fileUpload.PostedFile.FileName, Type.Missing,
false, Type.Missing, "", "", true, Excel.XlPlatform.xlWindows, "\t", true,
false, Type.Missing, true);
string strSheetName = ((Excel.Worksheet)wb.Sheets[1]).Name.ToString();
xlWorkBooks.Close();
xlApp.Quit();
oledbCommand = new OleDbCommand();
oledbAdapter = new OleDbDataAdapter();
DataSet dsExcellData = new DataSet();
oledbConnection = new OleDbConnection(OleDbConnection);
oledbConnection.Open();
oledbCommand.Connection = oledbConnection;
oledbCommand.CommandText = "Select * from [" + strSheetName + "$]";
oledbAdapter.SelectCommand = oledbCommand;
oledbAdapter.Fill(dsExcellData);
return dsExcellData
Hi I am posting the sample code that i am having
Add a fie upload control and a button.On the button click execute the below code after selecting the file from the client machine.
string OleDbConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= \"FilePath\";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
OleDbConnection = OleDbConnection.Replace("FilePath", FileUpload1.PostedFile.FileName);
Label6.Text = OleDbConnection;
string strSheetName = "ASSET_RECV";
OleDbConnection oledbConnection;
OleDbCommand oledbCommand;
OleDbDataAdapter oledbAdapter;
oledbCommand = new OleDbCommand();
oledbAdapter = new OleDbDataAdapter();
DataSet dsExcellData = new DataSet();
oledbConnection = new OleDbConnection(OleDbConnection);
oledbConnection.Open();
oledbCommand.Connection = oledbConnection;
//oledbCommand.CommandText = "Select * from [{0}$]";
oledbCommand.CommandText = "Select * from [" + strSheetName + "$]"; // i want to find this sheet name
oledbAdapter.SelectCommand = oledbCommand;
oledbAdapter.Fill(dsExcellData);
oledbConnection.Close();
GridView1.DataSource = dsExcellData.Tables[0];
GridView1.DataBind();
1) Publish the project in IIS.Try to run the application from another machine and read the data from the excel file (from client machine).
you will get the below error .Please help.
The Microsoft Jet database engine could not find the object 'D:\FileName.xls'. Make sure the object exists and that you spell its name and the path name correctly.
I think you need to save the file before you can open it. You can use:
PostedFile.SaveAs()
to save it to the server.
Did that help?
Can you post your uploading code?
Should be something like this..
<asp:FileUpload ID="batchUpload" runat="server" />
<asp:Button runat="server" ID="uploadButton" Text="Upload" OnClick="UploadButton_Click" />
protected void UploadButton_Click(object sender, EventArgs e)
{
// Server time out 50 mins..
Context.Server.ScriptTimeout = 60 * 50;
errorLabel.Style[HtmlTextWriterStyle.Color] = "Red";
if (batchUpload.PostedFile == null || batchUpload.PostedFile.ContentLength == 0) {
errorLabel.InnerText = "Enter a valid file";
uploadButton.Enabled = true;
return;
}
string path = XMAppSettings.UploadsPath;
filePath = Path.Combine(path, batchUpload.FileName);
try {
batchUpload.SaveAs(filePath);
} catch (HttpException exception) {
errorLabel.InnerText = "Fatal error";
exception.Log();
return;
}
Notice the batchUpload.SaveAs(filePath)
Confirm the save!
Also, since you are trying to extract data from an excel sheet I'd suggest you exploit Linq over datasets(if you are not planning to do inserts). Excel.ApplicationClass will require that you reference the excel interops
/// <summary>
/// Summary description for ExcelHelper.
/// </summary>
internal sealed class ExcelHelper
{
private const string CONNECTION_STRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=<FILENAME>;Extended Properties=\"Excel 8.0;HDR=Yes;\";";
public static DataTable GetDataTableFromExcelFile(string fullFileName, ref string sheetName)
{
OleDbConnection objConnection = new OleDbConnection(CONNECTION_STRING.Replace("<FILENAME>", fullFileName));
DataSet dsImport = new DataSet();
try {
objConnection.Open();
DataTable dtSchema = objConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if ((null == dtSchema) || (dtSchema.Rows.Count <= 0)) {
throw new ArgumentNullException("No sheets");
}
//Reading the first sheet name from the Excel file.
sheetName = dtSchema.Rows[0]["TABLE_NAME"].ToString();
new OleDbDataAdapter("SELECT * FROM [" + sheetName + "]", objConnection).Fill(dsImport);
} catch (Exception e) {
e.Log();
throw;
} finally {
objConnection.Close();
objConnection.Dispose();
}
return dsImport.Tables[0];
}
}
and then do stuff like
var table = ExcelHelper.GetDataTableFromExcelFile(fileName, ref something).AsEnumerable();
var rollnoList = table
.Where(x => !String.IsNullOrEmpty(x.Field<string>("Roll Number")))
.Select(x => ExtractUser(x));
You need to make sure the file exists where you say it does. The error is saying it cannot find the file specified by the path. Also make sure your spelling is correct.
Thanks for the replies.I have fixed the issue.
The mistake that i did was i supplied the FileUpload1.PostedFile.FileName as a path to the excel connection string.What happens when we deploy the code in the server and try to read the excell is ,it is searching for the file in the server path.
So we need to save the file to the server before reading the file and we need to pass that server path to the excel connection string.
After reading the data from the excel you can delete the file.
But i am not sure whether there are some other work around like passing the file object as the datasource for the excel connection string.