WebBrowser.Print() wait until complete. .NET - c#

I am using a WebBrowser control in VB.NET and calling the Print() method. I am printing out using a PDF printer and when Print() is called it is not immediately kicked off (it waits until it has completed running code for the entire Sub or block.
I need to make sure the file I am printing too is complete and continue process with this file, therefore, I would like to print on demand and get some status of when the operation is complete. I have tried usign printDocument and process without luck.
Anyone have any ideas?

Check out the PrintTemplateTeardown event of the underlying unmanaged WebBrowser object. Sometimes that event gets fired multiple times but hopefully this will point you in the right direction. You need to add a reference to Microsoft Internet Controls.
Private Sub Print()
AddHandler DirectCast(WebBrowser1.ActiveXInstance, SHDocVw.WebBrowser).PrintTemplateTeardown, AddressOf PrintDone
WebBrowser1.Print()
End Sub
Private Sub PrintDone(ByVal obj As Object)
Trace.WriteLine("printed")
RemoveHandler DirectCast(WebBrowser1.ActiveXInstance, SHDocVw.WebBrowser).PrintTemplateTeardown, AddressOf PrintDone
End Sub

Your best bet is to get a handle on your 'printjobscollection' for your default printer and ensure that the jobcount = 0
like this in vb.net:
Dim intprint As Integer = Nothing
retry2:
intprint = GetPrintJobsCollection(printerinuse)
If Not intprint = 0 Then
System.Threading.Thread.Sleep(1000)
GoTo retry2
End If
'do what you want to do after print completes here

Related

Which event will be fire on exe if I close the main process using Task Manager?

My problem is what event will file after i kill the Main Process?
I have no problem when killing the Sub Process. When i kill the Sub frmAdmin Process,
For eg.
This event will be fire,
Private Sub frmAdmin_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If e.CloseReason = CloseReason.TaskManagerClosing Then
'Put you desired Code inside this!
'updateLogoutStatus(Euserid)
'updateLogoutStatus(DecryptAdminUser)
MsgBox("Why are you terminating me from : TaskManager?")
End If
End Sub
But when i kill the Main Process, Which contains the sub process,
Nothing happens. No event fire.
I already searched to internet but they only kill the sub process, not Main process.
Any ideas will be a big help.
The reason why i'm doing this because if the user Kill the main process using Task Manager, I want to trigger a Function.
Here is something I use, similar to your requirement.
Execute the update Query on Form Dispose Event
Private Sub frmAdmin_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
Try
'Update query and set flags to true / false'
Catch ex As Exception
'log exceptions (if any) to a local log file'
Finally
GC.Collect() 'Just release whatever memory your application occupied.'
End Try
End Sub

Visual Studio Automated UI Test Hangs

Firstly I am using VS2013 Winforms .net 4.0.
After excluding all other possibilities (from my set of possibilities) the culprit appears to be Me.close() in one specific form. After the me.close() method executes the coded-ui-test application seems to freeze and does not give any feedback about the buttons i am pressing or text i am entering. When I ask it to generate the code it goes as long as 1 hour before I decide to give up and kill the process. When I try the same test without the me.close it works as expected. Does anyone have any idea how to fix this bug in the automated ui testing? If not can you suggest any alternatives please?
Edit: This does not happen when I simply press the forms 'X' button in the top right. This is very strange.
Edit2: I have tried this in a fresh project. It is indeed me.close that causes the coded ui test application to 'freeze' such that I cannot generate the automated code and I will end up stuck at the 'please wait' loading bar.
Edit3: It appears to be specific to calling me.close in an infragistics click handler of a ultrabutton. Wow, here is example.
Designer
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class closemepls
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.UltraButton1 = New Infragistics.Win.Misc.UltraButton()
Me.SuspendLayout()
'
'UltraButton1
'
Me.UltraButton1.Location = New System.Drawing.Point(45, 47)
Me.UltraButton1.Name = "UltraButton1"
Me.UltraButton1.Size = New System.Drawing.Size(232, 157)
Me.UltraButton1.TabIndex = 0
Me.UltraButton1.Text = "UltraButton1"
'
'closemepls
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(284, 262)
Me.Controls.Add(Me.UltraButton1)
Me.Name = "closemepls"
Me.Text = "closemepls"
Me.ResumeLayout(False)
End Sub
Friend WithEvents UltraButton1 As Infragistics.Win.Misc.UltraButton
End Class
Code
Public Class closemepls
Private Sub UltraButton1_Click(sender As Object, e As EventArgs) Handles UltraButton1.Click
Me.Close()
End Sub
End Class
If I call closemepls.showdialog() and click the button the coded ui test application freezes! Infragistics FTW.
This is the result, it does not complete even after 1 hour.
I had problems like that in WPF before.
Here's how I found it: Comment everything out then find the code that causes the problem by adding blocks back one by one.
It's something that is binded (anything though, not data and more than likely a control) not being released.
I haven't tried mixing CodedUI and VB much, but I was hoping this question may help you:
Me.Close does not work
Alone, that doesn't mean much, right? But in conjunction with how CodedUI works it may provide a clue. Remember that when you're running a test you're technically initiating a UITesting.Playback, which is a process. You may want to add something to your TestCleanup method that makes sure all the processes are terminated, like so (Keep in mind that this is for a browser test):
/// <summary>
/// Closes the test browser and ends test playback
/// </summary>
[TestCleanup]//The decorator is what makes this a method a test cleanup
public void CleanTest()
{
if (Playback.IsInitialized) //This is the important part.
{
Playback.Cleanup();
}
if (browserWindow.Exists)
{
browserWindow.Close();
}
}
This is just a shot in the dark and I may even be misunderstanding what you need, really but I'm assuming that in both your real and example areas you're closing the entire application? This may be a question for Infragistics at the end of the day. Good luck!
This might be the same issue I've experienced when using MTM, on a few machines if they were running any form of capture for the resulting test. They where trying to save it to a illegal path(Found in Event Viewer). After performing a repair on VS thus MTM to was repaired and it worked for some machines. Others only seamed to be fixed when going to update 4.
But code wise I would suggest trying to click the close button on the form itself to see if you get a different behavior.
Dim closeButton = New WinButton(YourWindow);
closeButton.SearchProperties(UITestControl.PropertyNames.Name) = "Close";
Mouse.Click(closeButton);

Excel macro run from Interop (C#) application in Excel returns before it completes it's execution

My macro sub ('first-sub') ends by calling another sub ('second-sub') from Application.OnTime, with a wait time of 5 seconds. My C# application however gets back the control after the 'first-sub' execution is done. It doesn't wait for the 'second-sub' to be completed. Is there a way, my C# application can wait till both the macros complete their run?
C#:
xlApp.Run("first-sub");
Macros:
Sub first-sub
'Some code lines'
Application.OnTime(Now + "00:00:05"), "second-sub"
End Sub
Sub second-sub
'Some code lines'
End Sub
I tried using Thread.Sleep, it didn't work. Also, I tried creating a separate macro that runs calls first-sub and waits for 5 seconds. That didn't work either.
I am working with an add-in (bloomberg add-in) that calculates the result only after the 'first-sub' has ended. This add-in doesn't calculate results in the middle of the sub. So, once the control from the sub comes out, with-in about 5 seconds my results are populated. Then, I need 'second-sub' to execute. This is the reason, I have to use Application.OnTime and not Application.Wait.
So, the following codes didn't work
xlApp.Run("first-sub");
xlApp.OnTime((DateTime.Now + TimeSpan.FromSeconds(5)).ToString(), "second-sub");
It did run the second-sub, but bloomberg results were not populated.
This is one of many possible solutions:
Sub first-sub
'Some code lines'
Application.Wait "00:00:05"
second-sub
End Sub
This way, you wait 5 seconds, then execute second-sub synchronously, and first-sub ends AFTER the execution of second-sub.
Another solution is to execute the two subs SEPARATELY:
xlApp.Run("first-sub");
Application.Wait "00:00:05"
xlApp.Run("second-sub");

Working around InvokeRequired in a Windows Service

I'm trying to make a simple windows service.
All this service does is change the volume for one device when another device's volume is altered. It currently works as an application, and is only two Subs and a dll to function.
Basically an event handler is created on the Form Load:
AddHandler device.AudioEndpointVolume.OnVolumeNotification, AddressOf volume
Which calls the sub:
Private Sub volume(data As CoreAudioApi.AudioVolumeNotificationData)
If Me.InvokeRequired Then
Me.Invoke(New AudioEndpointVolumeNotificationDelegate(AddressOf volume), data)
Else
loopback.AudioEndpointVolume.MasterVolumeLevelScalar = data.MasterVolume
loopback.AudioEndpointVolume.Mute = data.Muted
End If
End Sub
Now in a windows service I can't use invoke, and when I remove it the error The function evaluation requires all threads to run is thrown.
What I believe is happening is that the control data and loopback (which are the controls of the audio Device accessed via the CoreAudioApi.dll) is not resolving without the invoke, but I don't know how to make them resolve properly.
Determine changes of master audio volume using NAudio.dll from: https://github.com/SjB/NAudio
Imports NAudio.CoreAudioApi
Public Class Form1
Private enumer As MMDeviceEnumerator = New MMDeviceEnumerator()
Private dev As MMDevice = enumer.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Control.CheckForIllegalCrossThreadCalls = False
AddHandler dev.AudioEndpointVolume.OnVolumeNotification, AddressOf AudioEndpointVolume_OnVolumeNotification
End Sub
Private Sub AudioEndpointVolume_OnVolumeNotification(ByVal data As AudioVolumeNotificationData)
' This shows data.MasterVolume, you can do whatever you want here
Me.Text = CInt(data.MasterVolume.ToString() * 100) & " Mute=" & data.Muted
End Sub
End Class
If I remove the if around the invoke statement so it just has the line:
Me.Invoke(New AudioEndpointVolumeNotificationDelegate(AddressOf volume), data)
followed by the other two lines it throws the error:
"'Invoke' is not a member of 'VolumeSet.VolumeSet'"
So I don't think invoke can be used inside a windows service at all.
But thanks for the idea!

Naudio,how to tell playback is completed

I am using the NAudio library to write a simple WinForms audio recorder/player. My problem is how can I tell that playback is completed? I need to close the wave stream after that.
I knew there is a PlaybackStopped event listed below:
wfr = new NAudio.Wave.WaveFileReader(this.outputFilename);
audioOutput = new DirectSoundOut();
WaveChannel32 wc = new NAudio.Wave.WaveChannel32(wfr);
audioOutput.Init(wc);
audioOutput.PlaybackStopped += new EventHandler<StoppedEventArgs>(audioOutput_PlaybackStopped);
audioOutput.Play();
But this PlaybackStopped event seems can only be triggered by calling audioOutput.stop(), does anyone know how to determine if playback is completed?
I create an open source project for this question, you can find it here: https://code.google.com/p/stack-overflow-questions/
The PlaybackStopped event is raised when you either manually stop playing, or the Read method of the IWaveProvider you are using returns 0. The issue here is that WaveChannel32 does not stop returning data when it's source stream ends, so playback never ends. The PadWithZeroes property should be set to false to fix this.
As #Mark Heath described in addition I want to add coding example of Naudio wich will play a mp3 file in Debug/Sound Folder folder and wait until it isn't finished.
Playback is completed can be checked by waveOut.PlaybackState == PlaybackState.Stopped
play_string = #"SOUND/space.mp3";
var reader = new Mp3FileReader(play_string);
var waveOut = new WaveOut(); // or WaveOutEvent()
waveOut.Init(reader);
waveOut.Play();
while (waveOut.PlaybackState != PlaybackState.Stopped) ; // Wait untill the playing isn't finished.
Here is my code in Visual Basic that works well for me to determine when the playback is done. It uses a loop to keep testing WaveOut.PlaybackState
In the loop, you will notice that a short thread sleep of 50 is used to stop the cpu running away. I picked 50 from experience, you may find another value works better for you through trial and error.
And finally, the loop allows windows.forms events so the user can click the Stop button, with the statement:
System.Windows.Forms.Application.DoEvents
In the code I have supplied below, you can see events being raised - for example:
RaiseEvent Enable_PlayButton
I have defined events to allow a parent class to enable the Play, Stop, and Record buttons:
Public Event Enable_PlayButton(Enabled As Boolean)
Public Event Enable_StopButton(Enabled As Boolean)
Public Event Enable_RecordButton(Enabled As Boolean)
Public Event Enable_SaveButton(Enabled As Boolean)
Public Event Enable_RevertButton(Enabled As Boolean)
Public Event RecordingChanged(NewRecording As Byte())
In a parent class, I use AddHandler to wire these up to method in the parent class. In the following example, I have methods such as in the first case, "EnablePlay". Likewise for the other events.
AddHandler mMicrophoneRecorder.Enable_PlayButton, AddressOf EnablePlay
AddHandler mMicrophoneRecorder.Enable_StopButton, AddressOf EnableStop
AddHandler mMicrophoneRecorder.Enable_RecordButton, AddressOf EnableRecord
AddHandler mMicrophoneRecorder.Enable_RevertButton, AddressOf EnableRevert
AddHandler mMicrophoneRecorder.RecordingChanged, AddressOf MicRecorder_RecordingChanged
In this method, there are 3 fields that are defined elsewhere:
mWaveOut_via_SoundCard - a class-level (field) of WaveOut.
mAudioFile - instantiated here but held at the class level (a field).
mWavRecordingPath - the path to the audio (wav) file being played.
These 3 fields could probably be passed in to this method as parameters if you prefer to inject them. I used fields, because that's just the way my code for this evolved.
Here then, is the code:
Public Sub A_PlayClicked()
If mWaveOut_via_SoundCard Is Nothing Then
mWaveOut_via_SoundCard = New WaveOutEvent()
End If
If mAudioFile Is Nothing AndAlso mWavRecordingPath <> "" Then
mAudioFile = New AudioFileReader(mWavRecordingPath)
mWaveOut_via_SoundCard.Init(mAudioFile)
End If
RaiseEvent Enable_StopButton(True)
mWaveOut_via_SoundCard.Play()
Dim PlayDone As Boolean = False
Dim PState As PlaybackState
Do
'if stopped or finished, mSoundCard will be nothing,
'so we test that by trying to get PlayBackState
' from the WaveOut object (mSoundCard)
If mWaveOut_via_SoundCard Is Nothing Then
PlayDone = True
Else
Try
PState = mWaveOut_via_SoundCard.PlaybackState
Catch ex As Exception
'mSoundCard is probably nothing - but
'no matter what the problem, for now we will say
'that PlayDone is true.
PlayDone = True
End Try
End If
'Okay we got the PlayState, so evaluate and
'decide whether to continue here:
If Not PlayDone Then
If PState <> PlaybackState.Stopped Then
'let the system do stuff (e.g. user might click Stop button)
System.Windows.Forms.Application.DoEvents()
'don't use all the cpu:
Threading.Thread.Sleep(50)
Else
'well it's stopped so we're done:
PlayDone = True
End If
End If
Loop Until PlayDone = True
'here we could raiseevent stopped as well
RaiseEvent Enable_PlayButton(mCanPlay)
RaiseEvent Enable_RecordButton(True)
End Sub

Categories