I'm beginer in COM, but write some projects in C#.
I have a Windows Service, COM object written on C# and 2 or more VBScripts to communicate with COM object.
Situation:
En example: VBScript 1 make some operation with COM-object but if I start new VBScript 2 - it create it's own example of COM class and make operations with it.
Question: How can I use both VBScripts with the same instance of COM-class The data from COM class (specified list) should be destroyed only after Service stopping - how can I do it

C# & COM Interoperability
MAttinNHTryAgain
One way to safely share data inside a multithreaded application is to apply the singleton pattern with synchronised access to any shared data.
public class SharedData
{
private SharedData()
{
}
private static SharedData oInstance = new SharedData();
private Object _oSharedObject;
public static Object SharedObject
{
get
{
Object oSharedObject;
Monitor.Enter(oInstance);
oSharedObject = oInstance._oSharedObject;
Monitor.Exit(oInstance);
return oSharedObject;
}
set
{
Monitor.Enter(oInstance);
oInstance._oSharedObject = value;
Monitor.Exit(oInstance);
}
}
}
Your code can then access SharedData.SharedObject and it will be the same object they access across multiple instance of any calling object.
Tpaktop
Ha!
From 1 VBSript - it works, but i have splitted this script on the 2 scripts (on two files) and got nothing. Each script - have it's own instance:
'First script=====================================
Dim oTest1
set oTest1 = CreateObject("ClassLibrary1.Test")
oTest1.SetText("FIRST")
MsgBox("Text FIRST: " & oTest1.GetText())
MsgBox("Text FIRST: " & oTest1.GetText())
=============================================
'Second script==================================
Dim oTest2
set oTest2 = CreateObject("ClassLibrary1.Test")
MsgBox("Text SECOND " & oTest2.GetText())
MsgBox("Text SECOND: " & oTest2.GetText())
=============================================
First I've started First Script and, when shows MassageBox, started Second - And value of oTest2.GetText == Initialised (As defined in constructor). Not "FIRST" as oTest1.SetTest() have initialized from First script (as I need).
Federico Alves
Hey!
That was what I wanted :-). The solution not in the incorrect coding but in incorrect registering (and in small code reviewing)
Radu Calinescu
JDavide
You can not create a reference to the SharedData class as it is has a private constructor. It creates it self and you access it through its static methods and properties.
I get it as you are exposing methods from a class to COM. Maybe somethings like this. Simplified as much as possible.
public class COMExposedClass
{
public object GetSomeSharedDataExposedMethod()
{
return SharedData.SharedObject;
}
}
VBScript 1 creates an instance of COMExposedClass
VBScript 2 created another instance of COMExposedClass
If any of them call the GetSomeSharedDataExposedMethod() method they will both go to the same data in the SharedData as it is existing only 1 for the whole application that is exposing the COM class.
You will not use the same instance of the COMExposedClass but in the inner workings it uses the same data because of how SharedData work using the singleton pattern.
vavkin
I created a class library in VC# Express, I signed it with a key to give it a strong name.
I added a new class SharedData.cs and it looks like this:
using System;
using System.Collections.Generic;
using System.Text;
namespace ClassLibrary1
{
class SharedData
{
private static SharedData instance = new SharedData();
private SharedData()
{
m_strText = "Initialised!";
}
String m_strText;
public static String Text
{
get
{
return instance.m_strText;
}
set
{
instance.m_strText = value;
}
}
}
}
I renamed Class1.cs to Test.cs and it looks like this:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ClassLibrary1
{
[Guid("C36D53BA-CBBA-49C9-B3FB-44D98E3D9FCF")]
public interface ITest
{
String GetText();
void SetText(String strText);
}
[Guid("5F6303AE-6EFA-4EE6-A9DB-6EDDBBE371E9"), ComVisible(true)]
public class Test : ITest
{
public String GetText()
{
return SharedData.Text;
}
public void SetText(String strText)
{
SharedData.Text = strText;
}
}
}
I compiled this project and added the resulting ClassLibrary1.dll to the global assembly cache. Then I registered the dll with "regasm.exe ClassLibrary1.dll" in the command prompt.
I wrote a small vbscript to test it out.
1: Dim oTest1
2: Dim oTest2
3:
4: set oTest1 = CreateObject("ClassLibrary1.Test")
5: MsgBox("Text after init 1: " & oTest1.GetText())
6: oTest1.SetText("Value set from 1")
7: MsgBox("Text after set from 1:" & oTest1.GetText())
8:
9: set oTest2 = CreateObject("ClassLibrary1.Test")
10: MsgBox("Text after init 2 from first instance:" & oTest1.GetText())
11: MsgBox("Text after init 2 from second instance:" & oTest2.GetText())
12: oTest2.SetText("Value set from 2")
13: MsgBox("Text after set 2 from first instance:" & oTest1.GetText())
14: MsgBox("Text after set 2 from second instance:" & oTest2.GetText())
I added the line numbers for explanation.
Line 4 will create first instance of the Test object. Text will be set to "Initialised"
Line 6 will set it to "Value set from 1"
Line 9 will NOT set it to "Initialised" as the SharedData class is not initialised because it can only exist 1
Line 12 will set the text to "Value set from 2"
As you can see both instances report the same text. Changing the text on one instance show up on the other instance as they are sharing the underlying data.
Jaanus Kivi
The SharedData class should be part of the assembly that your COM classes are in. You should not expose it to COM.
Your already existing COM exposes classes and method just need to call SharedData.SharedObject to use the same data no matter what instance of the COM class is calling it. If it is vbscript 1 or 2 does not matter as there will only be one SharedData in the assembly to use.
You will ofcourse need to modify the class to contain what you need.
Nitramsen1
IT is NOT work
. I have a COM class which contain a field with private static of my class. In my class are defined Property same as you written:
public class MyClass
{
private static MyClass instance
public static MyClass Instance
{
//it is without checking of protection
get{ if(instance == null) instance = new MyClass();
return instance;}
}
}
COM class do following:
class COM : ICOM
{
private static MyClass POOL = MyClass.Instance;
.......
}
I have build that, registered by regasm.exe and after I got same behavior - EACH VBScript have its own exemplar of COM class AND instance of MyClass, too
. If I try to create a MyClass by first VBScript and change his parameters by second VBScript - it is not work. I don't understand this behavior.
thecoder141859
Greg Smalter
I misunderstood you, you was clear in what you wanted but I got it wrong.
What I have suggested only works inside one process, that is inside one script file or application.
The COM dll server run in the process that creates it and the SharedData is not shared over processes, just inside 1 process. You need to implement your functionality in a out of process COM exe server. It has been done in .NET and one example is here.
http://blogs.msdn.com/adioltean/archive/2004/06/18/159479.aspx
I hope this helps you further. The singleton pattern is still useful to ensure one instance of shared data with synchronised access so multiple threads can work with the data safely.
Jaime de la Mancha
Do you mean I should to create new class which will implement a COM-class and put it into Service But how I'll should to call it from VBScript
Bugge