Calling a vb script from a asp.net / C# webpage - c#

I have written an ASP.NET web page with C# behind that runs an existing vb script.
The idea is that the user uploads an Excel spreadsheet (.xls) using the web page, the C# does a few basic checks on the file (file type, file name etc) then saves the .xls to a network location.
The C# then passes the network path of the .xls to the vb script, which gets the required information from the .xls to create a .csv file.
Finally the .csv is passed into a stored procedure and uploaded to a database table.
The problem is that all this runs perfectly when I run the webpage locally on my machine. However when I upload the page to the webserver it does not seem to execute the vb script; instead it just sits there waiting for the script to exit.
Some quick info:
Excel is installed on the web server
The website is set to execute scripts and executables
The script is currently set to 'run as' my personal domain login (this has to change) which has admin on the web server
If I run the script on the webserver using the cmd prompt it works
I'd really appreciate any ideas on what might be going wrong... seriously, I'm pulling my hair out over this one and will consider any idea, no matter how crazy... but, and it's a big one, despite the fact that that there are many other ways of achieving the same result, I'm afraid that for a number of reasons this is what I have to work with :)
Edit
Here is how I call the script
try
{
System.Security.SecureString password = new System.Security.SecureString();
string uspw = "mypassword";
foreach (char c in uspw)
{
password.AppendChar(c);
}
Process scriptProc = new Process();
scriptProc.StartInfo.FileName = #"cscript";
scriptProc.StartInfo.Arguments = scriptPath + " //Nologo " + uploadPath + xlsFileName;
scriptProc.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
scriptProc.StartInfo.UserName = "myusername";
scriptProc.StartInfo.Password = password;
scriptProc.StartInfo.UseShellExecute = false;
scriptProc.Start();
scriptProc.WaitForExit();
scriptProc.Close();
}
catch...
All of the file paths are relative.
The code seems to fail when the script is called. You can clearly see the page waiting for the script to finish. However if you watch the task manager on the web server neither cscript or excel start to run.
I've also stuck a message box right at the start of the script which does not get displayed
Edit 2
It turns out that cscript is running, I just needed to tick the 'All Users' check box in the task manager... I'm still none the wiser though!
Thanks so much in advance

Sounds like you are using automation to control the Excel application itself?
Some quick info:
Excel is installed on the web server
That is generally a bad idea, because the Excel application is not an application that is intended to be automated by a server. Thing might hang because the application is waiting for user input in a dialog somewhere. And it's not scalable for handling operations from multiple users simultaneously.
If the final goal is to extract the data from the excel file and put it in an sql server, I would rather suggest that you use the Jet OLEDB provider to retrieve the data from the excel file, either from your web application, and letting that feed the data into sql server, or let the sql server do it directly. If there is a lot of data in the excel file, the latter might be the best choice

Without seeing the code this is a blind guess - I suggest you check how you are specifying the path to the vb script - make sure you are not using an absolute path, and that the file is in the same location relative to the C# page on the server as it is on your machine.

Related

Unable to determine if a file is on a web server because the various methods of determining the directory do not work

I am developing an application in asp.net, vs2015 using c# and the development environment is a Win10Pro machine. I can use any of the various methods to obtain the working directory and see if a particular file exists on the dev pc, but not on the Web Server. I have tried the methods laid out on:
Get current application physical path within Application_Start
All work on the Dev PC, but when used on the Web Server it will not return the working directory. The Server is a 2016 Data server using IIS10. The issue is that the web site I am putting together work fine, except to display GrapeCity ActiveReports reports AR15. The web page containing their web viewer opens just fine and is looking for a report file (MyReport.rdlx). The global.aspx file is pointing to the root directory but when the web viewer opens up, it says File Not Found. I have absolutely no idea and tech support is not sure. Is this an IIS issue that is preventing the code to locate and verify the file is there? Any direction would be much appreciated. This has been very frustrating and time consuming.
AppDomain.CurrentDomain.BaseDirectory does not work, HttpRuntime.AppDomainAppPath does not as well as all the others. The request comes back blank.
string filename = AppDomain.CurrentDomain.BaseDirectory.ToString() +"SPU01_Dates.rdlx";
if (File.Exists(filename))
{
Response.Write("YES");
}
else
{
Response.Write("NO");
Response.Write("</br");
Response.Write(filename);
}
All this just returns nothing.
Thanks.
Try this code
if (File.Exists(Server.MapPath(filename)))
Check if a file exists on the server
In my test, it returned YES and worked well. Did you put "SPU01_Dates.rdlx" file in root folder?
In the development environment, it returned YES, and when I deployed it to IIS, it returned NO. I found that during the deployment process, the rdlx file was not deployed with the project, so I recreated one in the deployed folder, and it returned YES.
The test proves that AppDomain.CurrentDomain.BaseDirectory is the most accurate way to get the file path. When you test this code in IIS, does it return NO or empty? Returning empty means that this piece of code has not been executed.

C# Executing a query and getting data out of an Access Database (accdb) without using ACE.OLEDB

I'm writing a WPF application.
Trying to use the normal method of getting a connection returns an error similar to: "The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine."
ACE.OLEDB has never been installed on this machine so this error makes sense.
I'm trying to create this application in a way so that our users won't need to contact IT to have the application installed. Getting IT involved is a no go situation and the project will be abandoned.
Another team has an Access database (accdb) that I want my application to extract information (only read, no insert or update). I talked to the team and they won't convert this database back to an earlier version (mdb).
After my research I assume that installing ACE.OLEDB without using Admin privileges is impossible. Because of this and my application requirement of not requiring admin privileges I need to start looking for "Mutant"/Dirty solutions that don't involve ACE.OLEDB.
I tried using power-shell but I'm getting the same problems as I had with C# (requires IT to install ACE.OLEDB).
I have two potential solutions. One write a VBA script that opens up the database and dumps a query result into a file. My C# application would call this VB script and then parse the created file.
The second option is to create a new Access process using Process.Start(fullFilePath) and somehow pass the command to execute a query and somehow pass the results back to the executing application (either via a method return or first to a file).
How would you get the data out?
Is there a way for C# to duplicate the DB file and convert it from (accdb -> mdb)?
This is the second question I ask that is very similar.
C# Connecting to Access DB with no install
The difference between the two (to prevent this is a duplicate question) is that in the previous question I was looking for ways to install ACE.OLEDB without admin privileges while here I'm just looking for any other work around.
Found a workaround. It uses Microsoft.Office.Interop.Access found in NuGet.
var accApp = new Microsoft.Office.Interop.Access.Application();
accApp.OpenCurrentDatabase(#tests.DatabasePath);
Microsoft.Office.Interop.Access.Dao.Database cdb = accApp.CurrentDb();
Microsoft.Office.Interop.Access.Dao.Recordset rst =
cdb.OpenRecordset(
"SELECT * FROM Users",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenSnapshot);
while (!rst.EOF)
{
Console.WriteLine(rst.Fields["username"].Value);
rst.MoveNext();
}
rst.Close();
accApp.CloseCurrentDatabase();
accApp.Quit();

How to read txt file on Client from aspx c# website

i have a question, I have this code
foreach (string line in File.ReadLines(**#"C:\fis32v6\fis32.ini"**))
{
if (line.Contains("TEST1"))
{
Label1.Text="TEST1";
PdLine = "1";
}
}
DataSet ds;
ds = GetData(PdLine.ToString());
I want to read from txt file on client specific line with condition. When developing this and building the code it works, what ever i change in txt file can be read from my PC. But when I run the website on server it reads the txt file on that server instead of client I opened the website.
Is there any possibility to make the path relative?
As John mentioned that would be a huge security issue, mostly to make sure the website doesn't dig around in your system.
However it can be instigated from client side.
Just have search here on SO for 'upload file using asp.net' there are loads of hits with answers listed.
You didn't mention specific versions you use (MVC?, asp.net? / core?), and no context as to what workflow your code is running in (is it run on connection or during a specific process), is it configuration settings used for the web session itself? but it is possible to upload.
Should you require the file during startup that might be a bit trickier as you'd have to upload it somehow.
If however it is settings for the web session, why not save it in a cookie?

Microsoft Excel cannot access the file "...". There are several possible reasons Windows Server 2008 R2 with Microsoft Office 2010

I have a problem with starting the Excel Application under a particular user.
I try to schedule this script (C#) through an application X (not Windows Task Scheduler. And this application will always use a service account to run services on the server). If I run the C# script in command prompt under the same user, it runs. Under the application X, which uses the exact same user, to initiate the C# script, it fails to open the Excel application (not sufficient permission?).
This script calls:
app.Workbooks.Open(ExcelFileName,0,false,Type.missing....), yet it gives the following error:
Microsoft Excel cannot access the file "...". There are several possible reasons:
-The file name or path does not exist.
-The file is being used by another program.
-The workbook you are trying to save has the same name as a currently open workbook.
I tried all the methods that I found online to no avail.
Create directory “C:\Windows\SysWOW64\config\systemprofile\Desktop” (for 64 bit Windows) or “C:\Windows\System32\config\systemprofile\Desktop” (for 32 bit Windows). Then Set full control permissions on Desktop directory above (for example in Win7 & IIS 7 & DefaultAppPool set permissions for user “IIS AppPool\DefaultAppPool”)
Changed the DCOM config for the Microsoft Excel application to include this user for Local/Remote Launch and Access
Enabled all macros in Excel and set the Trust Center.
Add the user to have full control on all folders that contain the Excel file.
Under DCOM config, Microsoft Excel Application, if I modify the Identity tab to check on "This User" and enter the username/password to let Excel always run under that user. Then the application runs perfectly. However, other users can't run the excel application on their own with the following error: "Cannot use object linking and embedding". If I check "Use the launching user", then Excel can't be launched. No errors in the logs or events anywhere to check.
Yet, still the same error. I think it's permission but I am not sure where and what to do for this to work.
Now, normally, when I run this excel report, I can double-click on the file and it'd automatically run, save the new parameters into the current file and generate a new excel file (with date attached to the file name). That means there is a change (save) to the original file.
I appreciate all your help!
I found the problem is the layer of security in the server!
Creating the Desktop folder inside the C:\Windows\System32\config\systemprofile and giving the service account permission to access the desktop folder is not enough.
I modified the C:\Windows\System32\config (or C:\windows\SysWOW64\config) folder to allow permission to the service account in security tab.
Then I also had to set up the same permission for the sub folder C:\Windows\System32\config\systemprofile (or C:\windows\SysWOW64\config\systemprofile) for the service account.
This works!
Microsoft Excel cannot access the file in Server 2012 Excel 2016.. checked various solutions online to create folder desktop in C:\Windows\SysWOW64\config\systemprofile\desktop.. didn't work for this but then i added a folder desktop in System32 and that definitely worked.
Since I have 64-bit Excel installed, the proper directory turned out to be the
c:\windows\system32\config\systemprofile\desktop
I ran across another way you can get this error: when you try to save a file with an "illegal" name, such as one with whacks (forward slashes) in it.
For that reason, it would seem reasonable that the err msg would give that as one possible explanation of the problem, but...no!
Specifically, I was trying to save a file named C:\RoboReporter\ABUELITOS\20160524_1327\ABUELITOS - Fill Rate - 4\1\61910B10
The whacks (shown as backwhacks in the copied exception text, but seen as forwardwhacks when hovering over the value when debugging) were the cause of the discombobulation. Once I fixed that by replacing whacks with underscores:
filename = String.Format("{0}\\{1} - Fill Rate - {2}.xlsx", uniqueFolder, _unit, _begDate.ToShortDateString());
filename = filename.Replace("/", "_");
...all went swimmingly.

Change SSRS data source of report programmatically in server side

Today, for each customer, we deploy same SSRS reports folder and data source folder.
The difference between these folders are the name of each folder and the connection string of the data source.
We are using Report Server 2008 R2.
Is it possible to maintain only one reports and data source folder and change programmatically its connection string on server-side before the report been rendered?
If not, Is it something that can be achieved by changing some logic in reports?
Today we use "shared data source" option.
This is something we've done in our environment - we maintain one set of reports that can be deployed at any client with their own configuration.
You've got a couple of options here. Since you're using a Shared Data Source this makes things easier as you won't need to define a Data Source for each report.
1. Use the rs.exe utility and a script file
rs.exe at Books Online
This program allows you to create script files (in VB.NET) that can interact with a Report Server Web Service. You create a script file (e.g. Deploy.rss) and call the rs.exe program with various parameters, including any custom ones you define:
rs.exe -i DeployReports.rss -s http://server/ReportServer -v DatabaseInstance="SQL" -v DatabaseName="ReportDB" -v ReportFolder="ClientReports"
So this would call a script DeployReports.rss, connect to http://server/ReportServer, with three user defined parameters which could be used to create a data source and the report folder.
In the scipt file you could have something like this:
Public Sub Main()
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
CreateFolder(reportFolder, "Report folder")
CreateFolder(datasourceFolder, "Data source folder")
CreateDataSource()
End Sub
Which can then make Web Service calls like:
rs.CreateFolder(folderName, "/", Nothing)
'Define the data source definition.
Dim definition As New DataSourceDefinition()
definition.CredentialRetrieval = CredentialRetrievalEnum.Integrated
definition.ConnectString = "data source=" + DatabaseInstance + ";initial catalog=" + DatabaseName
definition.Enabled = True
definition.EnabledSpecified = True
definition.Extension = "SQL"
definition.ImpersonateUser = False
definition.ImpersonateUserSpecified = True
'Use the default prompt string.
definition.Prompt = Nothing
definition.WindowsCredentials = False
Try
rs.CreateDataSource(datasource, datasourcePath, False, definition, Nothing)
Console.WriteLine("Data source {0} created successfully", datasource)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
You haven't specified what version of Reporting Services you're using, so I'm assuming 2008. Please note that there are multiple endpoints that can be used, depending on SQL Server version. The 2005/2008 end point is deprecated in 2008R2 and above but is still usable. Just something to bear in mind when writing your script.
2. Call the SSRS Web Service through an application
Report Server Web Service overview
The same calls that are made from the script above can be made in any other application, too. So you'd just need to add a reference to a Report Server Web Service through WSDL and you can connect to a remote service and call its methods to deploy reports, data sources, etc.
So ultimately you're connecting to the Report Server Web Service, it's just the medium used that you need to think about.
Using a script is easier to get running as it's just running a program from the command line, but writing your own deployment application will certainly give greater flexibility. I would recommend getting the script going, so you understand the process, then migrate this to a bespoke application if required. Good luck!
You can use an Expression Based Connection String to select the correct database. You can base this on a parameter your application passes in, or the UserId global variable. I do believe you need to configure the unattended execution account for this to work.
Note: be careful about the security implications. Realize that if you would pass sensitive data (e.g. passwords) into a parameter, that (a) it will go over the wire, and (b) will be stored in the execution log tables for reporting services.

Categories