I run a website with IIS 7.5 in classic ASP with an isolated Application Pool (ApplicationPoolIdentity). Inside this website I also run unmanaged code (wkhtmltopdf.exe) thru "WScript.Shell" object run method. After that I stream the result file as pdf
set wshell = CreateObject("WScript.Shell")
wshell.run wkhtmltopdf.exe http://www.mypagehanging.com c:\myfile.pdf", 0, TRUE
set wshell = nothing
Everything works fine but sometimes my Website Hang. It's completely stuck. The wktmltopdf.exe running under the identity of the app pool (iis apppool\myapp) hangs.
This causes my all website to hang because i run the program with option bWaitOnReturn to true.
I cannot set this option to false because I must wait for the script to execute completely before streaming the pdf.
Couldn't find any timeout option to give to wkhtmltopdf. Couldn't understand why wkhtmltopdf was hanging. But it's probably caused by the website I'm trying to render and not wkhtmltopdf.
Any suggestions ?
I've addressed this problem by killing the process if it takes an unusual amount of time to run.
here is my code should it be helpful to someone.
In the asp file
'Run this programm that will kill pdf generation if it hangs-execute for more than 10seconds
wshell.run "KillProcess.exe -p wkhtmltopdf -t 10000",0,FALSE
'Launch pdf generation with bwaitonreturn true
wshell.run wkhtmltopdf.exe http://www.mypagehanging.com c:\inetpub\wwwroot\myfile.pdf", 0, TRUE
'Stream the pdf ...
Code source for the KillProcess.exe
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using CommandLine; //http://commandline.codeplex.com
using CommandLine.Text; //http://commandline.codeplex.com
namespace KillProcess
{
class Program
{
static void Main(string[] args)
{
var options = new Options();
ICommandLineParser parser = new CommandLineParser();
if (parser.ParseArguments(args, options))
{
double maxWaitTime = options.time; //ms
string processName = options.process;
bool exit;
do
{
exit = true;
foreach (Process p in GetProcesses(processName))
{
exit = false;
try
{
if (p.StartTime.AddMilliseconds(maxWaitTime) < DateTime.Now)
{
p.Kill();
Console.WriteLine("Killed Process: {0} ID: {1} started at {2} after {3}ms of execution time", p.ProcessName, p.Id, p.StartTime, options.time);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Thread.Sleep(100);
} while (!exit);
return;
}
else
{
Console.WriteLine(options.GetUsage());
return;
}
}
static IEnumerable<Process> GetProcesses(string processName)
{
var processes = from p in Process.GetProcesses()
where p.ProcessName == processName
orderby p.ProcessName
select p;
return processes;
}
class Options : CommandLineOptionsBase
{
[Option("p", "process", Required = true, HelpText = "Name of the process-es to kill after some execution time (Warning ! This will kill all the processes that match the name !)")]
public string process { get; set; }
[Option("t", "time", Required = true, HelpText = "Maximum execution time allowed for the process to run. If the process has run for more than this amount of time it will be killed")]
public int time { get; set; }
[HelpOption]
public string GetUsage()
{
return HelpText.AutoBuild(this, (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current));
}
}
}
}
Related
I have a Console Application which is invoking SSIS Package.Below is the code which is working Fine.
public static void ExecuteSSIS_Staging()
{
DataAccessLayer objDAL = new DataAccessLayer();
LogManager_SSIS objlogM = new LogManager_SSIS();
String strDestinationFilePath = System.Configuration.ConfigurationManager.AppSettings.Get("FileDownloaded");
try
{
Package pkg;
Application app;
DTSExecResult pkgResults;
MyEventListener eventListener = new MyEventListener();
string staging_pkgLocation = System.Configuration.ConfigurationManager.AppSettings.Get("SSIS_Staging_Filepath").ToString();
app = new Application();
pkg = app.LoadPackage(staging_pkgLocation, eventListener);
pkgResults = pkg.Execute(null, null, eventListener, null, null);
if (pkgResults == Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success)
{
Console.WriteLine("Success");
}
else if (pkgResults == Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure)
{
string err = "";
foreach (Microsoft.SqlServer.Dts.Runtime.DtsError local_DtsError in pkg.Errors)
{
string error = local_DtsError.Description.ToString();
err = err + error;
}
throw new Exception("Error Occurred while executing the SSIS Staging package:" + err);
}
}
catch (Exception ex)
{
throw new Exception("SSIS Package Execution Failed:" + ex.Message.ToString());
}
}
Now I am in a position to Invoke this Package inside Foreach Loop.
static void Main(string[] args)
{
try
{
foreach (DateTime FileDate in SortedDates)
{
ExecuteSSIS_Staging(FileDate);
}
}
Catch(Exception ex)
{
}
}
I am getting Many Issues like
Could not load file or assembly 'Microsoft.SqlServer.ManagedDTS
and few other DLL reference error.
Can anyone suggest me, how can i invoke SSIS Package Inside Foreach loop. The main thing is, In my Local machine it is working obsolutely file. But When i deploy it in server, it is not.
The actuall issue is i have added
Microsoft.SQLServer.ManagedDTS.dll version 9.0
in one machine. When i tried to open it in other machine, some how DLL is refernced to
Microsoft.SQLServer.ManagedDTS.dll version 10.0 version.
I changed it again & executed. Now Working Fine.
I have a long running PostgreSQL function. For simplicity, something like this:
CREATE FUNCTION pg_function()
RETURNS void
AS
$$
BEGIN
PERFORM pg_notify('channel1', 'pg_function() started.');
PERFORM pg_sleep(5);------PERFORM task1();-----------------------------------------
PERFORM pg_notify('channel1', 'Task1 payload.');
PERFORM pg_sleep(5);------PERFORM task2();-----------------------------------------
PERFORM pg_notify('channel1', 'Task2 payload.');
PERFORM pg_sleep(5);------PERFORM task3();-----------------------------------------
PERFORM pg_notify('channel1', 'Task3 payload.');
PERFORM pg_notify('channel1', 'pg_function() completed.');
END;
$$
LANGUAGE "plpgsql";
On C#, I have:
public bool listening;
public void PgFunction()
{
this.listening = true;
ThreadStart listenerStart = delegate
{
using (NpgsqlConnection connection = new NpgsqlConnection(this.connectionString))
{
connection.Open();
connection.Notification += Listen;
using (NpgsqlCommand listenChannel1 = new NpgsqlCommand("LISTEN channel1;", connection))
{
listenChannel1.ExecuteNonQuery();
}
while (this.listening)
{
using (NpgsqlCommand pollingCommand = new NpgsqlCommand("SELECT 0;", connection))
{
pollingCommand.ExecuteNonQuery();
}
Thread.Sleep(5000);
}
}
};
Thread listenerThread = new Thread(listenerStart) { IsBackground = false };
listenerThread.Start();
ThreadStart pgFunctionThreadStart = () => ExecuteNonQuery(new NpgsqlCommand("SELECT pg_function();"));
pgFunctionThreadStart += () =>
{
Thread.Sleep(5000);
this.listening = false;
};
Thread pgFunctionThread = new Thread(pgFunctionThreadStart) { IsBackground = true };
pgFunctionThread.Start();
}
private void Listen(object sender, NpgsqlNotificationEventArgs e)
{
string payload = e.AdditionalInformation;
//SignalR stuff here
}
When I run the program debugging, this code works okay. But when it is tested on IIS server or browsed with Visual Studio 2013 integrated IIS, the application crashes. Since I have very little knowledge of tasks and threads in C#, I would like to know what I am doing wrong here? Please advise.
Edit
Upon debugging it again, I came with a NpgsqlException, which happens to happen once in a while:
Additional information: Cannot write to a BufferedStream while the read buffer is not empty if
the underlying stream is not seekable. Ensure that the stream underlying this BufferedStream
can seek or avoid interleaving read and write operations on this BufferedStream.
Good Evening all,
In a little of a pickle with a huge brain fart and could use a little help with something. So i wrote this C# console app that uses Selenium to open a web page, logs in, does some stuff, then submit a form and logs off the site. Now I have this in a for loop to do it 100 times. Now very rarely it may hiccup and throws an exception cause page didn't load fast enough or something. I thought it may be good to use a try/catch but once as the catch catches the exception, but I want it to redo that loop number that it is on and continue on. So example, say if i am on iteration 66 of 100 and it throws an exception cause page didn't load fast enough or there was an error on the page for that link, i need it to catch it, log it, then restart at number 66 again. Below is some of my original code and another section of what i have gotten it to.
using System;
using System.Collections.Generic;
using System.Text;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using System.Threading;
using System.IO;
namespace SeleniumTest
{
class Program
{
static void Main(string[] args)
{
for (Int64 i = 1; i < 100; i++)
{
DateTime time;
time = DateTime.Now;
StreamWriter tw = new StreamWriter(#"C:\folder\file.txt", true);
IWebDriver driver = new FirefoxDriver();
tw.WriteLine("Staring test," + time);
driver.Navigate().GoToUrl("http://site.com");
driver.FindElement(By.Name("username")).Clear();
driver.FindElement(By.Name("username")).SendKeys("username");
driver.FindElement(By.Name("password")).Clear();
driver.FindElement(By.Name("password")).SendKeys("password");
driver.FindElement(By.CssSelector("input.ui-standard-button")).Click();
driver.FindElement(By.LinkText("page")).Click();
driver.FindElement(By.LinkText("page")).Click();
Thread.Sleep(5000);
//Do awesome stuff
DateTime time1;
time1 = DateTime.Now;
driver.FindElement(By.CssSelector("div.Parameters")).Click();
driver.FindElement(By.Name("submit")).Click();
driver.FindElement(By.LinkText("Logoff")).Click();
driver.Quit();
tw.WriteLine("Stopping Test Successfully," + time1);
tw.Flush();
tw.Close();
Thread.Sleep(10000);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using System.Threading;
using System.IO;
namespace SeleniumTest
{
class Program
{
static void Main(string[] args)
{
try
{
for (Int64 i = 1; i < 100; i++)
{
DateTime time;
time = DateTime.Now;
StreamWriter tw = new StreamWriter(#"C:\folder\file.txt", true);
IWebDriver driver = new FirefoxDriver();
tw.WriteLine("Staring test," + time);
driver.Navigate().GoToUrl("http://site.com");
driver.FindElement(By.Name("username")).Clear();
driver.FindElement(By.Name("username")).SendKeys("username");
driver.FindElement(By.Name("password")).Clear();
driver.FindElement(By.Name("password")).SendKeys("password");
driver.FindElement(By.CssSelector("input.ui-standard-button")).Click();
driver.FindElement(By.LinkText("page")).Click();
driver.FindElement(By.LinkText("page")).Click();
Thread.Sleep(5000);
//Do awesome stuff
DateTime time1;
time1 = DateTime.Now;
driver.FindElement(By.CssSelector("div.Parameters")).Click();
driver.FindElement(By.Name("submit")).Click();
driver.FindElement(By.LinkText("Logoff")).Click();
driver.Quit();
tw.WriteLine("Stopping Test Successfully," + time1);
tw.Flush();
tw.Close();
Thread.Sleep(10000);
}
}
catch(Exception e)
{
StreamWriter tw = new StreamWriter(#"C:\folder\file.txt", true);
tw.WriteLine("Problem happened. Restarting test. Exception is :" + e);
//Line of code to restart test at number 66 which I don't know
}
}
}
}
Where //Line of code to restart test at number 66 which I don't know is where my knowledge ends and hopefully is where someone else is. Any guidance you can give would be great and appreciated.
Decrementing the counter when an exception is encountered should do it.
for (Int64 i = 1; i < 100; i++) {
try {
//main code here
} catch (Exception ex) {
//logging here
i--;
}
}
I would try to figure out why it's failing, but if that's not an option I would convert it to a while loop with a try catch
int i = 100;
while(i > 0)
{
try
{
//Do your logic here
i--
}
catch
{
//Log failure
}//Don't decrement in case of failure
}
for (Int64 i = 1; i < 100; ++i)
{
for (;;)
{
try
{
//code here
break;
}
catch (Exception exc)
{
//log error
}
}
}
I am writing a database application using Visual Studio 2012 with Entity Framework 5 and SQL Server 2008. I would like Entity Framework to impersonate a SQL Server user (i.e. user without a login). I have created a new constructor for the DB context MyDatabaseEntities which includes an argument for the name of the user to impersonate. Here is the code that I've written:
public partial class MyDatabaseEntities
{
private String _impersonateUser = null;
public MyDatabaseEntities(String impersonateUser)
: base("MyConnectionString")
{
_impersonateUser = impersonateUser;
this.Database.Connection.StateChange += Connection_StateChange;
}
void Connection_StateChange(object sender, StateChangeEventArgs e)
{
if (e.CurrentState == ConnectionState.Open && e.OriginalState != ConnectionState.Open)
{
using (var cmd = this.Database.Connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("user", _impersonateUser));
cmd.CommandText = "EXECUTE AS USER = #user";
cmd.ExecuteNonQuery();
}
}
}
I had to add the check...
if (e.CurrentState == ConnectionState.Open && e.OriginalState != ConnectionState.Open)
...because the method Connection_StateChange method seems to execute even when the state hasn't changed. Then problem is that when I run the code twice,
public void RunSimpleQuery()
{
using (MyDatabaseEntities context = new MyDatabaseEntities("UserName"))
{
var result = context.TableName.ToList();
}
}
...Entity Framework throws a SqlException:
A severe error occurred on the current command. The results, if
any, should be discarded.\r\nA severe error occurred on the current
command. The results, if any, should be discarded.
Any ideas?
Update 1
I in my code above, I changed...
cmd.CommandText = "EXECUTE AS USER = #user;";
...to...
cmd.CommandText = "REVERT; EXECUTE AS USER = #user;";
...and I still get the same SqlException error.
The problem is that EF closes connection when it doesn't need it and returns it back to the pool. So when it executes some SQL again it request new connection from the pool where your event may not be initialized. But again I believe that you should try to solve this with manually controlling connection lifetime to have both benefit of connection pooling and be able to meet your requirements.
I know is an old question, but maybe will be useful for someone.
I did in a different way, using your code...
Instead of
Connection_StateChanged event
I create two methods in the same class:
public void ChangeUser(String sUser)
{
if(Database.Connection.State != ConnectionState.Open)
Database.Connection.Open();
using (var cmd = Database.Connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("user", sUser));
cmd.CommandText = "EXECUTE AS USER = #user;";
cmd.ExecuteNonQuery();
}
}
public void Revert()
{
if (Database.Connection.State != ConnectionState.Open)
Database.Connection.Open();
using (var cmd = Database.Connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "REVERT;";
cmd.ExecuteNonQuery();
}
}
I use it before and after execute stored procedure,
using (var db = new MyDatabaseEntities())
{
db.ChangeUser(model.Username);
var result = db.Something();
db.Revert();
return result;
}
It works fine with SPs and it doesn't throw an exception even after many executions. If I could catch an event after command execute, maybe all be encapsulated on MyDatabaseEntities.
How to query Folder Size in remote computer through WMI and C#.
I need to find the each User's folder size in C:\Users in remote System through WMI.
I tried Win32_Directory , CMI_DataFile but not able to find the desired answer.
Please help!!
To get the size of a folder using the WMI, you must iterate over the files using the CIM_DataFile class and then get the size of each file from the FileSize property.
Try this sample (this code is not recursive, I leave such task for you).
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
// Directory is a type of file that logically groups data files 'contained' in it,
// and provides path information for the grouped files.
static void Main(string[] args)
{
try
{
string ComputerName = "localhost";
ManagementScope Scope;
if (!ComputerName.Equals("localhost", StringComparison.OrdinalIgnoreCase))
{
ConnectionOptions Conn = new ConnectionOptions();
Conn.Username = "";
Conn.Password = "";
Conn.Authority = "ntlmdomain:DOMAIN";
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), Conn);
}
else
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
string Drive= "c:";
//look how the \ char is escaped.
string Path="\\\\FolderName\\\\";
UInt64 FolderSize = 0;
ObjectQuery Query = new ObjectQuery(string.Format("SELECT * FROM CIM_DataFile Where Drive='{0}' AND Path='{1}' ", Drive, Path));
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
Console.WriteLine("{0}", (string)WmiObject["FileName"]);// String
FolderSize +=(UInt64)WmiObject["FileSize"];
}
Console.WriteLine("{0,-35} {1,-40}", "Folder Size", FolderSize.ToString("N"));
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}