Gabriel Guimarães
Gabriel Guimarães

Reputation: 2744

WATIN on SSIS script component - Single-Threaded Apartment

Hi I need to download a file from a site with forms authentication and further processing the text file with Integration Services.

For the file download I choose to use WATIN, So I imported the Watin library and scripted the browser steps. However when I try to run the code I get an Exception with this Message.

The CurrentThread needs to have it's ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer.

all this using the (with the method attribute)

If I try to use this line of code to set it to STA

System.Threading.Thread.CurrentThread.SetApartmentState(Threading.ApartmentState.STA)

I get this exception

Error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Failed to set the specified COM apartment state. at System.Threading.Thread.SetApartmentState(ApartmentState state)

How do I change the SSIS script task to use this Single-Threaded apartment?

Upvotes: 2

Views: 1228

Answers (2)

Naigel
Naigel

Reputation: 9644

I found your solution very useful for my case that is similar, I add the C# code I used in case someone needs it

public void Main() {
    Thread thread = new Thread(new ParameterizedThreadStart(DoMethod));
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join(); // wait for thread to end

    Dts.TaskResult = (int)ScriptResults.Success;
}

public void DoMethod(object sender) {
    System.Windows.Forms.Application.Run(new BrowserWindow("http://x.xxx"));
}

And here is the BrowserWindow class

class BrowserWindow : Form
{
    private string url;

    public BrowserWindow(string url) {
        this.url = url;
        ShowInTaskbar = false;
        WindowState = FormWindowState.Minimized;
        Load += new EventHandler(Window_Load);
    }

    void Window_Load(object sender, EventArgs e) {
        WebBrowser wb = new WebBrowser();
        wb.AllowNavigation = true;
        wb.DocumentCompleted += wb_DocumentCompleted;
        wb.Navigate(this.url);
    }

    void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        WebBrowser web = sender as WebBrowser;
        // here goes the business logic
    }
}

Upvotes: 1

Gabriel Guimarães
Gabriel Guimarães

Reputation: 2744

I've solved this by creating another Thread with the STA ApartmentState.

The code was like this:

Private threadDelegate As ParameterizedThreadStart
Private filesdir As String

<STAThread()> _
Public Sub Main()
    Try
        threadDelegate = New ParameterizedThreadStart(AddressOf Me.DoSomething)
        StartBrowserRoutine(threadDelegate)
        Dts.TaskResult = ScriptResults.Success
    Catch
        Dts.TaskResult = ScriptResults.Failure
    End Try
End Sub

Private Sub StartBrowserRoutine(ByVal threadRoutine As ParameterizedThreadStart)
    Dim dialogThread As Thread = New Thread(threadRoutine)
    dialogThread.TrySetApartmentState(ApartmentState.STA)
    dialogThread.Start(Nothing)
    dialogThread.Join(System.Threading.Timeout.Infinite)
End Sub

Private Sub DoSomething()
    'Do Something
End Sub

Hope this helps someone with the same problem.

Upvotes: 2

Related Questions