.NET Interop Passing VB6 Form byRef - c#

I am trying to develop a .NET class that updates a VB6 Form and its controls with various new captions (It is in an assembly that is COM visible).
I pass a VB6 form ByRef as an object to the .NET class and then update the caption etc on the form as follows:
Public Sub AddFormRefLegacy(ByRef objForm As Object)
Try
objForm.Caption = "some new caption"
For Each ctl As Object In objForm.Controls
Select Case TypeName(ctl)
Case "Label"
ctl.caption = "some new caption"
Case "Frame"
ctl.caption = "some new caption"
Case "CommandButton", "PushButton"
ctl.caption = "some new caption"
'etc etc
This works about 85% of the time but occasioanlly I get a run time error 80131500 no such interface (E_NOINTERFACE)
I'm not sure exactly where this is throwing the error but can anyone see anything obviously wrong with this?
EDIT
The problem seems to be occurring on this section:
Case "ITabStrip" 'MS Common Controls 6
For i = 0 To ctl.Tabs.Count - 1 ' this sometimes throws the error!
ctl.Tabs(i + 1).Caption = FindValue(objForm.Name, ctl.Name, i, ctl.Tabs(i + 1).Caption)
Next

One possible problem might be that VB6 labels aren't windowed controls but are drawn on the form's window. Another possible problem is if you're using certain 3rd party controls it's likely that they're using owner draw techniques that might do unexpected things.
I'd suggest trying to narrow it down by control and see if any of them have the problem.

Related

Show Access Report in dialog

I want to show a Access Report without showing the MainForm from Access. I want to show it in a Dialog or something like that. I can show a report but with opening the Main Window of Access:
_access.DoCmd.OpenReport(
"myReport", //ReportName
AcView.acViewReport, //View
System.Reflection.Missing.Value,
"my Where Condition"
);
But this opens Access all the time. I only want to see my Report in a Dialog. Even when I set the AcWindowMode.acDialog property it opens Access behind it.
I also know that I can save it as PDF and open this. But this is not possible in my case.
Is there a way to show a Access Report in a Dialog without showing (or hiding) the Access Main Window behind it?
You can do it this way:
First, in the access application, set the interface to tabbed. and un-check show tabs.
Now write a code stub in a standard code module in Access.
Say like this:
Sub RunMyReport(s As String)
DoCmd.ShowToolbar "Ribbon", acToolbarNo
' now launch report
DoCmd.OpenReport "qryHotels", acViewReport
End Sub
Now, your .net code will look like this
(I not even bothering with interop - it don't help much).
You have this .net code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim objAccess As Object = CreateObject("Access.Application")
objAccess.OpenCurrentDatabase("C:\test\test44.accdb")
objAccess.Run("RunMyReport", "qryHotels")
objAccess.Visible = True
End Sub
And the results will now look like this:
note the vb form that launched the form.
Note the Access report,
it shows no ribbon or background interface.
And note that we get to pass the report name to the given routine.
Now you likely could move the VBA code of this:
DoCmd.ShowToolbar "Ribbon", acToolbarNo
' now launch report
DoCmd.OpenReport "qryHotels", acViewReport
To the .net side, and not even have to call a VBA routine.
Dim objAccess As Object = CreateObject("Access.Application")
objAccess.OpenCurrentDatabase("C:\test\test44.accdb")
objAccess.DoCmd.ShowToolbar("Ribbon", 2) ' acToolbarNo = 2
objAccess.DoCmd.OpenReport("qryHotels", 5) ' acViewReport = 5
objAccess.Visible = True
So, in fact we don't need the VBA helper function, and we can open any report. The command to hide the ribbon works, and the other settings (hide nav pane, and tabbed interface is to be set in the access application).
So above should work. Given it only a few lines of vb.net code, then as c#, it should be easy to convert. Eg this should work:
{
var objAccess = Interaction.CreateObject("Access.Application");
objAccess.OpenCurrentDatabase(#"C:\test\test44.accdb");
objAccess.DoCmd.ShowToolbar("Ribbon", 2); // acToolbarNo = 2
objAccess.DoCmd.OpenReport("qryHotels", 5); // acViewReport = 5
objAccess.Visible = true;
}
You can consider the inter-op assemblies, as that can help in intel-sense, but above is written without any references to office or use of the inter-op assemblies.

Revit API - Exception thrown: 'Autodesk.Revit.Exceptions.InternalException' in RevitAPI.dll - When trying to run button twice

Objective
Hi All, I'm working on making a button in Revit that is meant to add a single viewport to a new sheet and then change the viewport to show a viewTitle instead of being empty or just a line
Error
When I run the button for the first time, everything works except the view title is not set to the loaded family although the view title "line" is showing. My error occurs when I run the button the second time.
This is the error I get when I try to run the button a second time:
Exception thrown: 'Autodesk.Revit.Exceptions.InternalException' in RevitAPI.dll
A managed exception was thrown by Revit or by one of its external applications.
The error occurs at this line :
Viewport newViewPort = Viewport.Create(doc, viewSheet.Id, duplicatedPlan2Copy, new XYZ(location.U, location.V, 0));
Exploration
From what I've researched, the button is trying to access an element that is already being accessed but if I'm changing the scale, I should be able to change the ViewTitle. See references at the bottom of this question
here is some of my code which is in the transaction
FamilySymbol firstSheet = colTitleBlocks.FirstElement() as FamilySymbol;
ViewSheet viewSheet = ViewSheet.Create(doc, firstSheet.Id);
UV location = new UV((viewSheet.Outline.Max.U - viewSheet.Outline.Min.U) / 2,
(viewSheet.Outline.Max.V - viewSheet.Outline.Min.V) / 2);
ElementId duplicatedPlan2Copy = duplicatedPlan.Duplicate(ViewDuplicateOption.WithDetailing);
Viewport newViewPort = Viewport.Create(doc, viewSheet.Id, duplicatedPlan2Copy, new XYZ(location.U, location.V, 0));
Findings
I've found that if I remove this line from my code:
bool elementType = doc.GetElement(newViewPort.GetTypeId()).get_Parameter(BuiltInParameter.VIEWPORT_ATTR_LABEL_TAG).Set(viewTitleIdCommand);
It works and is able to create new sheets and place viewports with the view title line only repeatedly.
Any and all help is appreciated.
This link here shows how having 2 separate transaction commits solved the problem however I tried it and that didn't work. this one shows something similar
Here is a reference to my other related question regarding the button
I suggest that you explore and test your intended functionality manually through the user interface first. Once that is stable and optimised and works as expected, you can move over to automating the same steps programmatically through the Revit API. That will probably help you understand what the problem is in a much more efficient manner than struggling with the API, which just replicates the UI functionality.
I've figured it out. I was initially trying to using the TitleView's elementId loaded in from my LoadFamily class that I had instead of finding the elementId through a Filtered Element Collector.
I'm not sure why that was throwing me an error but it was.

Universe 9+ system, UniObjects (not for .NET) - How to convert examples from VB 6 to C#

I am working with a multi-value database that is currently using IBM U2 (now Rocket Software)'s UniObjects software to connect to a Universe 9.+ system. This is not UniObjects for .NET as put out by Rocket Software for Universe 10+ and 11+ systems. The only examples I have to use to try to connect to the Universe 9+ system are using Visual Basic 6.0 and I need to use C#. Can anyone show me HOW to connect to a Universe 9+ system in C#? Basically, I'm trying to translate what I would use in VB 6 over to C# in order to connect to that system. Thanks for any and all help you can provide. Some of the examples in the documentation are as follows:
Sub SampleFile ()
' SampleFile
'
' This routine creates a new session and opens the chosen
account's VOC
' file. The user is asked for a record id from VOC (e.g.
RELLEVEL), which
' is read and displayed in a message box. Finally the session
is closed.
Dim objSession As object ' The Session to the database
Dim objFile As object ' The file to open (VOC)
Const UVE_NOERROR = 0 ' From UVOAIF.TXT - no error
' The registered name of a database Session - Version 1
Const UV_SESSION_OBJECT = "UniObjects.unioaifctrl"
'
' Create a Session object to work with
' - This is a contrived sample, in a full application the
session object
' - would typically be a Global variable that is set once
maybe in
' - response to a menu selection (e.g. Connect) on the main
form.
'
Set objSession = CreateObject(UV_SESSION_OBJECT)
If objSession Is Nothing Then
' NB. Errors will be reported by VB
Exit Sub ' End the program
End If
objSession.UserName = Input.Box ("User Name:","Login")
objSession.Password = Input.Box ("Password:","Password")
'
' Establish a connection to the database server. By default it
displays
' a dialog box to request the HostName and AccountPath property
values.
'
objSession.Connect
If objSession.IsActive Then
'
' Open the VOC file
'
Set objFile = objSession.OpenFile("VOC")
If objFile Is Nothing Then
MsgBox "Unable to open VOC file (" & objSession.Error &
")"
Exit Sub ' End the program
End If
'
' Read user entered record from the VOC e.g. RELLEVEL
'
objFile.RecordId = InputBox("Enter Record Id:", "Record Id")
objFile.Read
File Object: Example 3-85
/productinfo/alldoc/UNIVERSE10/uv
objs/Ch3
If objFile.Error = UVE_NOERROR Then
' Display the record in a message box and close file
MsgBox objFile.Record
objFile.CloseFile ' Close the file - Good practice
Else
MsgBox "Unable to read (" & objFile.RecordId & ") record
from
å VOC " & objFile.Error
End If
'
' Close the session
'
objSession.Disconnect
Else
'
' Check for Session errors - display message box with error
code
' No error means the user cancelled the connection dialog
box
'
If objSession.Error <> UVE_NOERROR Then
MsgBox "Unable to open connection:- " & objSession.Error
End If
End If
End Sub
(I can program very well with C#. What I need is an example or two on how to connect to Universe 9+ and how to instantiate what "UniObjects" objects I need in C#. I know for instance that I need to create a session object, but VB 6 code won't tell me how to do that in C# ...)
UniVerse 9.6 came out in 2001, if the Readme file I just found is to be believed. That means that what you are using there predates the .Net Framework 1.0 release and the birth of commercial C#.
You might be able to use the Ardent ODBC (or some other) driver (if you can find it) but your success with that is going to depend heavily on your underlying data structure. In my admittedly somewhat limited exposure to old UV systems, they generally don't conform to ODBC standards in any kind of easy to deal with way.
You could do as the commenters suggest and write a database handler in VB6, but bear in mind that UniVerse data does not always return pretty columnular data like most people are used to. Make sure that you understand how Universe works before you undertake this endeavour as it will likely be a long and somewhat painful learning experience otherwise.
I think honestly you need to step back an evaluate the need. If it is a continuing integration with an old system, you are probably stuck with what you have.
If you are just trying to get the data off, I would work it from the Universe angle. BASIC is much easier to grok than VB6 and you can dump to the filesystem and load it elsewhere.
Good luck.
Here are some steps to create a new C# program to work with Rocket U2 UniObjects Object.
// For the C# program, it need to add the “UniObjects Control 3.0” type library to the project first.
//Create new UniObjects Object .
UnioaifCtrlClass uniobj = null;
// Set the Object properties.
uniobj.HostName = “localhost”;
uniobj.AccountPath = “XDEMO”;
uniobj.UserName = “user”;
uniobj.Password = “password”;
//Set UniVerse or UniData database type
UNIOBJECTSLib.enumDataBaseType dbtype;
// UniVerse
dbtype = (UNIOBJECTSLib.enumDataBaseType )1;
// UniData
//dbtype = (UNIOBJECTSLib.enumDataBaseType )2;
uniobj.set_DataBaseType(dbtype);
// Set TCP connection type
// Network TCP
UNIOBJECTSLib.enumTransport transportx;
transportx = (UNIOBJECTSLib.enumTransport)1;
uniobj.set_Transport(transportx);
// Connect to database
bool return_code = uniobj.Connect();
// Check the return_code
// Test UniObjects Command Object
UniCommand uocommand= (UniCommand)uniobj.Command;
uocommand.Text = “LIST VOC”;
uocommand.Exec();
// Show result:
MessageBox.Show(uocommand.Response.ToString());
// Close the session
uniobj.Disconnect();
There is no tool to convert a VB6 program to another new C# program automatically. You must convert the VB6 code to C# code by code. The UniObjects COM object has been phased out for many years. The driver is only 32-bit. New U2 Toolkit driver has provided more features than UniObjects (UO) and UniObjects for .NET (UO.NET). New driver is 32-bit and 64-bit support. It also meets with a lot of security compliance requests. I suggest to use new Rocket U2 Toolkit driver with same conversion effort.
Here is the part of sample codes.
- For the C# program, it need to add the “U2.Data.Client” reference to the project first.
- Create new U2 Toolkit Object .
using U2.Data.Client;
using U2.Data.Client.UO;
U2Connection u2connect = new U2Connection();
UniSession u2session;
UniCommand u2cmd;
- Set the Object properties and connection.
Connection_string="server=localhost;Database=XDEMO;UserID=user;Password=pass;Pooling=False;AccessMode=Native;ServerType=UniVerse;RpcServviceType=uvcs";
u2connect.ConnectionString = Connection_string;
u2connect.Open();
u2session = u2connect.UniSession;
- Test UniObjects Command Object
u2cmd = u2session.CreateUniCommand();
u2cmd.Command = "LIST VOC";
u2cmd.Execute();
// Show result:
MessageBox.Show(u2cmd.Response.ToString();
- Close the session
u2connect.Close();

GTK# window not rendered completely

Right now, I am trying to develop a program using Mono and GTK# on a Debian (Raspbian) system.
The issue I'm facing is, that, completely randomly, the GUI (generated by the Stetic designer or its dynamic elements) isn't completely drawn, missing either a few characters from a Label-element or whole widgets, mostly those that were dynamically created. This is how it looks on a dialog window: http://imgur.com/oEZRg7c (text is cut off)
As soon as one window shows this issue, every other window has the same issues, sometimes missing whole widgets, even if those were created afterwards. The solution is usually to quit the program and reopen it, as it only randomly occurs.
This is how the constructor of most of my windows looks like (the part after Build() varies):
public partial class ErrorSolutionDialog : Gtk.Dialog
{
public ErrorSolutionDialog (string errorMessage, string solutionHint)
{
this.WidthRequest = this.Screen.Width;
this.HeightRequest = this.Screen.Height;
this.Maximize ();
this.Fullscreen ();
this.KeepAbove = true;
this.DestroyWithParent = false;
Build ();
this.ErrorMessage.Markup = "<b><span size='xx-large'>" + errorMessage + "</span></b>";
this.SolutionHint.Text = solutionHint;
}
}
I wouldn't say that the use of the Stetic designer inside Xamarin Studio/Monodevelop is bad, but as any piece of software it certainly has some issues.
Also, the use of any designer in any software environment will tie you to that development platform forever. Finally, the created source code will be hardly maintainable, apart from completely foreign for you.
That's why I always recommend to get rid of the designer. You can follow a Gtk# tutorial such as this one, and you'll find it is easy and rewarding. And you'll have whole and thorough control of your code.
The basics about Gtk# is creating a layout with VBoxes and HBoxes. For example, the following code creates a layout in which you'll have a TreeView and a TextView in a Dialog.
var swWin1 = new Gtk.ScrollWindow();
var swWin2 = new Gtk.ScrollWindow();
// TextView
this.txtView = new Gtk.TextView();
swWin1.AddWithViewport( this.txtView );
// TreeView
this.tvView = new Gtk.TreeView();
swWin2.AddWithViewport( this.tvView );
// Layout
var hBox = new HBox( false, 2 );
hBox.PackStart( swWin1, true, true, 5 );
hBox.PackStart( swWin2, true, true, 5 );
this.VBox.PackStart( hBox, true, true, 5 );
PackStart() is the method doing the magic in order to add a widget to a layout. The booleans tell Gtk to expand the widget. A ScrollWindow adds scrollbars to any widget.
Finally, my advice is for any action, use Gtk.Action, and call its methods CreateMenuItem() and CreateToolItem() in order to create menu entries and toobar buttons, instead of repeating the same code again and again.
Hope this helps.

In coded ui how do you correctly retrieve a browser window that contains an embedded Adobe PDF reader in browser

I'am running across this issue when I'm debugging or running my coded UI automation project, where i get the exception labeled "{"COM object that has been separated from its underlying RCW cannot be used." System.Exception {System.Runtime.InteropServices.InvalidComObjectException}" everytime i come from a browser window that contains a pdf reader embedded in it. This happens every time I retrieve the window and try to click back. It barfs when i perform the back method on it. I've tried different things but none has worked including the playback wait.
var hereIsmypdf = ReturnPDFDoc();
public BrowserWindow ReturnPDFDoc()
{
Playback.Wait(1000);
var myPdFdoc = GlobalVariables.Browser;
return myPdFdoc;
}
hereIsmypdf.Back();
The only way i was able to get around this issue was not to use the BrowserWindow class. I ended up using the WinWindow class and just getting the tab of the window from it. The BrowserWindow class seemed to trigger the exception "COM object that has been separated from its underlying RCW cannot be used." System.Exception {System.Runtime.InteropServices.InvalidComObjectException}" everytime i tried to retrieve it. I hope this helps someone one or maybe someone has a better way to handle this issue.
For the people that voted my question down, i really did try to figure it out. Sorry i wasnt clear about what i was asking the community or couldn't properly articulate what this pain was. I'm sure someone probably is going through the same pain i did and having a hard time articulating whats going on.
Here is my code on what i ended up doing
public WinTabPage ReturnPDFDoc()
{
WinWindow Wnd = new WinWindow();
Wnd.SearchProperties[BrowserWindow.PropertyNames.ClassName] = "IEFrame";
WinTabList tabRoWlist = new WinTabList(Wnd);
tabRoWlist.SearchProperties[WinTabPage.PropertyNames.Name] = "Tab Row";
WinTabPage myTab = new WinTabPage(tabRoWlist);
myTab.SearchConfigurations.Add(SearchConfiguration.AlwaysSearch);
myTab.SearchProperties[WinTabPage.PropertyNames.Name] = "something";
//UITestControlCollection windows = newWin.FindMatchingControls();
return myTab;
}

Categories