Hi,
first, please excuse my untrained english. In addition i am not experierenced posting in forums. Hopefully i post my problem on the right place.
I will develop a Custom Task Gui with the 3 button:
and tried to use it in the overrided Show function in this was:
(Exerpt from VB-Code:)
Private show_Counter As Integer = 0
Public Overrides Function Show(ByVal Owner As IWin32Window) As ShowResult
Dim dlg As Class1Form = New Class1Form()
show_Counter = show_Counter + 1
_logger.Debug(String.Format("{0} Button {1} Show Counter {2}", System.Reflection.MethodBase.GetCurrentMethod().Name, dlg.ShowDialog(Owner), show_Counter.ToString))
If (DialogResult.OK = dlg.ShowDialog(Owner)) Then
_logger.Debug(String.Format("{0} RunNow", System.Reflection.MethodBase.GetCurrentMethod().Name))
Return ShowResult.RunNow
ElseIf (DialogResult.Yes = dlg.ShowDialog(Owner)) Then
_logger.Debug(String.Format("{0} RunLater", System.Reflection.MethodBase.GetCurrentMethod().Name))
Return ShowResult.RunLater
Else
_logger.Debug(String.Format("{0} Canceld", System.Reflection.MethodBase.GetCurrentMethod().Name))
Return ShowResult.Canceled
End If
End Function
Basicly the functionality works (RunLater, RunNow, Canceled) but i have to hit the buttons repeatedly - up to 3-5 times.
Logging shows that the Show function runs just once (only one occurence from result "_logger.Debug(String.Format("{0} Button {1} Show Counter {2}"....") :
(Exerpt from the EG-Log):
2018-02-20 09:47:54,508 [Main] DEBUG ClassLibrary1.Class1 [(null)] - Show Button Yes Show Counter 1
2018-02-20 09:47:56,605 [Main] DEBUG ClassLibrary1.Class1 [(null)] - Show RunLater
I hope that ich posted my problem not to clouded and that someone can help me. Thanks a lot.
Regrads,
Michael
Hi @mk_methrada,
There are a few things going on here. With the current logic, ShowDialog is called multiple times as the code executes. That accounts for the multiple clicks that you're perceiving -- you're actually dismissing up to 4 different instances of the dialog window.
Each time you see dlg.ShowDialog() in this code, the window could be created/displayed. That includes the Debug action you send to the logger! Exactly how many times you see the window will depend on the logic of the If...Then...Else flow.
_logger.Debug(String.Format("[{0}] dlg.ShowDialog(Owner)={1} show_Counter={2}", System.Reflection.MethodBase.GetCurrentMethod().Name, dlg.ShowDialog(Owner), show_Counter.ToString)) ' If Button Start is hit .... If (DialogResult.OK = dlg.ShowDialog(Owner)) Then _logger.Debug(String.Format("[{0}] RunNow", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunNow ElseIf (DialogResult.Yes = dlg.ShowDialog(Owner)) Then ' if Button Save is hit ..... Settings = dlg.Settings _logger.Debug(String.Format("[{0}] RunLater", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunLater End If
Here is a refactored version of the code that calls ShowDialog just once. I left your other debugging statements intact.
Public Overrides Function Show(ByVal Owner As IWin32Window) As ShowResult Dim dlg As RunLaterForm = New RunLaterForm(Settings) show_Counter = show_Counter + 1 _logger.Debug(String.Format("[{0}] show_Counter={1}", System.Reflection.MethodBase.GetCurrentMethod().Name, show_Counter.ToString)) Select Case dlg.ShowDialog(Owner) Case DialogResult.OK _logger.Debug(String.Format("[{0}] RunNow", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunNow Case DialogResult.Yes ' if Button Save is hit ..... Settings = dlg.Settings _logger.Debug(String.Format("[{0}] RunLater", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunLater Case DialogResult.Cancel Case Else ' all other like canceld ... _logger.Debug(String.Format("[{0}] Canceld", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.Canceled End Select Return ShowResult.Canceled End Function
Also: your project has references to many SAS Enterprise Guide DLLs, and you need only those that have the documented APIs:
I would remove the other references, as this will make your project more portable/usable for future versions of EG.
As you continue this pursuit, I recommend that you learn how to use the Visual Studio debugger. It's an excellent tool, and setting proper breakpoints would have revealed exactly what's going on here. You can use the Debug->Attach to Process feature to join the debugger to the running task "just in time" -- as long as the deployed custom task DLL and PDB (symbols) file are in the same folder. If you're working from my book about custom tasks, I have an entire chapter devoted to this.
Update: Just remembered I also have a blog post about this debugging trick.
In addition to returning one of the ShowResult values, your VB form also needs to have logic that closes the window when one of those buttons is clicked. For OK-style buttons and Cancel-style buttons, you can associate the AcceptButton and CancelButton properties with those button IDs as well as the DialogResult value (OK and Cancel, respectively), and that will wired up the Close action. For "RunLater", you probably need to add logic that calls Close() on the displayed form so that the window is dismissed.
Dear Chris,
thanks for your quick reply.
For the buttons "Start" (ShowResult.RunNow) and "Cancel" ((ShowResult.Canceld) the property DialogResult is set to "OK" and "CANCEL". On the form the properties AcceptButton is assigned to Button "Start" and CancelButton is assigned to Button "Cancel".
For the Button "Save" (ShowResult.RunLater) i added the function "btn_Save_Click" and perform "me.close()".
The behaviour did not change. When i hit one of the buttons, it needs 2 hits on "Start" and 3 hits on the other buttons before the form is closed.
Here an excerpt from the log when i test the "Save" button (please find the whole log in the attachement):
2018-02-21 09:03:32,778 [Main] DEBUG RunLater.RunLater [(null)] - [.ctor] calls InitializeComponent()
2018-02-21 09:03:32,779 [Main] DEBUG RunLater.RunLater [(null)] - [InitializeComponent]
2018-02-21 09:03:32,779 [Main] INFO SAS.Shared.AddIns.Management.AddInProxy [(null)] - Creating AddInProxy for RunLater.RunLater, C:\Users\micha_2\AppData\Roaming\SAS\EnterpriseGuide\7.1\Custom\RunLater.dll
2018-02-21 09:03:32,806 [Main] DEBUG RunLater.RunLaterForm [(null)] - [.ctor] calls InitializeComponent() and get settings ...
2018-02-21 09:03:40,090 [Main] DEBUG RunLater.RunLaterForm [(null)] - [btn_Save_Click] Hits: 1
2018-02-21 09:03:40,091 [Main] DEBUG RunLater.RunLaterForm [(null)] - [OnClosed] DialogResult=Yes
2018-02-21 09:03:40,145 [Main] DEBUG RunLater.RunLater [(null)] - [Show] dlg.ShowDialog(Owner)=Yes show_Counter=1
2018-02-21 09:03:50,411 [Main] DEBUG RunLater.RunLaterForm [(null)] - [btn_Save_Click] Hits: 2
2018-02-21 09:03:50,411 [Main] DEBUG RunLater.RunLaterForm [(null)] - [OnClosed] DialogResult=Yes
2018-02-21 09:04:01,636 [Main] DEBUG RunLater.RunLaterForm [(null)] - [btn_Save_Click] Hits: 3
2018-02-21 09:04:01,636 [Main] DEBUG RunLater.RunLaterForm [(null)] - [OnClosed] DialogResult=Yes
2018-02-21 09:04:01,696 [Main] DEBUG RunLater.RunLater [(null)] - [Show] RunLater
2018-02-21 09:04:01,702 [Main] DEBUG RunLater.RunLater [(null)] - [GetXmlState]
2018-02-21 09:04:01,702 [Main] DEBUG RunLater.RunLaterSettings [(null)] - [toXML] doc.OuterXml=<Class1 Text="test" />
2018-02-21 09:05:20,100 [Main] DEBUG SAS.EG.ProjectElements.GitRepository [(null)] - Disposing
2018-02-21 09:05:20,100 [Main] DEBUG SAS.EG.ProjectElements.GitRepository [(null)] - Attempting to delete C:\Users\micha_2\AppData\Local\Temp\SEG13764\isfFXPqAuqbiqVNH
[OnClosed] and [Show] are the overridden funktion.
Do you habe any more ideas, what i have done wrong? In addition i have appended the RunLater Project (Visual Studio 2017) too and woud like to ask you whether Is it possible, that you take a brief look at the code?
Kind regrads
Michael
Sorry, the complete log has got lost in the previous post. Here it is .....
Hi @mk_methrada,
There are a few things going on here. With the current logic, ShowDialog is called multiple times as the code executes. That accounts for the multiple clicks that you're perceiving -- you're actually dismissing up to 4 different instances of the dialog window.
Each time you see dlg.ShowDialog() in this code, the window could be created/displayed. That includes the Debug action you send to the logger! Exactly how many times you see the window will depend on the logic of the If...Then...Else flow.
_logger.Debug(String.Format("[{0}] dlg.ShowDialog(Owner)={1} show_Counter={2}", System.Reflection.MethodBase.GetCurrentMethod().Name, dlg.ShowDialog(Owner), show_Counter.ToString)) ' If Button Start is hit .... If (DialogResult.OK = dlg.ShowDialog(Owner)) Then _logger.Debug(String.Format("[{0}] RunNow", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunNow ElseIf (DialogResult.Yes = dlg.ShowDialog(Owner)) Then ' if Button Save is hit ..... Settings = dlg.Settings _logger.Debug(String.Format("[{0}] RunLater", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunLater End If
Here is a refactored version of the code that calls ShowDialog just once. I left your other debugging statements intact.
Public Overrides Function Show(ByVal Owner As IWin32Window) As ShowResult Dim dlg As RunLaterForm = New RunLaterForm(Settings) show_Counter = show_Counter + 1 _logger.Debug(String.Format("[{0}] show_Counter={1}", System.Reflection.MethodBase.GetCurrentMethod().Name, show_Counter.ToString)) Select Case dlg.ShowDialog(Owner) Case DialogResult.OK _logger.Debug(String.Format("[{0}] RunNow", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunNow Case DialogResult.Yes ' if Button Save is hit ..... Settings = dlg.Settings _logger.Debug(String.Format("[{0}] RunLater", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.RunLater Case DialogResult.Cancel Case Else ' all other like canceld ... _logger.Debug(String.Format("[{0}] Canceld", System.Reflection.MethodBase.GetCurrentMethod().Name)) Return ShowResult.Canceled End Select Return ShowResult.Canceled End Function
Also: your project has references to many SAS Enterprise Guide DLLs, and you need only those that have the documented APIs:
I would remove the other references, as this will make your project more portable/usable for future versions of EG.
As you continue this pursuit, I recommend that you learn how to use the Visual Studio debugger. It's an excellent tool, and setting proper breakpoints would have revealed exactly what's going on here. You can use the Debug->Attach to Process feature to join the debugger to the running task "just in time" -- as long as the deployed custom task DLL and PDB (symbols) file are in the same folder. If you're working from my book about custom tasks, I have an entire chapter devoted to this.
Update: Just remembered I also have a blog post about this debugging trick.
Hi Chris,
oh, how embarrassing A few weeks ago i bought your book and have also read the section about debugging, but not with the concentration you mentioned it. My fault, pardon me. And yes, i have to go deeper in Vb .Net processes ......
Many, many thanks for your help, time and tipps!
Best regards
Michael
Thanks for buying the book -- and good luck with your custom tasks. Build something amazing!
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.