Bind to already opened form created using CreateObject - c#

I was wondering if what I am trying to do is possible. I have created a C# class library which invokes a form when called from VBScript using CreateObject.
I have a VBS that passes some data to the Form and once the script is complete, obviously all references are lost. I wanted to know if there is a way for me to connect and use the existing form the next time I call the VBS script again?
Set e = CreateObject("MyObject")
'SendEvents to Form'
'Script ends.. all references lost'
'Script is run again'
Set e = CreateObject("MyObject")
'Is it possible to send events to the existing form, instead of closing it and creating new one?'
*Edit: Currently, I am using my class lib to close the existing form when the script is called again. However, I have a user request to keep it open regardless of how many times the script is called. I am not sure how I can use the existing form for the next time CreateObject is called. Is it possible?

Try it like this
Set e = CreateObject("MyObject")
'SendEvents to Form'
'Script ends.. all references lost'
'Script is run again'
Set e = GetObject(, "MyObject") 'no, the empty parameter is no typo
See http://technet.microsoft.com/en-us/library/ee176980.aspx for more info.

Related

How to click button in MS Access using C# and Office Interop?

I am trying to automate some tasks in MS Access which are involving some button presses. Here are my best guesses so far, but I never find a way to finally execute a click...
using Microsoft.Office.Interop.Access;
Application access = new Application();
access.OpenCurrentDatabase("SomeDatabaseName.accdb");
access.DoCmd.OpenForm("SomeFormName", AcFormView.acNormal);
access.DoCmd.GoToControl("SomeButtonName");
access.DoCmd... // I can go to the control, but how do I click it?
Or maybe there is another approach using the Microsoft.Office.Interop.Access.CommandButton instance?
var form = access.Forms["SomeFormName"];
foreach (var control in form.Controls)
{
if (control is CommandButton button)
{
// I can get the CommandButton, but how do I execute the click procedure?
string onClick = button.OnClick; // it's just this string: "[Event Procedure]"
}
}
access.CloseCurrentDatabase();
access.Quit(AcQuitOption.acQuitSaveNone);
Is this possible using the MS Office Interop assemblies? Or are there any alternatives? Unfortunately, these interop assemblies are very poorly documented.
You can use the CommandBars.ExecuteMso method which executes the control identified by the idMso parameter. This method is useful in cases where there is no object model for a particular command. Works on controls that are built-in buttons, toggleButtons, and splitButtons. On failure it returns E_InvalidArg for an invalid idMso, and E_Fail for controls that are not enabled or not visible. For example:
Application.CommandBars.ExecuteMso("Copy")
If you need to execute non-ribbon controls you may consider using Windows API functions or Accessibility API for that.

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.

Unity Android: NoClassDefFoundError: Can't create Notifications

Edit
I found out, that the requirements for showing a notification consist of setting a content-title, a context-text and a small icon. The last of which I do not do. Unfortunately, I don't know, how to provide a small icon especially in unity.
Original Question
I'm currently trying to show a notification from a unity-instance via android. I want to show the notification, when the user enters a specific gps-area. Thus, the script should run, when the app is paused. That's why I want to use the android-functionality.
With this code, I currently try to show the notification manually:
public void createNotification(){
NotificationManagerCompat nManager = NotificationManagerCompat.from(curContext);
NotificationCompat.Builder builder = new NotificationCompat.Builder(curContext, CHANNEL_ID)
.setContentTitle("Stuff")
.setContentText("MoreStuff")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
nManager.notify(1551, builder.build());
}
The context is stored in a static variable and is set, when calling the method.
The function is called in C# with:
PluginInstance.Call("createNotification");
The PluginInstance works, the function can be called, but I get the error:
AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/core/app/NotificationManagerCompat
I found the solution for my problem: I used the Unity Android Jar-Resolver in which I provided the *Dependencies.xml (Where the * presents the Name of my project). In the *Dependenices.xml I specified: <androidPackage spec="androidx.appcompat:appcompat:1.1.0"> and run through the steps, provided in the Tutorial of the Resolver.
Afterwards, multiple dependencies appeared in my /Assets/Plugin/Android-Folder, which were successfully transferred to the app, when building it.

The new Input System doesn't trigger anything anymore

This post is shamelessly a copy/paste from my post on the Unity Forums : https://forum.unity.com/threads/input-system-doesnt-trigger-anything-anymore.717386/, but Stack Overflow seems more active
TL;DR : InputSystem worked some days ago, don't trigger anything anymore, halp.
I tried the new Input System some days ago, and that's really neat ! I did a lot of stuff, trying to understand the best way to use it, and, in the end, I had a character jumping and moving everywhere, that was cool ! Then, I merged my code in our develop branch and went to bed.
Today, I want to continue my code, but my character doesn't move anymore, Actions are not triggered (even if inputs are detected in debugger) and I really don't know why. Either the code merge overwrote some important settings (I know what you're thinking and yes, the "Active Input Handling" is set on "Both" and I tried only running the preview) or I did something important during my little tests and I didn't realize.
So I decided to try to reproduce my steps on a fresh new project, maybe you guys can help me figure what do I do wrong ?
1/ Create a new 2D project (via the Hub)
2/ Install the latest Package (version 0.9.0)
3/ Click Yes on that message prompt to activate the new Input management in the settings
4/ Restart Unity Editor since it didn't restart even if the message said it would and check the project settings (yes, it's on "Both", and yes, my Scripting Runtime Version is 4.0)
5/ Create a new GameObject and add a PlayerInput on it
6/ Click on "Open Input Settings" and create an "InputSettings" asset
7/ Click on "Create Actions..." to create my ActionMap asset
8/ Create a "TestAction" on my "Player" ActionMap and set it to the key "t"
9/ Create a new Script "TestScript" that contains a OnTestAction() method (that only logs "test") and enables the test map/action (just to be sure) :
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.PlayerInput;
public class TestScript : MonoBehaviour
{
void Start()
{
InputActionMap playerActionMap = GetComponent<PlayerInput>().actions.GetActionMap("Player");
playerActionMap.Enable();
playerActionMap.GetAction("TestAction").Enable(); //Just to be sure
}
public void OnTestAction()
{
Debug.Log("test");
}
}
10/ Pressing "Play" and spamming "T" like a madman to try to display a debug (note that, in the debugger, a User is created, my "t" presses are detected, my TestAction exists and is mapped on the "t" key but no debug is displayed
It's probably a silly problem, but it's driving me crazy, what do I do wrong ? It's even more infuriating that it worked some days ago !
Additional information :
- Switching the Input Management from "Both" to "New Input System (preview) does nothing
- Checking in Update() is my action is enabled returns "True" every frame
- Checking in Update() is my action is triggered returns "False" every frame
- Using action.started/triggered/performed does nothing (I tried also switching to UnityEvent or C# events for this) :
public class TestScript : MonoBehaviour
{
InputAction a;
void Start()
{
InputActionMap playerActionMap = GetComponent<PlayerInput>().actions.GetActionMap("Player");
playerActionMap.Enable();
a = playerActionMap.GetAction("TestAction");
a.Enable(); //Just to be sure
a.started += OnTriggeredTestAction;
a.performed += OnTriggeredTestAction;
a.canceled += OnTriggeredTestAction;
}
public void OnTestAction()
{
Debug.Log("test");
}
public void OnTriggeredTestAction(InputAction.CallbackContext ctx)
{
Debug.Log("test triggered");
}
}
Injecting directly the InputActionReference of my TestAction and using it does nothing
Forcing "Default Control Scheme" and "Default Action Map" does nothing
Using BroadcastMessage or UnityEvents doesn't work
You probably tried to import a new input system package for multiple input devices compatibility. These types of errors are due to conflict between old and new input system packages and are probably resolved in the latest updates.
To resolve this issue, Go to Edit -> Project Settings->Player->Under Other Settings under Configuration is the option Active Input Handling. Select Both. Unity will restart. Now your problem should be solved. You will be able to use old input system packages and the new ones also simultaneously.
Check for rogue users in the input debugger
I was having very similar symptoms (Input System would randomly just stop sending callbacks). When I opened up the input debugger, it was registering the key presses, but the callbacks were never being called in my script.
Restarting Unity didn't help.
Rebooting didn't help.
I also discovered in the input debugger that there were 2 "users" in the input system and (by process of disabling Game Objects in the scene one at a time) discovered that I had accidentally attached another copy of my Input Action Asset to a different Game Object in the scene and that Unity was registering this other object as a 2nd player or "user", which was assigned all the input action bindings I was trying to capture.
The rogue Action Asset was essentially intercepting the actions, preventing the callbacks from being called on the intended script. I don't know if that's your particular issue, but maybe it will help someone else who (like me) has spent hours pouring through forums, looking for a solution to this elusive problem.
An easy way to tell if you have the same problem is to open the input debugger and see if the desired actions are actually mapped to the user of interest.
Screen clip of input debugger:
For me, there was an unexpected User #1 and only one of the users (not the intended one) actually had keys bound to the desired actions
Posting just incase others run into this issue, as this solved my problem. Make sure to call Enable() for it to start routing events.
//Create a and set the reference
private InputControls _inputMapping;
private void Awake() => _inputMapping = new InputControls();
//Route and Un-route events
private void OnEnable() => _inputMapping.Enable();
private void OnDisable() => _inputMapping.Disable();
I don't know if this will work for you but it worked for me and I was having the same issue.
I had created 2 control schemes. Mobile and Pc. Mobile required touch screen and PC required keyboard and Mouse. Doing this made my Mobile input event stop firing. So adding the Gamepad to my Mobile Control scheme allowed the events to fire again.
TLDR. Check your control scheme make sure it allows for the inputs your binding to.
I had a similar problem, reproduced with exactly the steps described in the question.
In my case, I forgot to set control schemes.
The problem was fixed after adding them.
To do so:
Open your Input Action Asset.
Select a control scheme, in the upper left corner. (say, Keyboard) (if you haven't added a control scheme to begin with, your problem may be different than mine)
Go Right Click > Edit Control Scheme.
EditControlScehme Screen Img
Click on the plus sign to add a control scheme to the list.
Add control scheme to the list Screen Img
Select the control scheme you want to add. (in this case, Keyboard)
Select control scheme Screen Img
Should look like this:
Added control scheme Screen Img
You're all set. Save everything and the problem should be fixed.
Play your game and it should work.
As of at least Unity 2020.1.2 and Input System 1.0.0 the input system will randomly stop working correctly. The only fix I'm aware of is restarting Unity.

How do I Programmatically change Connection String un LINQ C# Winforms

This question may be redundant, but i could not totally understand how to do this.
I need to be able to, when the users Run my Winforms app, can search for the instance of SQL if the previous one are not available. I already have the check for the DB existence, and also made a dialog wich search for all the available instance, and bulding the connection string isn't a problem. The point here is that, I need to be able to everytime the users open the app it loads the CN from a external file, and if the external file doesn't exist or the instance isn't available, i can use the app in another instance (asuming, offcourse, that the required DB is in that Instance).
The point is that, i don't know how to Programmatically change Connection String, using LINQ in winforms.
Thanks in advance
You should be to pass the connection string to the DataContext constructor.
var db = new MyDataContext(myconnectionstring);
var someConnectionString = "This is my connection String";
using (var db = new SomeConcreteDataContext(someConnectionString)){
//...Do whatever...
}
A DataContext is created per 'unit of work'.
As ichiban says pass the required connection string into the constructor when creating the DC

Categories